البدء
تنقلك هذه الصفحة من الصفر إلى JWT متحقق منه خلال نحو خمس عشرة دقيقة على جهازك. إنها تجربة محلية وليست نشرًا إنتاجيًا: أمر docker run واحد مع تطبيق الهاتف على الشبكة المحلية نفسها، دون TLS أو وكيل عكسي. لوصفات الإنتاج (TLS مباشرة أو compose مع Caddy وLet's Encrypt أو Kubernetes)، راجع deploy/README.md بعد إكمال التجربة.
1. شغّل ZTXBAS
يتوفر ZTXBAS في صورة حاوية موقّعة باسم ghcr.io/corezt/ztxbas. تُوقّع الصورة باستخدام cosign؛ والتحقق اختياري للتجربة، لكنه موصى به قبل أي تثبيت فعلي (انظر deploy/README.md).
ستحتاج أيضًا مرحّل SMTP تستطيع الحاوية الوصول إليه؛ فخطوة التسجيل في القسم الثالث ترسل رابطًا عبر البريد.
حضّر ملف متغيرات البيئة. انسخ المثال المرفق واملأ بعض القيم:
cp env.txt .env
اعثر على عنوان IP المحلي لجهازك (يجب أن يستطيع الهاتف الوصول إليه):
ip -4 addr show | grep -oP '(?<=inet\s)\d+\.\d+\.\d+\.\d+' | grep -v '^127\.'
عدّل .env واضبط:
ZTXBAS_PUBLIC_URL=http://<lan-ip>:8443
ZTXBAS_CONSOLE_LISTEN_ADDR=0.0.0.0:8080
ZTXBAS_ALLOW_INSECURE_CONSOLE=1
ZTXBAS_SMTP_HOST=smtp.example.com
ZTXBAS_SMTP_PORT=587
ZTXBAS_SMTP_USER=your-smtp-user
ZTXBAS_SMTP_PASS=your-smtp-pass
ZTXBAS_SMTP_FROM=ztxbas@yourdomain.com
تُضمّن قيمة ZTXBAS_PUBLIC_URL في كل رابط تسجيل ورمز QR، ولذلك يجب أن تكون عنوانًا يستطيع الهاتف الوصول إليه فعلًا. ولن يعمل عنوان loopback.
يربط ZTXBAS_CONSOLE_LISTEN_ADDR=0.0.0.0:8080 لوحة التحكم داخل الحاوية بجميع الواجهات حتى يصل إليها تعيين منفذ Docker؛ وتبلغ قيمة ZTXBAS_ALLOW_INSECURE_CONSOLE=1 آلية الأمان عند البدء بأن ذلك مقصود. وتظل اللوحة غير مكشوفة للعامة لأن -p 127.0.0.1:8080:8080 في أمر Docker يقيّدها بواجهة loopback على المضيف.
شغّل الحاوية:
docker run --rm --name ztxbas \
--env-file .env \
-p <lan-ip>:8443:8443 \
-p 127.0.0.1:8080:8080 \
-p 9443:9443/udp \
-v ztxbas-data:/var/lib/ztxbas \
--cap-drop ALL --security-opt no-new-privileges \
--read-only --tmpfs /tmp:size=16m \
ghcr.io/corezt/ztxbas:latest
تُستخدم ثلاثة منافذ:
| المنفذ | الارتباط | الغرض |
|---|---|---|
| 8443/tcp | IP الشبكة المحلية | واجهة API للتطبيق المعتمد RP؛ يستدعيها التطبيق/SDK |
| 8080/tcp | Loopback | لوحة إدارة النظام |
| 9443/udp | جميع الواجهات | نقل تطبيق الهاتف؛ انشره مباشرة لأنه بروتوكول إطارات مخصص لا تستطيع وكلاء HTTP تمريره |
تبقى لوحة الإدارة على loopback لأنك تفتحها في متصفح على المضيف نفسه. وإذا كنت تتصل عبر SSH بمضيف بعيد، فأضف -L 8080:localhost:8080 إلى الأمر وافتح http://127.0.0.1:8080 محليًا.
فحص الصحة:
curl -s http://<lan-ip>:8443/health
# {"status":"ok","version":"1.0.0"}
2. سجّل الدخول وأنشئ تطبيقًا
التطبيق هو الطرف المعتمد على المصادقة (RP). يحصل على معرّف وسر HMAC لتوقيع طلبات API.
احصل على كلمة مرور المسؤول الأولية من سجلات الحاوية:
docker logs ztxbas 2>&1 | grep -i breakglass
افتح 127.0.0.1:8080، وسجّل الدخول بتلك الكلمة، وعيّن كلمة صحيحة عند الطلب (كلمة المرور الطارئة تستخدم مرة واحدة).
من اللوحة: Applications → New application، سمّ التطبيق وسيظهر معرّفه وسر HMAC مرة واحدة. احفظهما؛ فلا يمكن استرجاع السر.
هل تفضّل CLI؟ يمكنك تنفيذ الأمر نفسه عبر docker exec:
docker exec ztxbas ztxbas app create "Quickstart App"
# Application created.
# ID: app_a1b2c3d4e5
# Name: Quickstart App
# HMAC secret: 5f6e7d8c9b0a...
3. سجّل أصلًا
الأصل هو scheme://host[:port] الذي يجري تطبيقك المصادقة منه. ويظهر للمستخدم على هاتفه أثناء الموافقة، ليكون مرجعًا لمقاومة التصيد.
أسهل طريقة: افتح التطبيق الذي أنشأته في اللوحة وأضف الأصل (https://app.example.com) مع اسم للعرض مثل Example App. هذا الاسم هو ما يراه المستخدم على هاتفه.
إذا فضّلت التنفيذ برمجيًا، تتولى SDK توقيع HMAC بدلًا منك؛ فالتوقيع اليدوي يحتاج إلى دقة (انظر توقيع HMAC للصيغة الموحّدة).
4. سجّل مستخدمًا وأنشئ تحديًا
اختر لغتك. تنفذ اللغات الثلاث التدفق نفسه: تسجيل المستخدم ← إنشاء التحدي ← الاستعلام عن حالته ← الحصول على JWT متحقق منه.
Go
c, _ := ztxbas.New("http://127.0.0.1:8443", "app_a1b2c3d4e5", "5f6e7d8c9b0a...")
_, _ = c.RegisterUser(ctx, ztxbas.RegisterUserRequest{Email: "alice@example.com"})
ch, _ := c.CreateChallenge(ctx, ztxbas.CreateChallengeRequest{
UserEmail: "alice@example.com",
Origin: "https://app.example.com",
})
claims, _ := c.PollChallenge(ctx, ch.ChallengeID)
fmt.Println(claims.Email, claims.Origin)
Node/TypeScript
const c = new Client("http://127.0.0.1:8443", "app_a1b2c3d4e5", "5f6e7d8c9b0a...");
await c.registerUser({ email: "alice@example.com" });
const ch = await c.createChallenge({
user_email: "alice@example.com",
origin: "https://app.example.com",
});
const claims = await c.pollChallenge(ch.challenge_id);
console.log(claims.email, claims.origin);
Python
c = Client("http://127.0.0.1:8443", "app_a1b2c3d4e5", "5f6e7d8c9b0a...")
c.register_user("alice@example.com")
ch = c.create_challenge("alice@example.com", "https://app.example.com")
claims = c.poll_challenge(ch["challenge_id"])
print(claims.email, claims.origin)
في النشر الفعلي، استبدل http://127.0.0.1:8443 بواجهة TLS لديك (https://ztxbas.example.com).
5. ما الذي حدث؟
- تلقّى المستخدم رسالة تسجيل وثبّت تطبيق مصادقة ZTXBAS وربط هاتفه. يتواصل التطبيق مع خادم ZTXBAS عبر منفذ UDP المكشوف على 9443.
- أرسل استدعاء
create_challengeإشعارًا حيويًا إلى الجهاز يعرضExample App(اسم عرض الأصل). - وافق المستخدم بالبصمة أو الوجه.
- أصدر ZTXBAS رمز JWT بـES256 مرتبطًا بـ
alice@example.comوhttps://app.example.com. - جلبت SDK مفاتيح JWKS من
/.well-known/jwks.jsonوتحققت من التوقيع وأعادت المطالبات.
أمثلة بدء جاهزة للتشغيل
أمثلة متكاملة لكل لغة:
يبلغ كل مثال نحو 30 سطرًا ويستخدم التدفق نفسه الموضح أعلاه.
الخطوات التالية
- افهم أساس أمان ربط الأصل في ربط الأصل.
- انتقل إلى الإنتاج عبر compose مع Caddy أو Kubernetes أو systemd:
deploy/README.md. - قوِّ التثبيت: دليل تقوية الأمان.
- اختر الحزمة: Go SDK أو Node SDK أو Python SDK.