ওভারভিউ
পাসকি রেজিস্ট্রেশনে জড়িত মূল পদক্ষেপগুলির একটি উচ্চ-স্তরের ওভারভিউ এখানে রয়েছে:
- একটি পাসকি তৈরি করার বিকল্পগুলি সংজ্ঞায়িত করুন। সেগুলিকে ক্লায়েন্টের কাছে পাঠান, যাতে আপনি সেগুলিকে আপনার পাসকি তৈরির কলে পাঠাতে পারেন: ওয়েবে WebAuthn API কল
navigator.credentials.create
এবং Android-এcredentialManager.createCredential
৷ ব্যবহারকারী পাসকি তৈরির বিষয়টি নিশ্চিত করার পরে, পাসকি তৈরির কলটি সমাধান করা হয় এবং একটি শংসাপত্রPublicKeyCredential
প্রদান করে। - শংসাপত্র যাচাই করুন এবং এটি সার্ভারে সংরক্ষণ করুন।
নিম্নলিখিত বিভাগগুলি প্রতিটি ধাপের সুনির্দিষ্ট বিষয়গুলিতে ডুব দেয়।
শংসাপত্র তৈরির বিকল্পগুলি তৈরি করুন
সার্ভারে আপনাকে যে প্রথম পদক্ষেপটি নিতে হবে তা হল একটি PublicKeyCredentialCreationOptions
অবজেক্ট তৈরি করা।
এটি করতে, আপনার FIDO সার্ভার-সাইড লাইব্রেরির উপর নির্ভর করুন। এটি সাধারণত একটি ইউটিলিটি ফাংশন অফার করবে যা আপনার জন্য এই বিকল্পগুলি তৈরি করতে পারে। SimpleWebAuthn অফার করে, উদাহরণস্বরূপ, generateRegistrationOptions
.
PublicKeyCredentialCreationOptions
পাসকি তৈরির জন্য প্রয়োজনীয় সবকিছু অন্তর্ভুক্ত করা উচিত: ব্যবহারকারী সম্পর্কে তথ্য, RP সম্পর্কে, এবং আপনি যে শংসাপত্র তৈরি করছেন তার বৈশিষ্ট্যগুলির জন্য একটি কনফিগারেশন। একবার আপনি এই সবগুলিকে সংজ্ঞায়িত করার পরে, আপনার FIDO সার্ভার-সাইড লাইব্রেরির ফাংশনে প্রয়োজন অনুসারে এগুলি পাস করুন যা PublicKeyCredentialCreationOptions
অবজেক্ট তৈরির জন্য দায়ী৷
কিছু PublicKeyCredentialCreationOptions
' ক্ষেত্র ধ্রুবক হতে পারে। অন্যদের গতিশীলভাবে সার্ভারে সংজ্ঞায়িত করা উচিত:
-
rpId
: সার্ভারে RP ID পূরণ করতে, সার্ভার-সাইড ফাংশন বা ভেরিয়েবল ব্যবহার করুন যা আপনাকে আপনার ওয়েব অ্যাপ্লিকেশনের হোস্টনাম দেয়, যেমনexample.com
। -
user.name
এবংuser.displayName
: এই ক্ষেত্রগুলি পূরণ করতে, আপনার সাইন-ইন করা ব্যবহারকারীর সেশনের তথ্য ব্যবহার করুন (বা নতুন ব্যবহারকারীর অ্যাকাউন্টের তথ্য, যদি ব্যবহারকারী সাইনআপে একটি পাসকি তৈরি করে)।user.name
সাধারণত একটি ইমেল ঠিকানা, এবং এটি RP-এর জন্য অনন্য।user.displayName
একটি ব্যবহারকারী-বান্ধব নাম। মনে রাখবেন যে সমস্ত প্ল্যাটফর্মdisplayName
ব্যবহার করবে না। -
user.id
: একটি এলোমেলো, অনন্য স্ট্রিং অ্যাকাউন্ট তৈরি করার সময় তৈরি হয়। এটি স্থায়ী হওয়া উচিত, একটি ব্যবহারকারীর নামের বিপরীতে যা সম্পাদনাযোগ্য হতে পারে। ব্যবহারকারীর আইডি একটি অ্যাকাউন্টকে শনাক্ত করে, তবে এতে কোনো ব্যক্তিগতভাবে শনাক্তযোগ্য তথ্য (PII) থাকা উচিত নয় । আপনার সিস্টেমে সম্ভবত ইতিমধ্যেই একটি ব্যবহারকারী আইডি আছে, তবে প্রয়োজন হলে, এটিকে কোনো PII মুক্ত রাখতে পাসকিগুলির জন্য বিশেষভাবে একটি তৈরি করুন৷ -
excludeCredentials
: পাসকি প্রদানকারীর কাছ থেকে একটি পাসকি নকল প্রতিরোধ করতে বিদ্যমান শংসাপত্রের আইডিগুলির একটি তালিকা৷ এই ক্ষেত্রটি পপুলেট করতে, এই ব্যবহারকারীর জন্য আপনার ডাটাবেসের বিদ্যমান শংসাপত্রগুলি সন্ধান করুন৷ একটি নতুন পাসকি তৈরি প্রতিরোধে বিশদ পর্যালোচনা করুন যদি একটি ইতিমধ্যে বিদ্যমান থাকে । -
challenge
: শংসাপত্র নিবন্ধনের জন্য, চ্যালেঞ্জটি প্রাসঙ্গিক নয় যদি না আপনি প্রত্যয়ন ব্যবহার করেন, একটি পাসকি প্রদানকারীর পরিচয় এবং এটি যে ডেটা নির্গত হয় তা যাচাই করার জন্য একটি আরও উন্নত কৌশল। যাইহোক, এমনকি যদি আপনি প্রত্যয়ন ব্যবহার না করেন, তবুও চ্যালেঞ্জটি একটি প্রয়োজনীয় ক্ষেত্র। সেই ক্ষেত্রে, আপনি সরলতার জন্য এই চ্যালেঞ্জটিকে একক0
এ সেট করতে পারেন। প্রমাণীকরণের জন্য একটি নিরাপদ চ্যালেঞ্জ তৈরি করার নির্দেশাবলী সার্ভার-সাইড পাসকি প্রমাণীকরণে উপলব্ধ।
এনকোডিং এবং ডিকোডিং
PublicKeyCredentialCreationOptions
ক্ষেত্রগুলি অন্তর্ভুক্ত করে যেগুলি ArrayBuffer
s, তাই সেগুলি JSON.stringify()
দ্বারা সমর্থিত নয়। এর মানে হল যে, এই মুহুর্তে, HTTPS এর মাধ্যমে PublicKeyCredentialCreationOptions
প্রদান করার জন্য, কিছু ক্ষেত্র অবশ্যই base64URL
ব্যবহার করে সার্ভারে ম্যানুয়ালি এনকোড করতে হবে এবং তারপর ক্লায়েন্টে ডিকোড করতে হবে।
- সার্ভারে , এনকোডিং এবং ডিকোডিং সাধারণত আপনার FIDO সার্ভার-সাইড লাইব্রেরি দ্বারা যত্ন নেওয়া হয়।
- ক্লায়েন্টে , এনকোডিং এবং ডিকোডিং এই মুহূর্তে ম্যানুয়ালি করা দরকার। ভবিষ্যতে এটি আরও সহজ হবে: JSON হিসাবে বিকল্পগুলিকে
PublicKeyCredentialCreationOptions
এ রূপান্তর করার একটি পদ্ধতি উপলব্ধ হবে৷ Chrome-এ বাস্তবায়নের অবস্থা দেখুন।
উদাহরণ কোড: শংসাপত্র তৈরির বিকল্পগুলি তৈরি করুন
আমরা আমাদের উদাহরণে SimpleWebAuthn লাইব্রেরি ব্যবহার করছি। এখানে, আমরা পাবলিক কী ক্রেডেনশিয়াল অপশন তৈরির কাজটি এর generateRegistrationOptions
ফাংশনে হস্তান্তর করি।
import {
generateRegistrationOptions,
verifyRegistrationResponse,
generateAuthenticationOptions,
verifyAuthenticationResponse
} from '@simplewebauthn/server';
import { isoBase64URL } from '@simplewebauthn/server/helpers';
router.post('/registerRequest', csrfCheck, sessionCheck, async (req, res) => {
const { user } = res.locals;
// Ensure you nest verification function calls in try/catch blocks.
// If something fails, throw an error with a descriptive error message.
// Return that message with an appropriate error code to the client.
try {
// `excludeCredentials` prevents users from re-registering existing
// credentials for a given passkey provider
const excludeCredentials = [];
const credentials = Credentials.findByUserId(user.id);
if (credentials.length > 0) {
for (const cred of credentials) {
excludeCredentials.push({
id: isoBase64URL.toBuffer(cred.id),
type: 'public-key',
transports: cred.transports,
});
}
}
// Generate registration options for WebAuthn create
const options = generateRegistrationOptions({
rpName: process.env.RP_NAME,
rpID: process.env.HOSTNAME,
userID: user.id,
userName: user.username,
userDisplayName: user.displayName || '',
attestationType: 'none',
excludeCredentials,
authenticatorSelection: {
authenticatorAttachment: 'platform',
requireResidentKey: true
},
});
// Keep the challenge in the session
req.session.challenge = options.challenge;
return res.json(options);
} catch (e) {
console.error(e);
return res.status(400).send({ error: e.message });
}
});
পাবলিক কী সংরক্ষণ করুন
যখন navigator.credentials.create
ক্লায়েন্টে সফলভাবে সমাধান করে, তার মানে একটি পাসকি সফলভাবে তৈরি করা হয়েছে। একটি PublicKeyCredential
অবজেক্ট ফেরত দেওয়া হয়।
PublicKeyCredential
অবজেক্টে একটি AuthenticatorAttestationResponse
অবজেক্ট রয়েছে, যা একটি পাসকি তৈরি করার জন্য ক্লায়েন্টের নির্দেশে পাসকি প্রদানকারীর প্রতিক্রিয়া উপস্থাপন করে। এটিতে নতুন শংসাপত্র সম্পর্কে তথ্য রয়েছে যা পরবর্তীতে ব্যবহারকারীকে প্রমাণীকরণের জন্য RP হিসাবে আপনার প্রয়োজন। পরিশিষ্টে AuthenticatorAttestationResponse
সম্পর্কে আরও জানুন : AuthenticatorAttestationResponse
.
সার্ভারে PublicKeyCredential
অবজেক্ট পাঠান। একবার আপনি এটি পেয়ে গেলে, এটি যাচাই করুন।
আপনার FIDO সার্ভার-সাইড লাইব্রেরিতে এই যাচাইকরণের ধাপটি হস্তান্তর করুন। এটি সাধারণত এই উদ্দেশ্যে একটি ইউটিলিটি ফাংশন অফার করবে। SimpleWebAuthn অফার করে, উদাহরণস্বরূপ, verifyRegistrationResponse
. পরিশিষ্টে হুডের নিচে কী ঘটছে তা জানুন: নিবন্ধন প্রতিক্রিয়া যাচাইকরণ ।
একবার যাচাইকরণ সফল হলে, আপনার ডাটাবেসে শংসাপত্রের তথ্য সংরক্ষণ করুন যাতে ব্যবহারকারী পরে সেই শংসাপত্রের সাথে যুক্ত পাসকি দিয়ে প্রমাণীকরণ করতে পারে।
পাসকিগুলির সাথে যুক্ত সর্বজনীন কী শংসাপত্রগুলির জন্য একটি উত্সর্গীকৃত টেবিল ব্যবহার করুন৷ একজন ব্যবহারকারীর শুধুমাত্র একটি পাসওয়ার্ড থাকতে পারে, তবে একাধিক পাসকি থাকতে পারে — উদাহরণস্বরূপ, Apple iCloud Keychain-এর মাধ্যমে সিঙ্ক্রোনাইজ করা একটি পাসকি এবং একটি Google পাসওয়ার্ড ম্যানেজারের মাধ্যমে।
এখানে একটি উদাহরণ স্কিমা রয়েছে যা আপনি শংসাপত্রের তথ্য সংরক্ষণ করতে ব্যবহার করতে পারেন:
- ব্যবহারকারীর টেবিল:
-
user_id
: প্রাথমিক ব্যবহারকারী আইডি। ব্যবহারকারীর জন্য একটি এলোমেলো, অনন্য, স্থায়ী আইডি। আপনার ব্যবহারকারী টেবিলের জন্য এটি একটি প্রাথমিক কী হিসাবে ব্যবহার করুন। -
username
একটি ব্যবহারকারী-সংজ্ঞায়িত ব্যবহারকারীর নাম, সম্ভাব্য সম্পাদনাযোগ্য। -
passkey_user_id
: পাসকি-নির্দিষ্ট PII-মুক্ত ব্যবহারকারী আইডি, আপনার নিবন্ধন বিকল্পগুলিতেuser.id
দ্বারা প্রতিনিধিত্ব করা হয়। যখন ব্যবহারকারী পরবর্তীতে প্রমাণীকরণের চেষ্টা করে, তখন প্রমাণীকরণকারীuserHandle
এ তার প্রমাণীকরণ প্রতিক্রিয়াতে এইpasskey_user_id
উপলব্ধ করবে। আমরা আপনাকে একটি প্রাথমিক কী হিসাবেpasskey_user_id
সেট না করার পরামর্শ দিচ্ছি। প্রাথমিক কীগুলি সিস্টেমে ডি ফ্যাক্টো PII হয়ে যায়, কারণ সেগুলি ব্যাপকভাবে ব্যবহৃত হয়।
-
- সর্বজনীন কী শংসাপত্রের টেবিল:
-
id
: শংসাপত্র আইডি। আপনার সর্বজনীন কী শংসাপত্র টেবিলের জন্য এটি একটি প্রাথমিক কী হিসাবে ব্যবহার করুন৷ -
public_key
: শংসাপত্রের সর্বজনীন কী। -
passkey_user_id
: ব্যবহারকারী টেবিলের সাথে একটি লিঙ্ক স্থাপন করতে এটি একটি বিদেশী কী হিসাবে ব্যবহার করুন। -
backed_up
: একটি পাসকি ব্যাক আপ করা হয় যদি এটি পাসকি প্রদানকারী দ্বারা সিঙ্ক্রোনাইজ করা হয়। ব্যাকআপ স্টেট সংরক্ষণ করা উপকারী যদি আপনি ভবিষ্যতেbacked_up
পাসকি ধারণকারী ব্যবহারকারীদের জন্য পাসওয়ার্ড ফেলে দেওয়ার কথা বিবেচনা করতে চান। আপনিauthenticatorData
ডেটাতে ফ্ল্যাগগুলি পরীক্ষা করে পাসকিটি ব্যাক আপ করা হয়েছে কিনা তা পরীক্ষা করতে পারেন, অথবা একটি FIDO সার্ভার-সাইড লাইব্রেরি বৈশিষ্ট্য ব্যবহার করে যা সাধারণত আপনাকে এই তথ্যে সহজে অ্যাক্সেস দেওয়ার জন্য উপলব্ধ। ব্যাকআপ যোগ্যতা সংরক্ষণ করা সম্ভাব্য ব্যবহারকারীর জিজ্ঞাসার সমাধান করতে সহায়ক হতে পারে। -
name
: ঐচ্ছিকভাবে, শংসাপত্রের জন্য একটি প্রদর্শন নাম ব্যবহারকারীদের শংসাপত্রের কাস্টম নাম দিতে সক্ষম করতে। -
transports
: পরিবহনের একটি অ্যারে। ট্রান্সপোর্ট সংরক্ষণ করা প্রমাণীকরণ ব্যবহারকারীর অভিজ্ঞতার জন্য দরকারী। যখন ট্রান্সপোর্ট উপলব্ধ থাকে, তখন ব্রাউজার সেই অনুযায়ী আচরণ করতে পারে এবং একটি UI প্রদর্শন করতে পারে যা ক্লায়েন্টদের সাথে যোগাযোগের জন্য পাসকি প্রদানকারী ব্যবহার করে পরিবহণের সাথে মেলে- বিশেষ করে পুনরায় প্রমাণীকরণ ব্যবহারের ক্ষেত্রে যেখানেallowCredentials
খালি নেই।
-
পাসকি প্রদানকারীর মতো আইটেম, শংসাপত্র তৈরির সময় এবং সর্বশেষ ব্যবহৃত সময় সহ ব্যবহারকারীর অভিজ্ঞতার উদ্দেশ্যে সংরক্ষণ করতে অন্যান্য তথ্য সহায়ক হতে পারে। পাসকি ইউজার ইন্টারফেস ডিজাইনে আরও পড়ুন।
উদাহরণ কোড: শংসাপত্র সংরক্ষণ করুন
আমরা আমাদের উদাহরণে SimpleWebAuthn লাইব্রেরি ব্যবহার করছি। এখানে, আমরা রেজিস্ট্রেশন প্রতিক্রিয়া যাচাইকরণ এর verifyRegistrationResponse
ফাংশনে হস্তান্তর করি।
import { isoBase64URL } from '@simplewebauthn/server/helpers';
router.post('/registerResponse', csrfCheck, sessionCheck, async (req, res) => {
const expectedChallenge = req.session.challenge;
const expectedOrigin = getOrigin(req.get('User-Agent'));
const expectedRPID = process.env.HOSTNAME;
const response = req.body;
// This sample code is for registering a passkey for an existing,
// signed-in user
// Ensure you nest verification function calls in try/catch blocks.
// If something fails, throw an error with a descriptive error message.
// Return that message with an appropriate error code to the client.
try {
// Verify the credential
const { verified, registrationInfo } = await verifyRegistrationResponse({
response,
expectedChallenge,
expectedOrigin,
expectedRPID,
requireUserVerification: false,
});
if (!verified) {
throw new Error('Verification failed.');
}
const { credentialPublicKey, credentialID } = registrationInfo;
// Existing, signed-in user
const { user } = res.locals;
// Save the credential
await Credentials.update({
id: base64CredentialID,
publicKey: base64PublicKey,
// Optional: set the platform as a default name for the credential
// (example: "Pixel 7")
name: req.useragent.platform,
transports: response.response.transports,
passkey_user_id: user.passkey_user_id,
backed_up: registrationInfo.credentialBackedUp
});
// Kill the challenge for this session
delete req.session.challenge;
return res.json(user);
} catch (e) {
delete req.session.challenge;
console.error(e);
return res.status(400).send({ error: e.message });
}
});
পরিশিষ্ট: AuthenticatorAttestationResponse
AuthenticatorAttestationResponse
এ দুটি গুরুত্বপূর্ণ বস্তু রয়েছে:
-
response.clientDataJSON
হল ক্লায়েন্ট ডেটার একটি JSON সংস্করণ, যা ওয়েবে ব্রাউজার দ্বারা দেখা ডেটা। ক্লায়েন্ট যদি একটি অ্যান্ড্রয়েড অ্যাপ হয় তবে এতে RP মূল, চ্যালেঞ্জ এবংandroidPackageName
রয়েছে। একটি RP হিসাবে,clientDataJSON
পড়ার ফলে আপনিcreate
অনুরোধের সময় ব্রাউজার দেখেছিলেন এমন তথ্যে অ্যাক্সেস দেয়। -
response.attestationObject
এ দুটি তথ্য রয়েছে:-
attestationStatement
যা প্রাসঙ্গিক নয় যদি না আপনি সত্যায়ন ব্যবহার করেন। -
authenticatorData
হল এমন ডেটা যা পাসকি প্রদানকারী দ্বারা দেখা যায়। একটি RP হিসাবে,authenticatorData
পড়া আপনাকে পাসকি প্রদানকারীর দ্বারা দেখা ডেটাতে অ্যাক্সেস দেয় এবংcreate
অনুরোধের সময় ফিরে আসে।
-
authenticatorData
পাবলিক কী শংসাপত্র সম্পর্কে প্রয়োজনীয় তথ্য রয়েছে যা নতুন তৈরি পাসকির সাথে যুক্ত:
- সর্বজনীন কী শংসাপত্র নিজেই, এবং এটির জন্য একটি অনন্য শংসাপত্র আইডি।
- শংসাপত্রের সাথে যুক্ত RP ID।
- ফ্ল্যাগ যা ব্যবহারকারীর অবস্থা বর্ণনা করে যখন পাসকি তৈরি করা হয়েছিল: একজন ব্যবহারকারী আসলে উপস্থিত ছিল কিনা এবং ব্যবহারকারী সফলভাবে যাচাই করা হয়েছে কিনা (
userVerification
দেখুন)। - AAGUID , যা পাসকি প্রদানকারীকে শনাক্ত করে। পাসকি প্রদানকারী প্রদর্শন করা আপনার ব্যবহারকারীদের জন্য উপযোগী হতে পারে, বিশেষ করে যদি তাদের একাধিক পাসকি প্রদানকারীতে আপনার পরিষেবার জন্য একটি পাসকি নিবন্ধিত থাকে।
যদিও authenticatorData
attestationObject
মধ্যে নেস্ট করা হয়েছে, আপনি প্রত্যয়ন ব্যবহার করুন বা না করুন আপনার পাসকি বাস্তবায়নের জন্য এতে থাকা তথ্য প্রয়োজন। authenticatorData
এনকোড করা হয়, এবং একটি বাইনারি বিন্যাসে এনকোড করা ক্ষেত্র রয়েছে। আপনার সার্ভার-সাইড লাইব্রেরি সাধারণত পার্সিং এবং ডিকোডিং পরিচালনা করবে। আপনি যদি একটি সার্ভার-সাইড লাইব্রেরি ব্যবহার না করেন, তাহলে নিজেকে কিছু পার্সিং এবং ডিকোডিং কাজ সার্ভার-সাইড সংরক্ষণ করতে getAuthenticatorData()
ক্লায়েন্ট-সাইড ব্যবহার করার কথা বিবেচনা করুন।
পরিশিষ্ট: নিবন্ধন প্রতিক্রিয়া যাচাইকরণ
হুডের অধীনে, নিবন্ধন প্রতিক্রিয়া যাচাই করার জন্য নিম্নলিখিত চেকগুলি রয়েছে:
- নিশ্চিত করুন যে RP ID আপনার সাইটের সাথে মেলে।
- নিশ্চিত করুন যে অনুরোধের উত্সটি আপনার সাইটের জন্য একটি প্রত্যাশিত উত্স (প্রধান সাইট URL, Android অ্যাপ)৷
- আপনার যদি ব্যবহারকারীর যাচাইকরণের প্রয়োজন হয়, নিশ্চিত করুন যে ব্যবহারকারী যাচাইকরণ পতাকা
authenticatorData.uv
true
। ব্যবহারকারীর উপস্থিতি পতাকাauthenticatorData.up
true
কিনা পরীক্ষা করুন, যেহেতু পাসকিগুলির জন্য ব্যবহারকারীর উপস্থিতি সর্বদা প্রয়োজন । - ক্লায়েন্ট আপনার দেওয়া চ্যালেঞ্জ প্রদান করতে সক্ষম হয়েছে কিনা পরীক্ষা করুন। আপনি যদি প্রত্যয়ন ব্যবহার না করেন তবে এই চেকটি গুরুত্বপূর্ণ নয়। যাইহোক, এই চেকটি বাস্তবায়ন করা একটি সর্বোত্তম অনুশীলন: এটি নিশ্চিত করে যে আপনি যদি ভবিষ্যতে সত্যায়ন ব্যবহার করার সিদ্ধান্ত নেন তাহলে আপনার কোড প্রস্তুত রয়েছে৷
- নিশ্চিত করুন যে ক্রেডেনশিয়াল আইডি এখনও কোনও ব্যবহারকারীর জন্য নিবন্ধিত নয়৷
- যাচাই করুন যে শংসাপত্র তৈরি করতে পাসকি প্রদানকারীর দ্বারা ব্যবহৃত অ্যালগরিদমটি আপনার তালিকাভুক্ত একটি অ্যালগরিদম (
publicKeyCredentialCreationOptions.pubKeyCredParams
এর প্রতিটিalg
ক্ষেত্রে, যা সাধারণত আপনার সার্ভার-সাইড লাইব্রেরির মধ্যে সংজ্ঞায়িত করা হয় এবং আপনার কাছ থেকে দৃশ্যমান নয়)৷ এটি নিশ্চিত করে যে ব্যবহারকারীরা শুধুমাত্র অ্যালগরিদমগুলির সাথে নিবন্ধন করতে পারে যা আপনি অনুমতি দেওয়ার জন্য বেছে নিয়েছেন৷
আরও জানতে, verifyRegistrationResponse
এর জন্য SimpleWebAuthn-এর সোর্স কোড দেখুন বা স্পেসিফিকেশনে যাচাইকরণের সম্পূর্ণ তালিকায় ডুব দিন।