11import { Loggable } from '@lib/logger/decorator/loggable' ;
22import { RedisService } from '@lib/redis' ;
3- import {
4- Injectable ,
5- Logger ,
6- NotFoundException ,
7- UnauthorizedException ,
8- } from '@nestjs/common' ;
3+ import { Injectable , Logger , UnauthorizedException } from '@nestjs/common' ;
94import { ConfigService } from '@nestjs/config' ;
105import { JwtService } from '@nestjs/jwt' ;
116import { User } from '@prisma/client' ;
127import {
138 generateAuthenticationOptions ,
149 verifyAuthenticationResponse ,
1510} from '@simplewebauthn/server' ;
16- import {
17- AuthenticationResponseJSON ,
18- PublicKeyCredentialRequestOptionsJSON ,
19- } from '@simplewebauthn/types' ;
11+ import { AuthenticationResponseJSON } from '@simplewebauthn/types' ;
2012import * as bcrypt from 'bcryptjs' ;
2113import * as crypto from 'crypto' ;
2214import ms , { StringValue } from 'ms' ;
2315
2416import { AuthRepository } from './auth.repository' ;
2517import { LoginDto } from './dto/req.dto' ;
18+ import { PasskeyAuthOptionResDto } from './dto/res.dto' ;
2619import { LoginResultType } from './types/loginResult.type' ;
2720
2821@Injectable ( )
@@ -107,47 +100,30 @@ export class AuthService {
107100 return this . authRepository . findUserByUuid ( uuid ) ;
108101 }
109102
110- async authenticateOptions (
111- email : string ,
112- ) : Promise < PublicKeyCredentialRequestOptionsJSON > {
113- const user = await this . authRepository . findUserByEmail ( email ) ;
114-
115- if ( ! user || user . authenticators . length === 0 ) {
116- throw new NotFoundException ( ) ;
117- }
118-
103+ async authenticateOptions ( ) : Promise < PasskeyAuthOptionResDto > {
119104 const options = await generateAuthenticationOptions ( {
120105 rpID : this . passkeyRpId ,
121- allowCredentials : user . authenticators . map ( ( auth ) => ( {
122- id : auth . credentialId ,
123- type : 'public-key' ,
124- } ) ) ,
125106 } ) ;
107+ const key = crypto . randomUUID ( ) ;
126108
127- await this . redisService . set < string > ( user . uuid , options . challenge , {
109+ await this . redisService . set < string > ( key , options . challenge , {
128110 prefix : this . passkeyPrefix ,
129111 ttl : 10 * 60 ,
130112 } ) ;
131113
132- return options ;
114+ return { key , ... options } ;
133115 }
134116
135117 async verifyAuthentication (
136- email : string ,
118+ key : string ,
137119 response : AuthenticationResponseJSON ,
138120 ) : Promise < LoginResultType > {
139- const user = await this . authRepository . findUserByEmail ( email ) ;
140- if ( ! user ) throw new NotFoundException ( ) ;
141-
142- const expectedChallenge = await this . redisService . getOrThrow < string > (
143- user . uuid ,
144- {
145- prefix : this . passkeyPrefix ,
146- } ,
147- ) ;
121+ const expectedChallenge = await this . redisService . getOrThrow < string > ( key , {
122+ prefix : this . passkeyPrefix ,
123+ } ) ;
148124 if ( ! expectedChallenge ) throw new UnauthorizedException ( ) ;
149125
150- await this . redisService . del ( user . uuid , { prefix : this . passkeyPrefix } ) ;
126+ await this . redisService . del ( key , { prefix : this . passkeyPrefix } ) ;
151127
152128 const authenticator = await this . authRepository . findAuthenticator (
153129 response . id ,
@@ -161,7 +137,6 @@ export class AuthService {
161137 expectedRPID : this . passkeyRpId ,
162138 credential : {
163139 ...authenticator ,
164- id : authenticator . credentialId ,
165140 } ,
166141 requireUserVerification : true ,
167142 } ,
@@ -172,11 +147,11 @@ export class AuthService {
172147 }
173148
174149 await this . authRepository . updatePasskeyCounter (
175- authenticator . credentialId ,
150+ authenticator . id ,
176151 authenticationInfo . newCounter ,
177152 ) ;
178153
179- return this . issueTokens ( user . uuid ) ;
154+ return this . issueTokens ( authenticator . userUuid ) ;
180155 }
181156
182157 /**
0 commit comments