From 72d1cf974af085fbecdd7537e5053e7de287ce86 Mon Sep 17 00:00:00 2001 From: Mirko Mollik Date: Thu, 27 Jun 2024 15:30:29 +0200 Subject: [PATCH] fix: update session check (#73) Signed-off-by: Mirko Mollik --- .../src/app/auth/webauthn/webauthn.service.ts | 23 ++++++++++++++++--- .../oid4vp/dto/submission-request.dto.ts | 2 +- .../app/oid4vc/oid4vp/oid4vp.controller.ts | 18 ++++++++++----- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/apps/holder-backend/src/app/auth/webauthn/webauthn.service.ts b/apps/holder-backend/src/app/auth/webauthn/webauthn.service.ts index e3f9e10e..3851995f 100644 --- a/apps/holder-backend/src/app/auth/webauthn/webauthn.service.ts +++ b/apps/holder-backend/src/app/auth/webauthn/webauthn.service.ts @@ -189,17 +189,20 @@ export class WebauthnService { this.loginSessions.delete(key); } + /** + * Verify the authentication response + */ async verifyAuthenticationResponse( session: string, user: string, body: AuthenticationResponseJSON, expectedOrigin: string ) { - // (Pseudocode) Get `options.challenge` that was saved above const currentOptions: PublicKeyCredentialRequestOptionsJSON = this.getCurrentAuthenticationOptions(session); - // (Pseudocode} Retrieve a passkey from the DB that - // should match the `id` in the returned credential + if (!currentOptions) { + throw new ConflictException('No authentication session found'); + } const passkey: Passkey = await this.getUserPasskey(user, body.id); if (!passkey) { @@ -241,6 +244,11 @@ export class WebauthnService { await this.saveUpdatedCounter(passkey, newCounter); } + /** + * Save the updated counter for a passkey + * @param passkey + * @param newCounter + */ private async saveUpdatedCounter(passkey: Passkey, newCounter: number) { passkey.counter = newCounter; await this.passKeyRepository.save(passkey); @@ -256,6 +264,15 @@ export class WebauthnService { return this.passKeyRepository.findOne({ where: { id, user } }); } + /** + * Check if a user has any keys + */ + hasKeys(user: string) { + return this.passKeyRepository.count({ where: { user } }).then((count) => { + return count > 0; + }); + } + /** * Get all keys for a user * @param sub diff --git a/apps/holder-backend/src/app/oid4vc/oid4vp/dto/submission-request.dto.ts b/apps/holder-backend/src/app/oid4vc/oid4vp/dto/submission-request.dto.ts index f80afdbe..f9f4b27b 100644 --- a/apps/holder-backend/src/app/oid4vc/oid4vp/dto/submission-request.dto.ts +++ b/apps/holder-backend/src/app/oid4vc/oid4vp/dto/submission-request.dto.ts @@ -5,7 +5,7 @@ export class CredentialSelection { } export class SubmissionRequest { - auth: { + auth?: { session: string; response: AuthenticationResponseJSON; }; diff --git a/apps/holder-backend/src/app/oid4vc/oid4vp/oid4vp.controller.ts b/apps/holder-backend/src/app/oid4vc/oid4vp/oid4vp.controller.ts index 736f9a3e..7ca4a68b 100644 --- a/apps/holder-backend/src/app/oid4vc/oid4vp/oid4vp.controller.ts +++ b/apps/holder-backend/src/app/oid4vc/oid4vp/oid4vp.controller.ts @@ -1,5 +1,6 @@ import { Body, + ConflictException, Controller, Delete, Param, @@ -51,12 +52,17 @@ export class Oid4vpController { @Req() req: Request ) { const origin = req.headers.origin; - await this.webauthnService.verifyAuthenticationResponse( - value.auth.session, - user.sub, - value.auth.response, - origin - ); + if (await this.webauthnService.hasKeys(user.sub)) { + if (!value.auth) { + throw new ConflictException('No authentication provided'); + } + await this.webauthnService.verifyAuthenticationResponse( + value.auth.session, + user.sub, + value.auth.response, + origin + ); + } return this.oid4vciService.accept(id, user.sub, value.values); }