Skip to content

Commit

Permalink
fix: Webauthn authenticators now accept 'credentials'
Browse files Browse the repository at this point in the history
OKTA-495012
<<<Jenkins Check-In of Tested SHA: 8bcbbdb for [email protected]>>>
Artifact: okta-auth-js
Files changed count: 6
PR Link: #1199
  • Loading branch information
jaredperreault-okta authored and eng-prod-CI-bot-okta committed May 3, 2022
1 parent da8612f commit fa993ca
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 6.4.4

- [#1199](https://github.com/okta/okta-auth-js/pull/1199) Fixes webauthn enrollment/verification to accept `credentials` object

## 6.4.3

### Fixes
Expand Down
13 changes: 8 additions & 5 deletions lib/idx/authenticator/WebauthnEnrollment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,26 @@ import { Authenticator, Credentials } from './Authenticator';
export interface WebauthnEnrollValues {
clientData?: string;
attestation?: string;
credentials?: Credentials;
}

export class WebauthnEnrollment extends Authenticator<WebauthnEnrollValues> {
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() {
Expand Down
13 changes: 8 additions & 5 deletions lib/idx/authenticator/WebauthnVerification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,27 @@ export interface WebauthnVerificationValues {
clientData?: string;
authenticatorData?: string;
signatureData?: string;
credentials?: Credentials;
}

export class WebauthnVerification extends Authenticator<WebauthnVerificationValues> {
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() {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": true,
"name": "@okta/okta-auth-js",
"description": "The Okta Auth SDK",
"version": "6.4.3",
"version": "6.4.4",
"homepage": "https://github.com/okta/okta-auth-js",
"license": "Apache-2.0",
"main": "build/cjs/index.js",
Expand Down
68 changes: 68 additions & 0 deletions test/spec/idx/authenticator/WebauthnEnrollment.ts
Original file line number Diff line number Diff line change
@@ -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' },
]);
});
});
});
69 changes: 69 additions & 0 deletions test/spec/idx/authenticator/WebauthnVerification.ts
Original file line number Diff line number Diff line change
@@ -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/WebauthnVerification', () => {
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 },
]);
});
});
});

0 comments on commit fa993ca

Please sign in to comment.