123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- import { Dates, Result, UniqueEntityId, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
- import { VerifiedRegistrationResponse, verifyRegistrationResponse } from '@simplewebauthn/server'
- import { FeatureIdentifier } from '@standardnotes/features'
- import { AuthenticatorChallengeRepositoryInterface } from '../../Authenticator/AuthenticatorChallengeRepositoryInterface'
- import { AuthenticatorRepositoryInterface } from '../../Authenticator/AuthenticatorRepositoryInterface'
- import { Authenticator } from '../../Authenticator/Authenticator'
- import { VerifyAuthenticatorRegistrationResponseDTO } from './VerifyAuthenticatorRegistrationResponseDTO'
- import { FeatureServiceInterface } from '../../Feature/FeatureServiceInterface'
- import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
- export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface<UniqueEntityId> {
- constructor(
- private authenticatorRepository: AuthenticatorRepositoryInterface,
- private authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface,
- private relyingPartyId: string,
- private expectedOrigin: string[],
- private requireUserVerification: boolean,
- private userRepository: UserRepositoryInterface,
- private featureService: FeatureServiceInterface,
- ) {}
- async execute(dto: VerifyAuthenticatorRegistrationResponseDTO): Promise<Result<UniqueEntityId>> {
- const userUuidOrError = Uuid.create(dto.userUuid)
- if (userUuidOrError.isFailed()) {
- return Result.fail(`Could not verify authenticator registration response: ${userUuidOrError.getError()}`)
- }
- const userUuid = userUuidOrError.getValue()
- const user = await this.userRepository.findOneByUuid(userUuid)
- if (user === null) {
- return Result.fail('Could not verify authenticator registration response: user not found.')
- }
- const userIsEntitledToU2F = await this.featureService.userIsEntitledToFeature(
- user,
- FeatureIdentifier.UniversalSecondFactor,
- )
- if (!userIsEntitledToU2F) {
- return Result.fail('Could not verify authenticator registration response: user is not entitled to U2F.')
- }
- const authenticatorChallenge = await this.authenticatorChallengeRepository.findByUserUuid(userUuid)
- if (!authenticatorChallenge) {
- return Result.fail('Could not verify authenticator registration response: challenge not found')
- }
- let verification: VerifiedRegistrationResponse
- try {
- verification = await verifyRegistrationResponse({
- response: dto.attestationResponse,
- expectedChallenge: authenticatorChallenge.props.challenge.toString(),
- expectedOrigin: this.expectedOrigin,
- expectedRPID: this.relyingPartyId,
- requireUserVerification: this.requireUserVerification,
- })
- if (!verification.verified) {
- return Result.fail('Could not verify authenticator registration response: verification failed')
- }
- } catch (error) {
- return Result.fail(`Could not verify authenticator registration response: ${(error as Error).message}`)
- }
- if (!verification.registrationInfo) {
- return Result.fail('Could not verify authenticator registration response: registration info not found')
- }
- const authenticatorOrError = Authenticator.create({
- userUuid,
- counter: verification.registrationInfo.counter,
- credentialBackedUp: verification.registrationInfo.credentialBackedUp,
- credentialDeviceType: verification.registrationInfo.credentialDeviceType,
- credentialId: verification.registrationInfo.credentialID,
- credentialPublicKey: verification.registrationInfo.credentialPublicKey,
- dates: Dates.create(new Date(), new Date()).getValue(),
- transports: dto.attestationResponse.response.transports,
- })
- if (authenticatorOrError.isFailed()) {
- return Result.fail(`Could not verify authenticator registration response: ${authenticatorOrError.getError()}`)
- }
- const authenticator = authenticatorOrError.getValue()
- await this.authenticatorRepository.save(authenticator)
- return Result.ok(authenticator.id)
- }
- }
|