| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -11,16 +11,16 @@ import { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					import { REQUEST } from '@nestjs/core'; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					import { JwtService } from '@nestjs/jwt'; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					import { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  GenerateAssertionOptionsOpts, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  GenerateAttestationOptionsOpts, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  VerifiedAssertion, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  VerifiedAttestation, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  VerifyAssertionResponseOpts, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  VerifyAttestationResponseOpts, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  generateAssertionOptions, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  generateAttestationOptions, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  verifyAssertionResponse, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  verifyAttestationResponse | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  GenerateAuthenticationOptionsOpts, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  GenerateRegistrationOptionsOpts, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  VerifiedAuthenticationResponse, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  VerifiedRegistrationResponse, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  VerifyAuthenticationResponseOpts, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  VerifyRegistrationResponseOpts, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  generateAuthenticationOptions, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  generateRegistrationOptions, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  verifyAuthenticationResponse, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  verifyRegistrationResponse | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} from '@simplewebauthn/server'; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					import { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -46,10 +46,10 @@ export class WebAuthService { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    return this.configurationService.get('ROOT_URL'); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  public async generateAttestationOptions() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  public async generateRegistrationOptions() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const user = this.request.user; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const opts: GenerateAttestationOptionsOpts = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const opts: GenerateRegistrationOptionsOpts = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      rpName: 'Ghostfolio', | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      rpID: this.rpID, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      userID: user.id, | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -63,7 +63,7 @@ export class WebAuthService { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const options = generateAttestationOptions(opts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const options = generateRegistrationOptions(opts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    await this.userService.updateUser({ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      data: { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -84,27 +84,27 @@ export class WebAuthService { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const user = this.request.user; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const expectedChallenge = user.authChallenge; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    let verification: VerifiedAttestation; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    let verification: VerifiedRegistrationResponse; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    try { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const opts: VerifyAttestationResponseOpts = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const opts: VerifyRegistrationResponseOpts = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        credential, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        expectedChallenge, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        expectedOrigin: this.expectedOrigin, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        expectedRPID: this.rpID | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      verification = await verifyAttestationResponse(opts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      verification = await verifyRegistrationResponse(opts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } catch (error) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      console.error(error); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      throw new InternalServerErrorException(error.message); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const { verified, attestationInfo } = verification; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const { registrationInfo, verified } = verification; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const devices = await this.deviceService.authDevices({ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      where: { userId: user.id } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (verified && attestationInfo) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const { credentialPublicKey, credentialID, counter } = attestationInfo; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (registrationInfo && verified) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const { counter, credentialID, credentialPublicKey } = registrationInfo; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      let existingDevice = devices.find( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        (device) => device.credentialId === credentialID | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -115,9 +115,9 @@ export class WebAuthService { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					         * Add the returned device to the user's list of devices | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					         */ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        existingDevice = await this.deviceService.createAuthDevice({ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          counter, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          credentialPublicKey, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          credentialId: credentialID, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          counter, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          User: { connect: { id: user.id } } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        }); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      } | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -138,20 +138,20 @@ export class WebAuthService { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      throw new Error('Device not found'); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const opts: GenerateAssertionOptionsOpts = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      timeout: 60000, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const opts: GenerateAuthenticationOptionsOpts = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      allowCredentials: [ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          id: device.credentialId, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          type: 'public-key', | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          transports: ['internal'] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          transports: ['internal'], | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          type: 'public-key' | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      ], | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      userVerification: 'preferred', | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      rpID: this.rpID | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      rpID: this.rpID, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      timeout: 60000, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      userVerification: 'preferred' | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const options = generateAssertionOptions(opts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const options = generateAuthenticationOptions(opts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    await this.userService.updateUser({ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      data: { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -177,29 +177,29 @@ export class WebAuthService { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const user = await this.userService.user({ id: device.userId }); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    let verification: VerifiedAssertion; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    let verification: VerifiedAuthenticationResponse; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    try { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const opts: VerifyAssertionResponseOpts = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      const opts: VerifyAuthenticationResponseOpts = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        credential, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        expectedChallenge: `${user.authChallenge}`, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        expectedOrigin: this.expectedOrigin, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        expectedRPID: this.rpID, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        authenticator: { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          credentialID: device.credentialId, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          credentialPublicKey: device.credentialPublicKey, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          counter: device.counter | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        expectedChallenge: `${user.authChallenge}`, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        expectedOrigin: this.expectedOrigin, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        expectedRPID: this.rpID | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      verification = verifyAssertionResponse(opts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      verification = verifyAuthenticationResponse(opts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } catch (error) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      console.error(error); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      throw new InternalServerErrorException({ error: error.message }); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const { verified, assertionInfo } = verification; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const { verified, authenticationInfo } = verification; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (verified) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      device.counter = assertionInfo.newCounter; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      device.counter = authenticationInfo.newCounter; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      await this.deviceService.updateAuthDevice({ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        data: device, | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |