Passkey در ASP.NET Core 10: مهاجرت امن از رمز عبور بدون قفلکردن کاربر
راهنمای معماری و اجرای Passkey در ASP.NET Core Identity؛ از RP ID، Host Header و State امن تا بازیابی حساب، محدودیت منابع، rollout مرحلهای و آزمون مسیرهای ثبت و ورود.
ورود با Passkey معمولاً در نمایش اولیه بسیار ساده به نظر میرسد: کاربر یک دکمه را میزند، Windows Hello یا قفل زیستی گوشی را تأیید میکند و وارد میشود. پیچیدگی واقعی پشت همین تجربه کوتاه پنهان است؛ دامنهای که Credential به آن متصل میشود، State میان دو درخواست، بازیابی حساب، تعویض دستگاه و سیاست حذف اعتبارنامه همگی بخشی از امنیتاند.
ASP.NET Core 10 این مسیر را برای برنامههای مبتنی بر Identity کوتاهتر کرده است، اما کوتاهشدن کد به معنی حذف تصمیمهای معماری نیست. این راهنما نشان میدهد چگونه Passkey را مرحلهای اضافه کنید، چه کنترلهایی را پیش از Production بسنجید و چرا حذف فوری رمز عبور میتواند کاربر را قفل یا مسیر Recovery را به ضعیفترین حلقه تبدیل کند.
Passkey چیست و چه چیزی نیست؟
Passkey یک Public Key Credential مبتنی بر WebAuthn است. هنگام Registration، Authenticator یک جفت کلید میسازد؛ کلید خصوصی در محیط Authenticator باقی میماند و سرور کلید عمومی و دادههای لازم را ذخیره میکند. هنگام Authentication، سرور Challenge تازه میفرستد و Authenticator پس از تأیید کاربر آن را امضا میکند. سرور امضا را با کلید عمومی میسنجد.
اثر انگشت یا Face ID خود Passkey نیست. اینها روش User Verification برای بازکردن Credential روی دستگاهاند. برنامه وب تصویر چهره یا اثر انگشت را دریافت نمیکند. همچنین Passkey یک Magic Link یا OTP نیست؛ امنیت آن از کلید نامتقارن، Challenge و محدودشدن Credential به Relying Party میآید.
چه چیزی در ASP.NET Core Identity آماده است؟
راهنمای رسمی Passkey در ASP.NET Core Identity سه سناریوی اصلی را معرفی میکند: افزودن Passkey به حساب موجود، ایجاد حساب بدون Password و ورود بدون Password. قالب Blazor Web App نیز اجزای مدیریت و ورود را ارائه میدهد.
محدوده قابلیت را جدی بگیرید. پیادهسازی داخلی برای سناریوهای احراز هویت Identity طراحی شده و جای کتابخانه عمومی WebAuthn برای هر مدل Attestation، سیاست سختافزار سازمانی یا پروتکل سفارشی نیست. طبق مستندات Microsoft، Attestation Statement نیز بهطور پیشفرض اعتبارسنجی نمیشود و Passkey در Identity عامل اصلی ورود است، نه 2FA داخلی آماده.
دو Ceremony که باید کامل بمانند
Registration یا Attestation
سرور Creation Options و یک Challenge یکتا میسازد. مرورگر آن را به Authenticator میدهد، کلید ساخته میشود و پاسخ به سرور بازمیگردد. سرور پاسخ را بررسی و Public Key را به حساب درست متصل میکند. این فرایند دو درخواست دارد؛ اطلاعات میان آن دو همان نقطهای است که پیادهسازی دستساز اغلب آسیبپذیر میشود.
Authentication یا Assertion
سرور Request Options و Challenge تازه میسازد. Authenticator با کلید خصوصی امضا میکند و سرور Assertion را با Public Key ذخیرهشده میسنجد. مشخصات WebAuthn Level 3 این دو Ceremony و نقش مرورگر، Authenticator و Relying Party را تعریف میکند.
Challenge نباید قابلپیشبینی یا قابلاستفاده مجدد باشد. موفقشدن یک امضا نیز کافی نیست؛ Origin، RP ID، User Presence یا User Verification و State درخواست باید با سیاست برنامه تطبیق داده شوند.
RP ID؛ مرز امنیتی پنهان در نام دامنه
Relying Party ID تعیین میکند Credential برای کدام دامنه معتبر است. در ASP.NET Core گزینه ServerDomain این محدوده را صریح میکند. اگر تنظیم نشود، پیادهسازی میتواند از Host Header استفاده کند؛ بنابراین Reverse Proxy و برنامه باید Hostهای مجاز را اعتبارسنجی کنند.
- برای محیط Production، RP ID را صریح و مستند تنظیم کنید.
- دامنه Stage را از Production جدا نگه دارید؛ Credential یک محیط نباید ناخواسته در دیگری کار کند.
- محتوای آپلودی یا غیرقابلاعتماد را زیر دامنهای که در محدوده RP ID است میزبانی نکنید.
- اگر چند Origin مجاز دارید، سیاست Origin را صریح و با آزمون منفی تعریف کنید.
برای نمونه، Credential ثبتشده در دامنه ریشه ممکن است محدوده زیردامنهها را نیز تحت تأثیر قرار دهد. این تصمیم باید با معماری Tenantها، CDN، پنل مدیریت و دامنههای مشتری هماهنگ شود، نه اینکه از روی مقدار Host اولین درخواست حدس زده شود.
HTTPS و Host Header فقط تنظیم زیرساخت نیستند
عملیات Passkey در Production به HTTPS وابسته است. HSTS، پایان درست TLS در Proxy و انتقال معتبر Forwarded Headers باید همراه با برنامه آزموده شوند. اگر برنامه پشت Load Balancer قرار دارد، نباید هر Host ارسالی کاربر را معتبر فرض کند.
در کانتینر، یکسانبودن تنظیمات میان Kestrel، Ingress و DNS اهمیت دارد. اصول تکرارپذیری مطرحشده در راهنمای Docker برای توسعهدهندگان را به احراز هویت گسترش دهید: Configuration دامنه را نسخهبندی کنید، Secret را بیرون Image نگه دارید و Smoke Test را با Host واقعی اجرا کنید.
State ثبتنام را در Hidden Field نگذارید
مستندات Microsoft هشدار میدهد State تولیدشده میان Creation Options و پاسخ Credential باید چهار ویژگی داشته باشد: تمامیت، اتصال به Session و کاربر درخواستکننده، مصرف یکباره و عمر کوتاه. اگر شناسه کاربر داخل Hidden Field یا Storage محافظتنشده باشد، مهاجم میتواند Passkey خود را به حساب دیگری متصل کند.
مسیر پیشنهادی معمولاً استفاده از متدهای SignInManager است؛ این مسیر State موقت را مدیریت میکند. اگر ناچارید IPasskeyHandler را مستقیم فراخوانی کنید، State را روی سرور یا با ASP.NET Core Data Protection محافظت کنید، آن را پیش از مصرف حذف و نتیجه User Entity را با کاربر واردشده مقایسه کنید.
طراحی Recovery پیش از حذف Password
Passkey مقاوم در برابر فیشینگ است، اما کاربر ممکن است دستگاهش را از دست بدهد، Sync Provider را تغییر دهد یا Credential را پاک کند. اگر Recovery فقط یک ایمیل ضعیف باشد، مهاجم مسیر اصلی Passkey را دور میزند. از طرف دیگر، نبود Recovery میتواند صاحب واقعی حساب را قفل کند.
- در شروع، Passkey را به حساب موجود اضافه کنید و روش قبلی را فوراً حذف نکنید.
- ثبت حداقل دو Passkey یا یک Credential پشتیبان را تشویق کنید.
- Recovery Code را یکبار نمایش و ذخیره امن آن را توضیح دهید.
- برای Recovery حساس، Risk Signal، تأخیر، اعلان و بررسی دستگاه قبلی را ترکیب کنید.
- حذف آخرین Passkey را به Re-authentication و یک روش پشتیبان معتبر وابسته کنید.
طبق راهنمای Microsoft، پرچمهای Backup Eligibility و Backup State میتوانند برای درخواست Credential اضافی کمک کنند. این سیگنالها جای سیاست Recovery را نمیگیرند، اما در تشخیص حساب تکنقطهای مفیدند.
Attestation؛ نیاز سازمانی یا پیچیدگی اضافه؟
Attestation میتواند درباره مدل Authenticator اطلاعاتی بدهد، اما اعتبارسنجی زنجیره اعتماد و نگهداری Trust Store ساده نیست. ASP.NET Core Identity بهطور پیشفرض Attestation Statement را validate نمیکند و Microsoft پیشنهاد میکند فقط وقتی نیاز مشخصی برای محدودکردن Authenticator دارید سراغ اعتبارسنجی سفارشی بروید.
برای محصول عمومی، الزام سختافزار خاص میتواند نرخ موفقیت ثبت را کاهش دهد. برای سامانه سازمانی پرریسک، ممکن است AAGUID و فهرست مدلهای مجاز لازم باشد. تصمیم را براساس Threat Model بگیرید، نه تصور اینکه Attestation همیشه امنیت بیشتری بدون هزینه ایجاد میکند.
محدودیت منابع را فراموش نکنید
Endpoint ثبت Passkey میتواند برای پرکردن پایگاه داده یا ایجاد Stateهای موقت فراوان سوءاستفاده شود. راهنمای Microsoft پیشنهاد میکند تعداد Passkey هر کاربر و طول نام نمایشی محدود شود. این کنترلها را با Rate Limit، الزام ورود برای افزودن Credential و Audit تکمیل کنید.
- حداکثر تعداد Credential فعال برای هر حساب؛
- حداکثر طول و Character Policy برای Display Name؛
- Rate Limit جدا برای Creation Options و ثبت نهایی؛
- انقضای کوتاه State و پاکسازی Stateهای ناقص؛
- Audit برای افزودن، تغییرنام و حذف Passkey؛
- اعلان به کاربر پس از تغییر Credentialهای امنیتی.
مهاجرت چهارمرحلهای بدون قفلکردن کاربر
مرحله اول: مشاهده و آمادهسازی
پشتیبانی مرورگر و دستگاه، نرخ استفاده از MFA، تعداد Recovery موفق و شکستهای ورود را اندازه بگیرید. برای انواع کاربر—عمومی، مدیر، پشتیبان و حساب سرویس—سیاست جدا داشته باشید. Passkey برای حساب انسانی است؛ حساب سرویس به Credential ماشین مناسب نیاز دارد.
مرحله دوم: ثبت اختیاری
پس از ورود مطمئن، افزودن Passkey را پیشنهاد دهید. نام قابلفهم مانند «لپتاپ کاری» بگیرید و تاریخ ثبت و آخرین استفاده را نشان دهید. حذف و تغییرنام باید ساده اما محافظتشده باشد.
مرحله سوم: ترجیح Passkey در ورود
Passkey را گزینه نخست رابط کنید و Password را به مسیر جایگزین ببرید. نرخ Success، Cancel، Timeout و بازگشت به Password را براساس Browser و Device بررسی کنید. متن خطا نباید اطلاعات وجود حساب را افشا کند.
مرحله چهارم: Passwordless انتخابی
فقط کاربری که چند Credential یا Recovery قوی دارد وارد حالت بدون Password شود. حذف Password باید تصمیم آگاهانه و قابلبازگشت باشد. برای نقشهای حساس، سیاست جدا و Re-authentication قوی تعریف کنید.
مثال معماری برای برنامه Blazor
راهنمای Blazor Web App نقطه شروع مناسبی برای اجزای رابط و اتصال به Identity است. در معماری Production، جریان را به چند مسئولیت تقسیم کنید: Endpoint تولید Options، Cookie یا State محافظتشده، فراخوانی WebAuthn در مرورگر، Endpoint اعتبارسنجی پاسخ، ذخیره Credential و Audit.
کد Domain باید نتیجهها را شفاف مدل کند: موفقیت، Challenge منقضی، Origin نامعتبر، Credential ناشناخته، User Verification ناموفق و Conflict. الگوهای Result و Pattern Matching که در راهنمای Union Type در C# 15 بررسی شدهاند، برای جلوگیری از تبدیل همه شکستها به Exception عمومی مفیدند.
ماتریس آزمون ضروری
- ثبت روی Authenticator پلتفرم و Security Key در صورت پشتیبانی محصول؛
- ورود روی همان دستگاه و Cross-device Flow؛
- Challenge منقضی، مصرفشده و دستکاریشده؛
- Origin و Host نامعتبر، HTTP و Proxy با Header اشتباه؛
- حذف Credential، آخرین Credential و Credential حساب دیگر؛
- لغو توسط کاربر، Timeout و دستگاه بدون قابلیت لازم؛
- Recovery پس از گمشدن دستگاه و تغییر ایمیل؛
- Rate Limit و سقف تعداد Credential؛
- Accessibility دکمهها، پیام خطا و جریان استفاده با صفحهکلید.
آزمون واحد برای Serialization کافی نیست. Ceremony واقعی به Browser و Authenticator وابسته است؛ حداقل یک مجموعه End-to-End روی سیستمعاملها و مرورگرهای هدف اجرا کنید.
شاخصهای rollout که باید دیده شوند
نرخ ثبت Passkey، Success ورود، زمان کاملشدن، Cancel، Timeout، fallback به Password، تعداد Credential هر حساب و درخواست Recovery را اندازه بگیرید. دادهها را بهصورت Aggregate نگه دارید و از ثبت اطلاعات حساس Credential در Log خودداری کنید.
افزایش ثبت بدون کاهش Recovery یا Support Ticket نشانه بهتری از صرفاً زیادشدن کلیک دکمه است. برای نقشهای حساس، رویداد افزودن یا حذف Passkey باید هشدار و Audit قابلپیگیری داشته باشد.
خطاهای رایج
- فرضکردن اینکه Biometric به سرور ارسال میشود؛
- اعتماد به Host Header بدون Allowlist؛
- قرار دادن State ثبتنام در Hidden Field محافظتنشده؛
- حذف فوری Password بدون Recovery آزمودهشده؛
- نداشتن سقف Credential و Rate Limit؛
- نادیدهگرفتن Origin و زیردامنههای غیرقابلاعتماد؛
- اجرای سفارشی کامل WebAuthn وقتی SignInManager سناریو را پوشش میدهد؛
- ذخیره پاسخ خام یا داده حساس در Logهای عمومی.
چکلیست پیش از Production
- ServerDomain یا RP ID صریح و Hostهای مجاز محدود شدهاند.
- HTTPS، HSTS و Forwarded Headers در مسیر واقعی آزموده شدهاند.
- State دارای Integrity، Session Binding، Expiration و Single-use است.
- مالکیت حساب پیش از ذخیره Credential دوباره بررسی میشود.
- Recovery و حذف آخرین Passkey سیاست روشن دارند.
- سقف تعداد، طول نام و Rate Limit اعمال شدهاند.
- Audit و اعلان تغییر Credential فعالاند.
- ماتریس Browser، Device و Failure Path پاس شده است.
- Rollout مرحلهای، Feature Flag و Rollback آمادهاند.
جمعبندی
Passkey میتواند تجربه ورود را سادهتر و مقاومت در برابر فیشینگ را بیشتر کند، زیرا سرور Secret مشترک Password را نگه نمیدارد و Credential به Relying Party مربوط محدود میشود. اما امنیت نهایی به تمام مسیر وابسته است: دامنه، State، Recovery، مدیریت Credential و Monitoring.
در ASP.NET Core 10 از قابلیت داخلی Identity و الگوی SignInManager شروع کنید. ابتدا ثبت اختیاری، سپس ترجیح Passkey و در پایان Passwordless انتخابی را بسنجید. هر مرحله باید شاخص موفقیت، آزمون منفی و مسیر بازگشت داشته باشد. تکنولوژی ورود وقتی موفق است که هم مهاجم را متوقف کند و هم صاحب واقعی حساب راه امنی برای بازگشت داشته باشد.
اگر میخواهید Passkey را بدون تضعیف بازیابی حساب یا قفلکردن کاربران به سامانه ASP.NET Core خود اضافه کنید، برای ممیزی معماری احراز هویت و طراحی rollout با خانه برنامهنویسان البرز در تماس باشید.