From d18f6ccd32fa97c927781c17659cf7a8e662ee07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Wed, 11 Jan 2023 13:47:13 +0100 Subject: [PATCH] fix(auth): add relying party configuration options --- packages/auth/.env.sample | 4 ++++ packages/auth/src/Bootstrap/Container.ts | 11 ++++++++++- packages/auth/src/Bootstrap/Types.ts | 2 ++ .../auth/src/Domain/Authenticator/RelyingParty.ts | 4 ---- .../GenerateAuthenticatorRegistrationOptions.spec.ts | 7 ++++++- .../GenerateAuthenticatorRegistrationOptions.ts | 7 ++++--- .../VerifyAuthenticatorAuthenticationResponse.spec.ts | 6 +++++- .../VerifyAuthenticatorAuthenticationResponse.ts | 6 +++--- .../VerifyAuthenticatorRegistrationResponse.spec.ts | 6 +++++- .../VerifyAuthenticatorRegistrationResponse.ts | 6 +++--- 10 files changed, 42 insertions(+), 17 deletions(-) delete mode 100644 packages/auth/src/Domain/Authenticator/RelyingParty.ts diff --git a/packages/auth/.env.sample b/packages/auth/.env.sample index 399a562ff..f6660470e 100644 --- a/packages/auth/.env.sample +++ b/packages/auth/.env.sample @@ -67,3 +67,7 @@ VALET_TOKEN_SECRET= VALET_TOKEN_TTL= WEB_SOCKET_CONNECTION_TOKEN_SECRET= + +# (Optional) U2F Setup +U2F_RELYING_PARTY_ID= +U2F_RELYING_PARTY_NAME= diff --git a/packages/auth/src/Bootstrap/Container.ts b/packages/auth/src/Bootstrap/Container.ts index 73e6ad003..4580ff621 100644 --- a/packages/auth/src/Bootstrap/Container.ts +++ b/packages/auth/src/Bootstrap/Container.ts @@ -463,7 +463,12 @@ export class ContainerConfigLoader { container .bind(TYPES.SESSION_TRACE_DAYS_TTL) .toConstantValue(env.get('SESSION_TRACE_DAYS_TTL', true) ? +env.get('SESSION_TRACE_DAYS_TTL', true) : 90) - + container + .bind(TYPES.U2F_RELYING_PARTY_NAME) + .toConstantValue(env.get('U2F_RELYING_PARTY_NAME', true) ?? 'Standard Notes') + container + .bind(TYPES.U2F_RELYING_PARTY_ID) + .toConstantValue(env.get('U2F_RELYING_PARTY_ID', true) ?? 'standardnotes.com') // Services container.bind(TYPES.DeviceDetector).toConstantValue(new UAParser()) container.bind(TYPES.SessionService).to(SessionService) @@ -567,6 +572,8 @@ export class ContainerConfigLoader { new GenerateAuthenticatorRegistrationOptions( container.get(TYPES.AuthenticatorRepository), container.get(TYPES.AuthenticatorChallengeRepository), + container.get(TYPES.U2F_RELYING_PARTY_NAME), + container.get(TYPES.U2F_RELYING_PARTY_ID), ), ) container @@ -575,6 +582,7 @@ export class ContainerConfigLoader { new VerifyAuthenticatorRegistrationResponse( container.get(TYPES.AuthenticatorRepository), container.get(TYPES.AuthenticatorChallengeRepository), + container.get(TYPES.U2F_RELYING_PARTY_ID), ), ) container @@ -591,6 +599,7 @@ export class ContainerConfigLoader { new VerifyAuthenticatorAuthenticationResponse( container.get(TYPES.AuthenticatorRepository), container.get(TYPES.AuthenticatorChallengeRepository), + container.get(TYPES.U2F_RELYING_PARTY_ID), ), ) container diff --git a/packages/auth/src/Bootstrap/Types.ts b/packages/auth/src/Bootstrap/Types.ts index ed6cdb4cb..5a3ea5778 100644 --- a/packages/auth/src/Bootstrap/Types.ts +++ b/packages/auth/src/Bootstrap/Types.ts @@ -94,6 +94,8 @@ const TYPES = { VERSION: Symbol.for('VERSION'), PAYMENTS_SERVER_URL: Symbol.for('PAYMENTS_SERVER_URL'), SESSION_TRACE_DAYS_TTL: Symbol.for('SESSION_TRACE_DAYS_TTL'), + U2F_RELYING_PARTY_ID: Symbol.for('U2F_RELYING_PARTY_ID'), + U2F_RELYING_PARTY_NAME: Symbol.for('U2F_RELYING_PARTY_NAME'), // use cases AuthenticateUser: Symbol.for('AuthenticateUser'), AuthenticateRequest: Symbol.for('AuthenticateRequest'), diff --git a/packages/auth/src/Domain/Authenticator/RelyingParty.ts b/packages/auth/src/Domain/Authenticator/RelyingParty.ts deleted file mode 100644 index b6c41536c..000000000 --- a/packages/auth/src/Domain/Authenticator/RelyingParty.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum RelyingParty { - RP_NAME = 'Standard Notes', - RP_ID = 'standardnotes.com', -} diff --git a/packages/auth/src/Domain/UseCase/GenerateAuthenticatorRegistrationOptions/GenerateAuthenticatorRegistrationOptions.spec.ts b/packages/auth/src/Domain/UseCase/GenerateAuthenticatorRegistrationOptions/GenerateAuthenticatorRegistrationOptions.spec.ts index 0f9d3bbc9..0ae9f5f66 100644 --- a/packages/auth/src/Domain/UseCase/GenerateAuthenticatorRegistrationOptions/GenerateAuthenticatorRegistrationOptions.spec.ts +++ b/packages/auth/src/Domain/UseCase/GenerateAuthenticatorRegistrationOptions/GenerateAuthenticatorRegistrationOptions.spec.ts @@ -11,7 +11,12 @@ describe('GenerateAuthenticatorRegistrationOptions', () => { let authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface const createUseCase = () => - new GenerateAuthenticatorRegistrationOptions(authenticatorRepository, authenticatorChallengeRepository) + new GenerateAuthenticatorRegistrationOptions( + authenticatorRepository, + authenticatorChallengeRepository, + 'Standard Notes', + 'standardnotes.com', + ) beforeEach(() => { const authenticator = Authenticator.create({ diff --git a/packages/auth/src/Domain/UseCase/GenerateAuthenticatorRegistrationOptions/GenerateAuthenticatorRegistrationOptions.ts b/packages/auth/src/Domain/UseCase/GenerateAuthenticatorRegistrationOptions/GenerateAuthenticatorRegistrationOptions.ts index 98aa5275f..12aea2ca2 100644 --- a/packages/auth/src/Domain/UseCase/GenerateAuthenticatorRegistrationOptions/GenerateAuthenticatorRegistrationOptions.ts +++ b/packages/auth/src/Domain/UseCase/GenerateAuthenticatorRegistrationOptions/GenerateAuthenticatorRegistrationOptions.ts @@ -5,12 +5,13 @@ import { GenerateAuthenticatorRegistrationOptionsDTO } from './GenerateAuthentic import { AuthenticatorRepositoryInterface } from '../../Authenticator/AuthenticatorRepositoryInterface' import { AuthenticatorChallengeRepositoryInterface } from '../../Authenticator/AuthenticatorChallengeRepositoryInterface' import { AuthenticatorChallenge } from '../../Authenticator/AuthenticatorChallenge' -import { RelyingParty } from '../../Authenticator/RelyingParty' export class GenerateAuthenticatorRegistrationOptions implements UseCaseInterface> { constructor( private authenticatorRepository: AuthenticatorRepositoryInterface, private authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface, + private relyingPartyName: string, + private relyingPartyId: string, ) {} async execute(dto: GenerateAuthenticatorRegistrationOptionsDTO): Promise>> { @@ -28,8 +29,8 @@ export class GenerateAuthenticatorRegistrationOptions implements UseCaseInterfac const authenticators = await this.authenticatorRepository.findByUserUuid(userUuid) const options = generateRegistrationOptions({ - rpID: RelyingParty.RP_ID, - rpName: RelyingParty.RP_NAME, + rpID: this.relyingPartyId, + rpName: this.relyingPartyName, userID: userUuid.value, userName: username.value, attestationType: 'none', diff --git a/packages/auth/src/Domain/UseCase/VerifyAuthenticatorAuthenticationResponse/VerifyAuthenticatorAuthenticationResponse.spec.ts b/packages/auth/src/Domain/UseCase/VerifyAuthenticatorAuthenticationResponse/VerifyAuthenticatorAuthenticationResponse.spec.ts index eb66eb670..c025a68ed 100644 --- a/packages/auth/src/Domain/UseCase/VerifyAuthenticatorAuthenticationResponse/VerifyAuthenticatorAuthenticationResponse.spec.ts +++ b/packages/auth/src/Domain/UseCase/VerifyAuthenticatorAuthenticationResponse/VerifyAuthenticatorAuthenticationResponse.spec.ts @@ -13,7 +13,11 @@ describe('VerifyAuthenticatorAuthenticationResponse', () => { let authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface const createUseCase = () => - new VerifyAuthenticatorAuthenticationResponse(authenticatorRepository, authenticatorChallengeRepository) + new VerifyAuthenticatorAuthenticationResponse( + authenticatorRepository, + authenticatorChallengeRepository, + 'standardnotes.com', + ) beforeEach(() => { const authenticator = Authenticator.create({ diff --git a/packages/auth/src/Domain/UseCase/VerifyAuthenticatorAuthenticationResponse/VerifyAuthenticatorAuthenticationResponse.ts b/packages/auth/src/Domain/UseCase/VerifyAuthenticatorAuthenticationResponse/VerifyAuthenticatorAuthenticationResponse.ts index 503b4314a..c4f481b05 100644 --- a/packages/auth/src/Domain/UseCase/VerifyAuthenticatorAuthenticationResponse/VerifyAuthenticatorAuthenticationResponse.ts +++ b/packages/auth/src/Domain/UseCase/VerifyAuthenticatorAuthenticationResponse/VerifyAuthenticatorAuthenticationResponse.ts @@ -5,12 +5,12 @@ import { AuthenticatorDevice } from '@simplewebauthn/typescript-types' import { AuthenticatorChallengeRepositoryInterface } from '../../Authenticator/AuthenticatorChallengeRepositoryInterface' import { AuthenticatorRepositoryInterface } from '../../Authenticator/AuthenticatorRepositoryInterface' import { VerifyAuthenticatorAuthenticationResponseDTO } from './VerifyAuthenticatorAuthenticationResponseDTO' -import { RelyingParty } from '../../Authenticator/RelyingParty' export class VerifyAuthenticatorAuthenticationResponse implements UseCaseInterface { constructor( private authenticatorRepository: AuthenticatorRepositoryInterface, private authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface, + private relyingPartyId: string, ) {} async execute(dto: VerifyAuthenticatorAuthenticationResponseDTO): Promise> { @@ -40,8 +40,8 @@ export class VerifyAuthenticatorAuthenticationResponse implements UseCaseInterfa verification = await verifyAuthenticationResponse({ credential: dto.authenticationCredential, expectedChallenge: authenticatorChallenge.props.challenge.toString(), - expectedOrigin: `https://${RelyingParty.RP_ID}`, - expectedRPID: RelyingParty.RP_ID, + expectedOrigin: `https://${this.relyingPartyId}`, + expectedRPID: this.relyingPartyId, authenticator: { counter: authenticator.props.counter, credentialID: authenticator.props.credentialId, diff --git a/packages/auth/src/Domain/UseCase/VerifyAuthenticatorRegistrationResponse/VerifyAuthenticatorRegistrationResponse.spec.ts b/packages/auth/src/Domain/UseCase/VerifyAuthenticatorRegistrationResponse/VerifyAuthenticatorRegistrationResponse.spec.ts index e9bc565bc..a02d55d23 100644 --- a/packages/auth/src/Domain/UseCase/VerifyAuthenticatorRegistrationResponse/VerifyAuthenticatorRegistrationResponse.spec.ts +++ b/packages/auth/src/Domain/UseCase/VerifyAuthenticatorRegistrationResponse/VerifyAuthenticatorRegistrationResponse.spec.ts @@ -13,7 +13,11 @@ describe('VerifyAuthenticatorRegistrationResponse', () => { let authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface const createUseCase = () => - new VerifyAuthenticatorRegistrationResponse(authenticatorRepository, authenticatorChallengeRepository) + new VerifyAuthenticatorRegistrationResponse( + authenticatorRepository, + authenticatorChallengeRepository, + 'standardnotes.com', + ) beforeEach(() => { authenticatorRepository = {} as jest.Mocked diff --git a/packages/auth/src/Domain/UseCase/VerifyAuthenticatorRegistrationResponse/VerifyAuthenticatorRegistrationResponse.ts b/packages/auth/src/Domain/UseCase/VerifyAuthenticatorRegistrationResponse/VerifyAuthenticatorRegistrationResponse.ts index 4ead63f24..a907668fc 100644 --- a/packages/auth/src/Domain/UseCase/VerifyAuthenticatorRegistrationResponse/VerifyAuthenticatorRegistrationResponse.ts +++ b/packages/auth/src/Domain/UseCase/VerifyAuthenticatorRegistrationResponse/VerifyAuthenticatorRegistrationResponse.ts @@ -2,7 +2,6 @@ import { Dates, Result, UseCaseInterface, Uuid, Validator } from '@standardnotes import { VerifiedRegistrationResponse, verifyRegistrationResponse } from '@simplewebauthn/server' import { AuthenticatorChallengeRepositoryInterface } from '../../Authenticator/AuthenticatorChallengeRepositoryInterface' -import { RelyingParty } from '../../Authenticator/RelyingParty' import { AuthenticatorRepositoryInterface } from '../../Authenticator/AuthenticatorRepositoryInterface' import { Authenticator } from '../../Authenticator/Authenticator' import { VerifyAuthenticatorRegistrationResponseDTO } from './VerifyAuthenticatorRegistrationResponseDTO' @@ -11,6 +10,7 @@ export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface constructor( private authenticatorRepository: AuthenticatorRepositoryInterface, private authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface, + private relyingPartyId: string, ) {} async execute(dto: VerifyAuthenticatorRegistrationResponseDTO): Promise> { @@ -35,8 +35,8 @@ export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface verification = await verifyRegistrationResponse({ credential: dto.registrationCredential, expectedChallenge: authenticatorChallenge.props.challenge.toString(), - expectedOrigin: `https://${RelyingParty.RP_ID}`, - expectedRPID: RelyingParty.RP_ID, + expectedOrigin: `https://${this.relyingPartyId}`, + expectedRPID: this.relyingPartyId, }) if (!verification.verified) {