diff --git a/lib/idx/authenticator/WebauthnEnrollment.ts b/lib/idx/authenticator/WebauthnEnrollment.ts index 76a4c0ea6..5b5c04a31 100644 --- a/lib/idx/authenticator/WebauthnEnrollment.ts +++ b/lib/idx/authenticator/WebauthnEnrollment.ts @@ -3,23 +3,26 @@ import { Authenticator, Credentials } from './Authenticator'; export interface WebauthnEnrollValues { clientData?: string; attestation?: string; + credentials?: Credentials; } export class WebauthnEnrollment extends Authenticator { canVerify(values: WebauthnEnrollValues) { - const { clientData, attestation } = values; + const { credentials } = values; + const obj = credentials || values; + const { clientData, attestation } = obj; return !!(clientData && attestation); } mapCredentials(values: WebauthnEnrollValues): Credentials | undefined { - const { clientData, attestation } = values; - if (!clientData && !attestation) { + const { credentials, clientData, attestation } = values; + if (!credentials && !clientData && !attestation) { return; } - return { + return credentials || ({ clientData, attestation - }; + }); } getInputs() { diff --git a/lib/idx/authenticator/WebauthnVerification.ts b/lib/idx/authenticator/WebauthnVerification.ts index 10c9c1921..f106cfb69 100644 --- a/lib/idx/authenticator/WebauthnVerification.ts +++ b/lib/idx/authenticator/WebauthnVerification.ts @@ -4,24 +4,27 @@ export interface WebauthnVerificationValues { clientData?: string; authenticatorData?: string; signatureData?: string; + credentials?: Credentials; } export class WebauthnVerification extends Authenticator { canVerify(values: WebauthnVerificationValues) { - const { clientData, authenticatorData, signatureData } = values; + const { credentials } = values; + const obj = credentials || values; + const { clientData, authenticatorData, signatureData } = obj; return !!(clientData && authenticatorData && signatureData); } mapCredentials(values: WebauthnVerificationValues): Credentials | undefined { - const { authenticatorData, clientData, signatureData } = values; - if (!authenticatorData && !clientData && !signatureData) { + const { credentials, authenticatorData, clientData, signatureData } = values; + if (!credentials && !authenticatorData && !clientData && !signatureData) { return; } - return { + return credentials || ({ authenticatorData, clientData, signatureData - }; + }); } getInputs() { diff --git a/test/spec/idx/authenticator/WebauthnEnrollment.ts b/test/spec/idx/authenticator/WebauthnEnrollment.ts new file mode 100644 index 000000000..4c7908dd0 --- /dev/null +++ b/test/spec/idx/authenticator/WebauthnEnrollment.ts @@ -0,0 +1,68 @@ +import { IdxAuthenticator } from '../../../../lib/idx/types'; +import { WebauthnAuthenticatorFactory } from '@okta/test.support/idx'; +import { WebauthnEnrollment } from '../../../../lib/idx/authenticator'; + +describe('idx/authenticator/WebauthnEnrollment', () => { + let testContext; + beforeEach(() => { + const idxAuthenticator: IdxAuthenticator = WebauthnAuthenticatorFactory.build(); + const authenticator = new WebauthnEnrollment(idxAuthenticator); + testContext = { + idxAuthenticator, + authenticator + }; + }); + + describe('constructor', () => { + it('sets the authenticator on the "meta" property', () => { + const { idxAuthenticator, authenticator } = testContext; + expect(authenticator.meta).toBe(idxAuthenticator); + }); + }); + + describe('canVerify', () => { + it('by default, returns false', () => { + const { authenticator } = testContext; + expect(authenticator.canVerify({ unknownValue: 'foo' })).toBe(false); + }); + it('canVerify using "credentials"', () => { + const { authenticator } = testContext; + expect(authenticator.canVerify({ credentials: { attestation: 'foo', clientData: 'foo' } })).toBe(true); + }); + it('canVerify without using "credentials"', () => { + const { authenticator } = testContext; + expect(authenticator.canVerify({ attestation: 'foo', clientData: 'foo' })).toBe(true); + }); + }); + + describe('mapCredentials', () => { + it('returns undefined by default', () => { + const { authenticator } = testContext; + expect(authenticator.mapCredentials({})).toBe(undefined); + }); + it('returns a credentials object when values passed via credentials', () => { + const { authenticator } = testContext; + expect(authenticator.mapCredentials({ credentials: { attestation: 'foo', clientData: 'foo' } })).toEqual({ + attestation: 'foo', + clientData: 'foo' + }); + }); + it('returns a credentials object when values passed directly', () => { + const { authenticator } = testContext; + expect(authenticator.mapCredentials({ attestation: 'foo', clientData: 'foo' })).toEqual({ + attestation: 'foo', + clientData: 'foo' + }); + }); + }); + + describe('getInputs', () => { + it('returns one input: answer', () => { + const { authenticator } = testContext; + expect(authenticator.getInputs()).toEqual([ + { name: 'clientData', type: 'string', required: true, visible: false, label: 'Client Data' }, + { name: 'attestation', type: 'string', required: true, visible: false, label: 'Attestation' }, + ]); + }); + }); +}); diff --git a/test/spec/idx/authenticator/WebauthnVerification.ts b/test/spec/idx/authenticator/WebauthnVerification.ts new file mode 100644 index 000000000..03c64a4f0 --- /dev/null +++ b/test/spec/idx/authenticator/WebauthnVerification.ts @@ -0,0 +1,69 @@ +import { IdxAuthenticator } from '../../../../lib/idx/types'; +import { WebauthnAuthenticatorFactory } from '@okta/test.support/idx'; +import { WebauthnVerification } from '../../../../lib/idx/authenticator'; + +const VALID_CREDS = { + clientData: 'foo', + authenticatorData: 'foo', + signatureData:'foo', +}; + +describe('idx/authenticator/WebauthnEnrollment', () => { + let testContext; + beforeEach(() => { + const idxAuthenticator: IdxAuthenticator = WebauthnAuthenticatorFactory.build(); + const authenticator = new WebauthnVerification(idxAuthenticator); + testContext = { + idxAuthenticator, + authenticator + }; + }); + + describe('constructor', () => { + it('sets the authenticator on the "meta" property', () => { + const { idxAuthenticator, authenticator } = testContext; + expect(authenticator.meta).toBe(idxAuthenticator); + }); + }); + + describe('canVerify', () => { + it('by default, returns false', () => { + const { authenticator } = testContext; + expect(authenticator.canVerify({ unknownValue: 'foo' })).toBe(false); + }); + it('canVerify using "credentials"', () => { + const { authenticator } = testContext; + expect(authenticator.canVerify({ credentials: {...VALID_CREDS} })).toBe(true); + }); + it('canVerify without using "credentials"', () => { + const { authenticator } = testContext; + expect(authenticator.canVerify({...VALID_CREDS})).toBe(true); + }); + }); + + describe('mapCredentials', () => { + it('returns undefined by default', () => { + const { authenticator } = testContext; + expect(authenticator.mapCredentials({})).toBe(undefined); + }); + it('returns a credentials object when values passed via credentials', () => { + const { authenticator } = testContext; + expect(authenticator.mapCredentials({ credentials: {...VALID_CREDS} })).toEqual({...VALID_CREDS}); + }); + it('returns a credentials object when values passed directly', () => { + const { authenticator } = testContext; + expect(authenticator.mapCredentials({ ...VALID_CREDS })).toEqual({...VALID_CREDS}); + }); + }); + + describe('getInputs', () => { + it('returns one input: answer', () => { + const { authenticator } = testContext; + expect(authenticator.getInputs()).toEqual([ + { name: 'authenticatorData', type: 'string', label: 'Authenticator Data', required: true, visible: false }, + { name: 'clientData', type: 'string', label: 'Client Data', required: true, visible: false }, + { name: 'signatureData', type: 'string', label: 'Signature Data', required: true, visible: false }, + ]); + }); + }); +});