@@ -125,16 +125,106 @@ These options should then be remembered since some values will be needed to veri
125125response generated for these options:
126126
127127``` ts
128+ // The ID of the user's auth session that was created after the user logged in
129+ const sessionID = request .session .id ;
130+
131+ // User data associated with the current auth session
132+ const currentUser: UserModel = await getUserData (sessionID );
133+
128134const regOptions = await generateRegistrationOptions (currentUser );
129135
130- await pseudocodeSaveCurrentRegistrationOptions (currentUser , regOptions );
136+ // Persist the options so we can reference values in them during verification
137+ await pseudocodeSaveRegistrationOptions (sessionID , regOptions );
131138```
132139
133- ` regOptions ` can then be transmitted to the frontend (docs coming soon) as JSON for the frontend
134- to eventually pass them in to ` navigator.credentials.create() ` .
140+ ` regOptions ` can then be transmitted to the frontend as JSON for
141+ {{< link "./frontend.md" >}}the frontend to eventually pass in to
142+ ` navigator.credentials.create() ` .{{< /link >}}
135143
136144## 2. Verify registration responses
137145
146+ Once the frontend has taken the registration options above and fed them into WebAuthn,
147+ and after the user succeeds in creating a passkey with their chosen passkey provider,
148+ then the subsequent registration response returned from the WebAuthn call
149+ will need to be sent to the backend for verification.
150+
151+ As JSON is a popular way to send the response back,
152+ the backend method "` verifyRegistrationResponse() ` " should prepare to accept a value
153+ in the shape of [ ` RegistrationResponseJSON ` ] ( https://w3c.github.io/webauthn/#dictdef-registrationresponsejson ) .
154+
155+ ``` ts
156+ /**
157+ * Check that the WebAuthn registration data represents a well-formed passkey
158+ */
159+ async function verifyRegistrationResponse(
160+ currentUser : UserModel ,
161+ registrationOptions : PublicKeyCredentialCreationOptionsJSON ,
162+ registrationResponse : RegistrationResponseJSON ,
163+ ): VerifiedRegistration {
164+ try {
165+ // TODO: Write basic attestation-less response verification here?
166+ } catch (error ) {
167+ throw new Error (` Couldn't verify registration response ` , { cause: error });
168+ }
169+
170+ return {
171+ passkey: {
172+ id: registrationResponse .id ,
173+ publicKey: new Uint8Array ([... ]),
174+ counter: 0 ,
175+ backupEligible: true ,
176+ backupStatus: true ,
177+ transports: [' internal' , ' hybrid' ],
178+ },
179+ }
180+ }
181+
182+ type VerifiedRegistration = {
183+ passkey: {
184+ id: Base64URLString ;
185+ publicKey: Uint8Array ;
186+ counter: number ;
187+ backupEligible: boolean ;
188+ backupStatus: boolean ;
189+ transports? : AuthenticatorTransport [];
190+ }
191+ };
192+ ```
193+
194+ ``` ts
195+ // The ID of the user's auth session that was created after the user logged in
196+ const sessionID = request .session .id ;
197+
198+ // User data associated with the current auth session
199+ const currentUser: UserModel = await getUserData (sessionID );
200+
201+ // Retrieve registration options for the current attempt to check for expected values
202+ const regOptions: PublicKeyCredentialCreationOptionsJSON =
203+ await pseudocodeRetrieveAndDeleteRegistrationOptions (sessionID );
204+
205+ let passkey;
206+ try {
207+ const verification = await verifyRegistrationResponse (currentUser , regOptions , regResponse );
208+ passkey = verification .passkey ;
209+ // User successfully registered a passkey, continue
210+ } catch (err ) {
211+ console .error (err );
212+ // Something went wrong, notify the user accordingly
213+ }
214+ ```
215+
216+ Assuming successful creation, information about the newly-created passkey
217+ should then get stored as a ` PasskeyModel ` record in the database:
218+
219+ ``` ts
220+ /**
221+ * - Use `currentUser` for the foreign key needed for `PasskeyModel.user`
222+ * - Use `regOptions.user.id` for `PasskeyModel.webauthnUserID`
223+ * - Use the values in `passkey` to populate the remaining `PasskeyModel` fields
224+ */
225+ await pseudocodeSaveNewPasskey (currentUser , regOptions , passkey );
226+ ```
227+
138228## 3. Generate authentication options
139229
140230## 4. Verify authentication responses
0 commit comments