summaryrefslogtreecommitdiffhomepage
path: root/packages/server/src
diff options
context:
space:
mode:
authorMatthew Miller <matthew@millerti.me>2022-07-28 10:15:46 -0700
committerGitHub <noreply@github.com>2022-07-28 10:15:46 -0700
commit9e260901cf3ae69b40f50b7a1fd4ac5388186a08 (patch)
treef7fe58214818bae6bec73a759087cf3d4a53c1a7 /packages/server/src
parent522f00d9ae613ff1f51f0c1aca85a6ae129381c5 (diff)
parent2b9f082fc129566b97ec6f72cf390c25f55647ac (diff)
Merge pull request #232 from MasterKale/linting-catch-up
Run `npm run lint`
Diffstat (limited to 'packages/server/src')
-rw-r--r--packages/server/src/authentication/verifyAuthenticationResponse.test.ts74
-rw-r--r--packages/server/src/helpers/convertCertBufferToPEM.test.ts17
-rw-r--r--packages/server/src/helpers/convertPublicKeyToPEM.test.ts36
-rw-r--r--packages/server/src/helpers/decodeAuthenticatorExtensions.test.ts45
-rw-r--r--packages/server/src/helpers/decodeAuthenticatorExtensions.ts10
-rw-r--r--packages/server/src/helpers/isBase64URLString.test.ts6
-rw-r--r--packages/server/src/helpers/parseAuthenticatorData.ts17
-rw-r--r--packages/server/src/helpers/parseBackupFlags.test.ts2
-rw-r--r--packages/server/src/helpers/parseBackupFlags.ts10
-rw-r--r--packages/server/src/helpers/toHash.test.ts2
-rw-r--r--packages/server/src/helpers/validateCertificatePath.ts6
-rw-r--r--packages/server/src/metadata/verifyAttestationWithMetadata.test.ts43
-rw-r--r--packages/server/src/metadata/verifyAttestationWithMetadata.ts12
-rw-r--r--packages/server/src/registration/verifyRegistrationResponse.test.ts44
-rw-r--r--packages/server/src/registration/verifyRegistrationResponse.ts13
-rw-r--r--packages/server/src/services/metadataService.ts6
16 files changed, 185 insertions, 158 deletions
diff --git a/packages/server/src/authentication/verifyAuthenticationResponse.test.ts b/packages/server/src/authentication/verifyAuthenticationResponse.test.ts
index e5b6667..6f17377 100644
--- a/packages/server/src/authentication/verifyAuthenticationResponse.test.ts
+++ b/packages/server/src/authentication/verifyAuthenticationResponse.test.ts
@@ -263,19 +263,22 @@ test('should throw an error if RP ID not in list of possible RP IDs', async () =
test('should pass verification if custom challenge verifier returns true', () => {
const verification = verifyAuthenticationResponse({
credential: {
- 'id': 'AaIBxnYfL2pDWJmIii6CYgHBruhVvFGHheWamphVioG_TnEXxKA9MW4FWnJh21zsbmRpRJso9i2JmAtWOtXfVd4oXTgYVusXwhWWsA',
- 'rawId': 'AaIBxnYfL2pDWJmIii6CYgHBruhVvFGHheWamphVioG_TnEXxKA9MW4FWnJh21zsbmRpRJso9i2JmAtWOtXfVd4oXTgYVusXwhWWsA',
- 'response': {
- 'authenticatorData': 'SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFYftypQ',
- 'clientDataJSON': 'eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZXlKaFkzUjFZV3hEYUdGc2JHVnVaMlVpT2lKTE0xRjRUMnB1VmtwTWFVZHNibFpGY0RWMllUVlJTbVZOVmxkT1psODNVRmxuZFhSbllrRjBRVlZCSWl3aVlYSmlhWFJ5WVhKNVJHRjBZU0k2SW5OcFoyNU5aVkJzWldGelpTSjkiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjgwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9',
- 'signature': 'MEUCIByFAVGfkoKPEzynp-37BX_HOXSaC6-58-ELjB7BG9opAiEAyD_1mN9YAPrphcwpzK3ym2Xx8EjAapgQ326mKgQ1pW0',
- 'userHandle': 'internalUserId'
+ id: 'AaIBxnYfL2pDWJmIii6CYgHBruhVvFGHheWamphVioG_TnEXxKA9MW4FWnJh21zsbmRpRJso9i2JmAtWOtXfVd4oXTgYVusXwhWWsA',
+ rawId:
+ 'AaIBxnYfL2pDWJmIii6CYgHBruhVvFGHheWamphVioG_TnEXxKA9MW4FWnJh21zsbmRpRJso9i2JmAtWOtXfVd4oXTgYVusXwhWWsA',
+ response: {
+ authenticatorData: 'SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFYftypQ',
+ clientDataJSON:
+ 'eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZXlKaFkzUjFZV3hEYUdGc2JHVnVaMlVpT2lKTE0xRjRUMnB1VmtwTWFVZHNibFpGY0RWMllUVlJTbVZOVmxkT1psODNVRmxuZFhSbllrRjBRVlZCSWl3aVlYSmlhWFJ5WVhKNVJHRjBZU0k2SW5OcFoyNU5aVkJzWldGelpTSjkiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjgwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9',
+ signature:
+ 'MEUCIByFAVGfkoKPEzynp-37BX_HOXSaC6-58-ELjB7BG9opAiEAyD_1mN9YAPrphcwpzK3ym2Xx8EjAapgQ326mKgQ1pW0',
+ userHandle: 'internalUserId',
},
- 'type': 'public-key',
- 'clientExtensionResults': {}
+ type: 'public-key',
+ clientExtensionResults: {},
},
expectedChallenge: (challenge: string) => {
- const parsedChallenge: { actualChallenge: string; arbitraryData: string; } = JSON.parse(
+ const parsedChallenge: { actualChallenge: string; arbitraryData: string } = JSON.parse(
base64url.decode(challenge),
);
return parsedChallenge.actualChallenge === 'K3QxOjnVJLiGlnVEp5va5QJeMVWNf_7PYgutgbAtAUA';
@@ -284,10 +287,10 @@ test('should pass verification if custom challenge verifier returns true', () =>
expectedRPID: 'localhost',
authenticator: {
credentialID: base64url.toBuffer(
- 'AaIBxnYfL2pDWJmIii6CYgHBruhVvFGHheWamphVioG_TnEXxKA9MW4FWnJh21zsbmRpRJso9i2JmAtWOtXfVd4oXTgYVusXwhWWsA'
+ 'AaIBxnYfL2pDWJmIii6CYgHBruhVvFGHheWamphVioG_TnEXxKA9MW4FWnJh21zsbmRpRJso9i2JmAtWOtXfVd4oXTgYVusXwhWWsA',
),
credentialPublicKey: base64url.toBuffer(
- 'pQECAyYgASFYILTrxTUQv3X4DRM6L_pk65FSMebenhCx3RMsTKoBm-AxIlggEf3qk5552QLNSh1T1oQs7_2C2qysDwN4r4fCp52Hsqs'
+ 'pQECAyYgASFYILTrxTUQv3X4DRM6L_pk65FSMebenhCx3RMsTKoBm-AxIlggEf3qk5552QLNSh1T1oQs7_2C2qysDwN4r4fCp52Hsqs',
),
counter: 0,
},
@@ -300,7 +303,7 @@ test('should fail verification if custom challenge verifier returns false', () =
expect(() => {
verifyAuthenticationResponse({
credential: assertionResponse,
- expectedChallenge: (challenge) => challenge === 'willNeverMatch',
+ expectedChallenge: challenge => challenge === 'willNeverMatch',
expectedOrigin: assertionOrigin,
expectedRPID: 'dev.dontneeda.pw',
authenticator: authenticator,
@@ -312,38 +315,47 @@ test('should return authenticator extension output', async () => {
const verification = verifyAuthenticationResponse({
credential: {
response: {
- clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiaVpzVkN6dHJEVzdEMlVfR0hDSWxZS0x3VjJiQ3NCVFJxVlFVbkpYbjlUayIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOmd4N3NxX3B4aHhocklRZEx5ZkcwcHhLd2lKN2hPazJESlE0eHZLZDQzOFEiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZmlkby5leGFtcGxlLmZpZG8yYXBpZXhhbXBsZSJ9",
- authenticatorData:"DXX8xWP9p3nbLjQ-6kiYiHWLeFSdSTpP2-oc2WqjHMSFAAAAAKFvZGV2aWNlUHVibGljS2V5pWNkcGtYTaUBAgMmIAEhWCCZGqvtneQnGp7erYgG-dyW1tzNDEdiU6VRBInsg3m-WyJYIKCXPP3tu3nif-9O50gWc_szElBN3KVDTP0jQx1q0p7aY3NpZ1hHMEUCIElSbNKK72tOYhp9WTbStQSVL8CuIxOk8DV6r_-uqWR0AiEAnVE6yu-wsyx2Wq5v66jClGhe_2P_HL8R7PIQevT-uPhlbm9uY2VAZXNjb3BlQQBmYWFndWlkULk_2WHy5kYvsSKCACJH3ng=",
- signature:"MEYCIQDlRuxY7cYre0sb3T6TovQdfYIUb72cRZYOQv_zS9wN_wIhAOvN-fwjtyIhWRceqJV4SX74-z6oALERbC7ohk8EdVPO",
- userHandle:"b2FPajFxcmM4MWo3QkFFel9RN2lEakh5RVNlU2RLNDF0Sl92eHpQYWV5UQ=="
+ clientDataJSON:
+ 'eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiaVpzVkN6dHJEVzdEMlVfR0hDSWxZS0x3VjJiQ3NCVFJxVlFVbkpYbjlUayIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOmd4N3NxX3B4aHhocklRZEx5ZkcwcHhLd2lKN2hPazJESlE0eHZLZDQzOFEiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZmlkby5leGFtcGxlLmZpZG8yYXBpZXhhbXBsZSJ9',
+ authenticatorData:
+ 'DXX8xWP9p3nbLjQ-6kiYiHWLeFSdSTpP2-oc2WqjHMSFAAAAAKFvZGV2aWNlUHVibGljS2V5pWNkcGtYTaUBAgMmIAEhWCCZGqvtneQnGp7erYgG-dyW1tzNDEdiU6VRBInsg3m-WyJYIKCXPP3tu3nif-9O50gWc_szElBN3KVDTP0jQx1q0p7aY3NpZ1hHMEUCIElSbNKK72tOYhp9WTbStQSVL8CuIxOk8DV6r_-uqWR0AiEAnVE6yu-wsyx2Wq5v66jClGhe_2P_HL8R7PIQevT-uPhlbm9uY2VAZXNjb3BlQQBmYWFndWlkULk_2WHy5kYvsSKCACJH3ng=',
+ signature:
+ 'MEYCIQDlRuxY7cYre0sb3T6TovQdfYIUb72cRZYOQv_zS9wN_wIhAOvN-fwjtyIhWRceqJV4SX74-z6oALERbC7ohk8EdVPO',
+ userHandle: 'b2FPajFxcmM4MWo3QkFFel9RN2lEakh5RVNlU2RLNDF0Sl92eHpQYWV5UQ==',
},
- id:"E_Pko4wN1BXE23S0ftN3eQ",
- rawId:"E_Pko4wN1BXE23S0ftN3eQ",
- type:"public-key",
- clientExtensionResults: {}
+ id: 'E_Pko4wN1BXE23S0ftN3eQ',
+ rawId: 'E_Pko4wN1BXE23S0ftN3eQ',
+ type: 'public-key',
+ clientExtensionResults: {},
},
expectedOrigin: 'android:apk-key-hash:gx7sq_pxhxhrIQdLyfG0pxKwiJ7hOk2DJQ4xvKd438Q',
expectedRPID: 'try-webauthn.appspot.com',
expectedChallenge: 'iZsVCztrDW7D2U_GHCIlYKLwV2bCsBTRqVQUnJXn9Tk',
authenticator: {
credentialID: base64url.toBuffer(
- 'AaIBxnYfL2pDWJmIii6CYgHBruhVvFGHheWamphVioG_TnEXxKA9MW4FWnJh21zsbmRpRJso9i2JmAtWOtXfVd4oXTgYVusXwhWWsA'
+ 'AaIBxnYfL2pDWJmIii6CYgHBruhVvFGHheWamphVioG_TnEXxKA9MW4FWnJh21zsbmRpRJso9i2JmAtWOtXfVd4oXTgYVusXwhWWsA',
),
credentialPublicKey: base64url.toBuffer(
- 'pQECAyYgASFYILTrxTUQv3X4DRM6L_pk65FSMebenhCx3RMsTKoBm-AxIlggEf3qk5552QLNSh1T1oQs7_2C2qysDwN4r4fCp52Hsqs'
+ 'pQECAyYgASFYILTrxTUQv3X4DRM6L_pk65FSMebenhCx3RMsTKoBm-AxIlggEf3qk5552QLNSh1T1oQs7_2C2qysDwN4r4fCp52Hsqs',
),
counter: 0,
- }
+ },
});
expect(verification.authenticationInfo?.authenticatorExtensionResults).toMatchObject({
- 'devicePublicKey': {
- 'dpk': Buffer.from('A5010203262001215820991AABED9DE4271A9EDEAD8806F9DC96D6DCCD0C476253A5510489EC8379BE5B225820A0973CFDEDBB79E27FEF4EE7481673FB3312504DDCA5434CFD23431D6AD29EDA', 'hex'),
- 'sig': Buffer.from('3045022049526CD28AEF6B4E621A7D5936D2B504952FC0AE2313A4F0357AAFFFAEA964740221009D513ACAEFB0B32C765AAE6FEBA8C294685EFF63FF1CBF11ECF2107AF4FEB8F8', 'hex'),
- 'nonce': Buffer.from('', 'hex'),
- 'scope': Buffer.from('00', 'hex'),
- 'aaguid': Buffer.from('B93FD961F2E6462FB12282002247DE78', 'hex')
- }
+ devicePublicKey: {
+ dpk: Buffer.from(
+ 'A5010203262001215820991AABED9DE4271A9EDEAD8806F9DC96D6DCCD0C476253A5510489EC8379BE5B225820A0973CFDEDBB79E27FEF4EE7481673FB3312504DDCA5434CFD23431D6AD29EDA',
+ 'hex',
+ ),
+ sig: Buffer.from(
+ '3045022049526CD28AEF6B4E621A7D5936D2B504952FC0AE2313A4F0357AAFFFAEA964740221009D513ACAEFB0B32C765AAE6FEBA8C294685EFF63FF1CBF11ECF2107AF4FEB8F8',
+ 'hex',
+ ),
+ nonce: Buffer.from('', 'hex'),
+ scope: Buffer.from('00', 'hex'),
+ aaguid: Buffer.from('B93FD961F2E6462FB12282002247DE78', 'hex'),
+ },
});
});
diff --git a/packages/server/src/helpers/convertCertBufferToPEM.test.ts b/packages/server/src/helpers/convertCertBufferToPEM.test.ts
index 5960c25..0bb2549 100644
--- a/packages/server/src/helpers/convertCertBufferToPEM.test.ts
+++ b/packages/server/src/helpers/convertCertBufferToPEM.test.ts
@@ -1,9 +1,10 @@
-import { convertCertBufferToPEM } from "./convertCertBufferToPEM";
+import { convertCertBufferToPEM } from './convertCertBufferToPEM';
test('should return pem when input is base64URLString', () => {
- const input = "Y2VydEJ1ZmZlclN0cmluZyBjZXJ0QnVmZmVyU3RyaW5nIGNlcnRCdWZmZXJTdHJpbmcgY2VydEJ1ZmZlclN0cmluZyBjZXJ0QnVmZmVyU3RyaW5nIGNlcnRCdWZmZXJTdHJpbmcgY2VydEJ1ZmZlclN0cmluZw";
+ const input =
+ 'Y2VydEJ1ZmZlclN0cmluZyBjZXJ0QnVmZmVyU3RyaW5nIGNlcnRCdWZmZXJTdHJpbmcgY2VydEJ1ZmZlclN0cmluZyBjZXJ0QnVmZmVyU3RyaW5nIGNlcnRCdWZmZXJTdHJpbmcgY2VydEJ1ZmZlclN0cmluZw';
const actual = convertCertBufferToPEM(input);
- const actualPemArr = actual.split("\n");
+ const actualPemArr = actual.split('\n');
expect(actual).toEqual(`-----BEGIN CERTIFICATE-----
Y2VydEJ1ZmZlclN0cmluZyBjZXJ0QnVmZmVyU3RyaW5nIGNlcnRCdWZmZXJTdHJp
@@ -12,17 +13,17 @@ dHJpbmcgY2VydEJ1ZmZlclN0cmluZw==
-----END CERTIFICATE-----
`);
- expect(actualPemArr[0]).toEqual("-----BEGIN CERTIFICATE-----");
+ expect(actualPemArr[0]).toEqual('-----BEGIN CERTIFICATE-----');
expect(actualPemArr[1].length).toBeLessThanOrEqual(64);
expect(actualPemArr[2].length).toBeLessThanOrEqual(64);
expect(actualPemArr[3].length).toBeLessThanOrEqual(64);
- expect(actualPemArr[4]).toEqual("-----END CERTIFICATE-----");
+ expect(actualPemArr[4]).toEqual('-----END CERTIFICATE-----');
});
test('should return pem when input is buffer', () => {
const input = Buffer.alloc(128);
const actual = convertCertBufferToPEM(input);
- const actualPemArr = actual.split("\n");
+ const actualPemArr = actual.split('\n');
expect(actual).toEqual(`-----BEGIN CERTIFICATE-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -30,9 +31,9 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
-----END CERTIFICATE-----
`);
- expect(actualPemArr[0]).toEqual("-----BEGIN CERTIFICATE-----");
+ expect(actualPemArr[0]).toEqual('-----BEGIN CERTIFICATE-----');
expect(actualPemArr[1].length).toBeLessThanOrEqual(64);
expect(actualPemArr[2].length).toBeLessThanOrEqual(64);
expect(actualPemArr[3].length).toBeLessThanOrEqual(64);
- expect(actualPemArr[4]).toEqual("-----END CERTIFICATE-----");
+ expect(actualPemArr[4]).toEqual('-----END CERTIFICATE-----');
});
diff --git a/packages/server/src/helpers/convertPublicKeyToPEM.test.ts b/packages/server/src/helpers/convertPublicKeyToPEM.test.ts
index 2c2655f..6a52577 100644
--- a/packages/server/src/helpers/convertPublicKeyToPEM.test.ts
+++ b/packages/server/src/helpers/convertPublicKeyToPEM.test.ts
@@ -1,20 +1,20 @@
-import base64url from "base64url";
-import cbor from "cbor";
-import { COSEKEYS } from "./convertCOSEtoPKCS";
-import { convertPublicKeyToPEM } from "./convertPublicKeyToPEM";
+import base64url from 'base64url';
+import cbor from 'cbor';
+import { COSEKEYS } from './convertCOSEtoPKCS';
+import { convertPublicKeyToPEM } from './convertPublicKeyToPEM';
test('should return pem when input is base64URLString', () => {
const mockCOSEKey = new Map<number, number | Buffer>();
- const x = Buffer.from("gh9MmXjtmcHFesofqWZ6iuxSdAYgoPVvfJqpv1818lo", "base64")
- const y = Buffer.from("3BDZHsNvKUb5VbyGPqcAFf4FGuPhJ2Xy215oWDw_1jc", "base64")
+ const x = Buffer.from('gh9MmXjtmcHFesofqWZ6iuxSdAYgoPVvfJqpv1818lo', 'base64');
+ const y = Buffer.from('3BDZHsNvKUb5VbyGPqcAFf4FGuPhJ2Xy215oWDw_1jc', 'base64');
mockCOSEKey.set(COSEKEYS.kty, 2);
mockCOSEKey.set(COSEKEYS.alg, -7);
mockCOSEKey.set(COSEKEYS.crv, 1);
mockCOSEKey.set(COSEKEYS.x, x);
mockCOSEKey.set(COSEKEYS.y, y);
- jest.spyOn(cbor, "decodeAllSync").mockReturnValueOnce([mockCOSEKey]);
+ jest.spyOn(cbor, 'decodeAllSync').mockReturnValueOnce([mockCOSEKey]);
const input = base64url.toBuffer('test');
const actual = convertPublicKeyToPEM(input);
expect(actual).toEqual(`-----BEGIN PUBLIC KEY-----
@@ -23,19 +23,21 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgh9MmXjtmcHFesofqWZ6iuxSdAYg\noPVvfJqpv1818l
`);
});
-
test('should return pem when input is base64URLString', () => {
const mockCOSEKey = new Map<number, number | Buffer>();
- const n = Buffer.from("0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", "base64")
- const e = Buffer.from("AQAB", "base64")
+ const n = Buffer.from(
+ '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw',
+ 'base64',
+ );
+ const e = Buffer.from('AQAB', 'base64');
mockCOSEKey.set(COSEKEYS.kty, 3);
mockCOSEKey.set(COSEKEYS.alg, -7);
mockCOSEKey.set(COSEKEYS.crv, 1);
mockCOSEKey.set(COSEKEYS.n, n);
mockCOSEKey.set(COSEKEYS.e, e);
- jest.spyOn(cbor, "decodeAllSync").mockReturnValueOnce([mockCOSEKey]);
+ jest.spyOn(cbor, 'decodeAllSync').mockReturnValueOnce([mockCOSEKey]);
const input = base64url.toBuffer('test');
const actual = convertPublicKeyToPEM(input);
expect(actual).toEqual(`-----BEGIN PUBLIC KEY-----
@@ -56,12 +58,12 @@ test('should return pem when input is base64URLString', () => {
mockCOSEKey.set(COSEKEYS.kty, 0);
mockCOSEKey.set(COSEKEYS.alg, -7);
- jest.spyOn(cbor, "decodeAllSync").mockReturnValueOnce([mockCOSEKey]);
+ jest.spyOn(cbor, 'decodeAllSync').mockReturnValueOnce([mockCOSEKey]);
const input = base64url.toBuffer('test');
try {
convertPublicKeyToPEM(input);
- } catch(err) {
- expect((err as Error).message).toEqual("Public key was missing kty");
+ } catch (err) {
+ expect((err as Error).message).toEqual('Public key was missing kty');
}
});
@@ -71,11 +73,11 @@ test('should return pem when input is base64URLString', () => {
mockCOSEKey.set(COSEKEYS.kty, 1);
mockCOSEKey.set(COSEKEYS.alg, -7);
- jest.spyOn(cbor, "decodeAllSync").mockReturnValueOnce([mockCOSEKey]);
+ jest.spyOn(cbor, 'decodeAllSync').mockReturnValueOnce([mockCOSEKey]);
const input = base64url.toBuffer('test');
try {
convertPublicKeyToPEM(input);
- } catch(err) {
- expect((err as Error).message).toEqual("Could not convert public key type 1 to PEM");
+ } catch (err) {
+ expect((err as Error).message).toEqual('Could not convert public key type 1 to PEM');
}
});
diff --git a/packages/server/src/helpers/decodeAuthenticatorExtensions.test.ts b/packages/server/src/helpers/decodeAuthenticatorExtensions.test.ts
index 5c184a8..a9b3642 100644
--- a/packages/server/src/helpers/decodeAuthenticatorExtensions.test.ts
+++ b/packages/server/src/helpers/decodeAuthenticatorExtensions.test.ts
@@ -1,22 +1,31 @@
-import { decodeAuthenticatorExtensions } from "./decodeAuthenticatorExtensions";
+import { decodeAuthenticatorExtensions } from './decodeAuthenticatorExtensions';
test('should decode authenticator extensions', () => {
- const extensions = decodeAuthenticatorExtensions(Buffer.from(
- 'A16F6465766963655075626C69634B6579A56364706B584DA5010203262001215820991A' +
- 'ABED9DE4271A9EDEAD8806F9DC96D6DCCD0C476253A5510489EC8379BE5B225820A0973C' +
- 'FDEDBB79E27FEF4EE7481673FB3312504DDCA5434CFD23431D6AD29EDA63736967584730' +
- '45022100EFB38074BD15B8C82CF09F87FBC6FB3C7169EA4F1806B7E90937374302345B7A' +
- '02202B7113040731A0E727D338D48542863CE65880AA79E5EA740AC8CCD94347988E656E' +
- '6F6E6365406573636F706541006661616775696450000000000000000000000000000000' +
- '00', 'hex'
- ));
+ const extensions = decodeAuthenticatorExtensions(
+ Buffer.from(
+ 'A16F6465766963655075626C69634B6579A56364706B584DA5010203262001215820991A' +
+ 'ABED9DE4271A9EDEAD8806F9DC96D6DCCD0C476253A5510489EC8379BE5B225820A0973C' +
+ 'FDEDBB79E27FEF4EE7481673FB3312504DDCA5434CFD23431D6AD29EDA63736967584730' +
+ '45022100EFB38074BD15B8C82CF09F87FBC6FB3C7169EA4F1806B7E90937374302345B7A' +
+ '02202B7113040731A0E727D338D48542863CE65880AA79E5EA740AC8CCD94347988E656E' +
+ '6F6E6365406573636F706541006661616775696450000000000000000000000000000000' +
+ '00',
+ 'hex',
+ ),
+ );
expect(extensions).toMatchObject({
- "devicePublicKey": {
- "dpk": Buffer.from('A5010203262001215820991AABED9DE4271A9EDEAD8806F9DC96D6DCCD0C476253A5510489EC8379BE5B225820A0973CFDEDBB79E27FEF4EE7481673FB3312504DDCA5434CFD23431D6AD29EDA', 'hex'),
- "sig": Buffer.from('3045022100EFB38074BD15B8C82CF09F87FBC6FB3C7169EA4F1806B7E90937374302345B7A02202B7113040731A0E727D338D48542863CE65880AA79E5EA740AC8CCD94347988E', 'hex'),
- "nonce": Buffer.from('', 'hex'),
- "scope": Buffer.from('00', 'hex'),
- "aaguid": Buffer.from('00000000000000000000000000000000', 'hex')
- }
- })
+ devicePublicKey: {
+ dpk: Buffer.from(
+ 'A5010203262001215820991AABED9DE4271A9EDEAD8806F9DC96D6DCCD0C476253A5510489EC8379BE5B225820A0973CFDEDBB79E27FEF4EE7481673FB3312504DDCA5434CFD23431D6AD29EDA',
+ 'hex',
+ ),
+ sig: Buffer.from(
+ '3045022100EFB38074BD15B8C82CF09F87FBC6FB3C7169EA4F1806B7E90937374302345B7A02202B7113040731A0E727D338D48542863CE65880AA79E5EA740AC8CCD94347988E',
+ 'hex',
+ ),
+ nonce: Buffer.from('', 'hex'),
+ scope: Buffer.from('00', 'hex'),
+ aaguid: Buffer.from('00000000000000000000000000000000', 'hex'),
+ },
+ });
});
diff --git a/packages/server/src/helpers/decodeAuthenticatorExtensions.ts b/packages/server/src/helpers/decodeAuthenticatorExtensions.ts
index a0dc5c2..7723d85 100644
--- a/packages/server/src/helpers/decodeAuthenticatorExtensions.ts
+++ b/packages/server/src/helpers/decodeAuthenticatorExtensions.ts
@@ -6,7 +6,7 @@ import cbor from 'cbor';
* @param extensionData Authenticator Extension Data buffer
*/
export function decodeAuthenticatorExtensions(
- extensionData: Buffer
+ extensionData: Buffer,
): AuthenticationExtensionsAuthenticatorOutputs | undefined {
let toCBOR: AuthenticationExtensionsAuthenticatorOutputs | undefined;
try {
@@ -21,17 +21,17 @@ export function decodeAuthenticatorExtensions(
export type AuthenticationExtensionsAuthenticatorOutputs = {
devicePublicKey?: DevicePublicKeyAuthenticatorOutput;
uvm?: UVMAuthenticatorOutput;
-}
+};
export type DevicePublicKeyAuthenticatorOutput = {
dpk?: Buffer;
scp?: Buffer;
sig?: string;
aaguid?: Buffer;
-}
+};
// TODO: Need to verify this format
// https://w3c.github.io/webauthn/#sctn-uvm-extension.
export type UVMAuthenticatorOutput = {
- uvm?: Buffer[]
-}
+ uvm?: Buffer[];
+};
diff --git a/packages/server/src/helpers/isBase64URLString.test.ts b/packages/server/src/helpers/isBase64URLString.test.ts
index 545ff93..358c420 100644
--- a/packages/server/src/helpers/isBase64URLString.test.ts
+++ b/packages/server/src/helpers/isBase64URLString.test.ts
@@ -1,16 +1,16 @@
import { isBase64URLString } from './isBase64URLString';
test('should return true when input is base64URLString', () => {
- const actual = isBase64URLString("U2ltcGxlV2ViQXV0aG4")
+ const actual = isBase64URLString('U2ltcGxlV2ViQXV0aG4');
expect(actual).toEqual(true);
});
test('should return false when input is not base64URLString', () => {
- const actual = isBase64URLString("U2ltcGxlV2ViQXV0aG4+")
+ const actual = isBase64URLString('U2ltcGxlV2ViQXV0aG4+');
expect(actual).toEqual(false);
});
test('should return false when input is blank', () => {
- const actual = isBase64URLString("")
+ const actual = isBase64URLString('');
expect(actual).toEqual(false);
});
diff --git a/packages/server/src/helpers/parseAuthenticatorData.ts b/packages/server/src/helpers/parseAuthenticatorData.ts
index b130a5e..c2128e0 100644
--- a/packages/server/src/helpers/parseAuthenticatorData.ts
+++ b/packages/server/src/helpers/parseAuthenticatorData.ts
@@ -1,6 +1,9 @@
import cbor from 'cbor';
import { decodeCborFirst } from './decodeCbor';
-import { decodeAuthenticatorExtensions, AuthenticationExtensionsAuthenticatorOutputs } from './decodeAuthenticatorExtensions';
+import {
+ decodeAuthenticatorExtensions,
+ AuthenticationExtensionsAuthenticatorOutputs,
+} from './decodeAuthenticatorExtensions';
/**
* Make sense of the authData buffer contained in an Attestation
@@ -22,12 +25,12 @@ export function parseAuthenticatorData(authData: Buffer): ParsedAuthenticatorDat
// Bit positions can be referenced here:
// https://www.w3.org/TR/webauthn-2/#flags
const flags = {
- up: !!(flagsInt & 1 << 0), // User Presence
- uv: !!(flagsInt & 1 << 2), // User Verified
- be: !!(flagsInt & 1 << 3), // Backup Eligibility
- bs: !!(flagsInt & 1 << 4), // Backup State
- at: !!(flagsInt & 1 << 6), // Attested Credential Data Present
- ed: !!(flagsInt & 1 << 7), // Extension Data Present
+ up: !!(flagsInt & (1 << 0)), // User Presence
+ uv: !!(flagsInt & (1 << 2)), // User Verified
+ be: !!(flagsInt & (1 << 3)), // Backup Eligibility
+ bs: !!(flagsInt & (1 << 4)), // Backup State
+ at: !!(flagsInt & (1 << 6)), // Attested Credential Data Present
+ ed: !!(flagsInt & (1 << 7)), // Extension Data Present
flagsInt,
};
diff --git a/packages/server/src/helpers/parseBackupFlags.test.ts b/packages/server/src/helpers/parseBackupFlags.test.ts
index 3133137..14cab55 100644
--- a/packages/server/src/helpers/parseBackupFlags.test.ts
+++ b/packages/server/src/helpers/parseBackupFlags.test.ts
@@ -15,7 +15,7 @@ test('should throw on single-device cred, backed up', () => {
} catch (err) {
const _err: Error = err as Error;
expect(_err.message).toContain('impossible');
- expect(_err.name).toEqual('InvalidBackupFlags')
+ expect(_err.name).toEqual('InvalidBackupFlags');
}
});
diff --git a/packages/server/src/helpers/parseBackupFlags.ts b/packages/server/src/helpers/parseBackupFlags.ts
index c0a1e99..aab82e8 100644
--- a/packages/server/src/helpers/parseBackupFlags.ts
+++ b/packages/server/src/helpers/parseBackupFlags.ts
@@ -8,9 +8,9 @@ import { CredentialDeviceType } from '@simplewebauthn/typescript-types';
*
* Invalid configurations will raise an `Error`
*/
-export function parseBackupFlags({ be, bs }: { be: boolean, bs: boolean }): {
- credentialDeviceType: CredentialDeviceType,
- credentialBackedUp: boolean,
+export function parseBackupFlags({ be, bs }: { be: boolean; bs: boolean }): {
+ credentialDeviceType: CredentialDeviceType;
+ credentialBackedUp: boolean;
} {
const credentialBackedUp = bs;
let credentialDeviceType: CredentialDeviceType = 'singleDevice';
@@ -21,8 +21,8 @@ export function parseBackupFlags({ be, bs }: { be: boolean, bs: boolean }): {
if (credentialDeviceType === 'singleDevice' && credentialBackedUp) {
throw new InvalidBackupFlags(
- 'Single-device credential indicated that it was backed up, which should be impossible.'
- )
+ 'Single-device credential indicated that it was backed up, which should be impossible.',
+ );
}
return { credentialDeviceType, credentialBackedUp };
diff --git a/packages/server/src/helpers/toHash.test.ts b/packages/server/src/helpers/toHash.test.ts
index 86c9142..df0c50d 100644
--- a/packages/server/src/helpers/toHash.test.ts
+++ b/packages/server/src/helpers/toHash.test.ts
@@ -1,7 +1,7 @@
import { toHash } from './toHash';
test('should return a buffer of at 32 bytes for input string', () => {
- const hash = toHash("string");
+ const hash = toHash('string');
expect(hash.byteLength).toEqual(32);
});
diff --git a/packages/server/src/helpers/validateCertificatePath.ts b/packages/server/src/helpers/validateCertificatePath.ts
index 11c1689..d98b16b 100644
--- a/packages/server/src/helpers/validateCertificatePath.ts
+++ b/packages/server/src/helpers/validateCertificatePath.ts
@@ -94,15 +94,15 @@ async function _validatePath(certificates: string[]): Promise<boolean> {
if (notBefore > now || notAfter < now) {
if (isLeafCert) {
throw new CertificateNotYetValidOrExpired(
- `Leaf certificate is not yet valid or expired: ${issuerPem}`
+ `Leaf certificate is not yet valid or expired: ${issuerPem}`,
);
} else if (isRootCert) {
throw new CertificateNotYetValidOrExpired(
- `Root certificate is not yet valid or expired: ${issuerPem}`
+ `Root certificate is not yet valid or expired: ${issuerPem}`,
);
} else {
throw new CertificateNotYetValidOrExpired(
- `Intermediate certificate is not yet valid or expired: ${issuerPem}`
+ `Intermediate certificate is not yet valid or expired: ${issuerPem}`,
);
}
}
diff --git a/packages/server/src/metadata/verifyAttestationWithMetadata.test.ts b/packages/server/src/metadata/verifyAttestationWithMetadata.test.ts
index 57f8aa7..1af8c14 100644
--- a/packages/server/src/metadata/verifyAttestationWithMetadata.test.ts
+++ b/packages/server/src/metadata/verifyAttestationWithMetadata.test.ts
@@ -5,46 +5,47 @@ import { MetadataStatement } from '../metadata/mdsTypes';
test('should verify attestation with metadata (android-safetynet)', async () => {
const metadataStatementJSONSafetyNet: MetadataStatement = {
- legalHeader: "https://fidoalliance.org/metadata/metadata-statement-legal-header/",
- aaguid: "b93fd961-f2e6-462f-b122-82002247de78",
- description: "Android Authenticator with SafetyNet Attestation",
+ legalHeader: 'https://fidoalliance.org/metadata/metadata-statement-legal-header/',
+ aaguid: 'b93fd961-f2e6-462f-b122-82002247de78',
+ description: 'Android Authenticator with SafetyNet Attestation',
authenticatorVersion: 1,
- protocolFamily: "fido2",
+ protocolFamily: 'fido2',
schema: 3,
upv: [{ major: 1, minor: 0 }],
- authenticationAlgorithms: ["secp256r1_ecdsa_sha256_raw"],
- publicKeyAlgAndEncodings: ["cose"],
- attestationTypes: ["basic_full"],
+ authenticationAlgorithms: ['secp256r1_ecdsa_sha256_raw'],
+ publicKeyAlgAndEncodings: ['cose'],
+ attestationTypes: ['basic_full'],
userVerificationDetails: [
- [{ userVerificationMethod: "faceprint_internal" }],
- [{ userVerificationMethod: "fingerprint_internal" }],
- [{ userVerificationMethod: "passcode_internal" }],
- [{ userVerificationMethod: "pattern_internal" }]
+ [{ userVerificationMethod: 'faceprint_internal' }],
+ [{ userVerificationMethod: 'fingerprint_internal' }],
+ [{ userVerificationMethod: 'passcode_internal' }],
+ [{ userVerificationMethod: 'pattern_internal' }],
],
- keyProtection: ["hardware", "tee"],
+ keyProtection: ['hardware', 'tee'],
isKeyRestricted: false,
- matcherProtection: ["tee"],
- attachmentHint: ["internal"],
+ matcherProtection: ['tee'],
+ attachmentHint: ['internal'],
tcDisplay: [],
// Truncated from 28 to 1 to reduce test execution time
attestationRootCertificates: [
- "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",
+ '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',
],
- icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB7klEQVR4AaWPP2sUQRiHn5mdvexd/plEcvlDCi1E/EMabUWI9jaKWPoV/A7BQhAbG7t8CCUIKQQLuwhCUBsLBSUmGkLudm9n5nWHzMAego3P8Oy9s8vvfd+jzctPz2Ya+Zdbu48mG0ma8Eh8/bF3yWGGwPvV81d7+9/2lpy3Mrty7jswPPz8Yb20lQJ2iain2w9ok02aLURWstxuiHgknnrEK3GERg9poZ7s3CUxl/dvVfrntmRag9BuICJgrXfHnRvAWyJaDxXB+ezCWqX3t6e6i/ri/E1AkdBoLi/cZrL5pqeHb2yvu9RIUKfiWH95IVmmV6eucK1/j8JMIwRo6jNcX77P2vQ6ZEZ7OXreSFA93rnD3Mx6r7YfTxQKGkN4WP8eW7+bz4Z3eHEE9FFZAJXuliXVyUEfif9ZHINW+BQ5fSc+3oTjztTZRkx4LEhtfh1avBMSIkBrA+JvOAohm1AFgJGRpbOoXS/X1KXgHZE4X1Ssxpt18iYImGJiRFWWKCXkBdiR4L0QUEKamIKxhoQZm6fAdMDVjT7cQwBEYh3DSsl4A+trQTwJbUCsT5P+CodTZtYDmNJYcrEDQSChIMsVzoVQ2kLFMCCQFW4AoDbfbRDI7fIi5aAL41jtVNiQiPUjmUBOgAMCm683/ss/TaVXtx4qKMoAAAAASUVORK5CYII=",
+ icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB7klEQVR4AaWPP2sUQRiHn5mdvexd/plEcvlDCi1E/EMabUWI9jaKWPoV/A7BQhAbG7t8CCUIKQQLuwhCUBsLBSUmGkLudm9n5nWHzMAego3P8Oy9s8vvfd+jzctPz2Ya+Zdbu48mG0ma8Eh8/bF3yWGGwPvV81d7+9/2lpy3Mrty7jswPPz8Yb20lQJ2iain2w9ok02aLURWstxuiHgknnrEK3GERg9poZ7s3CUxl/dvVfrntmRag9BuICJgrXfHnRvAWyJaDxXB+ezCWqX3t6e6i/ri/E1AkdBoLi/cZrL5pqeHb2yvu9RIUKfiWH95IVmmV6eucK1/j8JMIwRo6jNcX77P2vQ6ZEZ7OXreSFA93rnD3Mx6r7YfTxQKGkN4WP8eW7+bz4Z3eHEE9FFZAJXuliXVyUEfif9ZHINW+BQ5fSc+3oTjztTZRkx4LEhtfh1avBMSIkBrA+JvOAohm1AFgJGRpbOoXS/X1KXgHZE4X1Ssxpt18iYImGJiRFWWKCXkBdiR4L0QUEKamIKxhoQZm6fAdMDVjT7cQwBEYh3DSsl4A+trQTwJbUCsT5P+CodTZtYDmNJYcrEDQSChIMsVzoVQ2kLFMCCQFW4AoDbfbRDI7fIi5aAL41jtVNiQiPUjmUBOgAMCm683/ss/TaVXtx4qKMoAAAAASUVORK5CYII=',
authenticatorGetInfo: {
- versions: ["FIDO_2_0"],
- aaguid: "b93fd961f2e6462fb12282002247de78",
+ versions: ['FIDO_2_0'],
+ aaguid: 'b93fd961f2e6462fb12282002247de78',
options: { plat: true, rk: true, uv: true },
- }
+ },
};
// Extracted from an actual android-safetynet response
const x5c = [
'MIIFYDCCBEigAwIBAgIRANhcGl70B5aICQAAAAEBn/EwDQYJKoZIhvcNAQELBQAwRjELMAkGA1UEBhMCVVMxIjAgBgNVBAoTGUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBMTEMxEzARBgNVBAMTCkdUUyBDQSAxRDQwHhcNMjIwMTI1MTAwMDM0WhcNMjIwNDI1MTAwMDMzWjAdMRswGQYDVQQDExJhdHRlc3QuYW5kcm9pZC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCY5lzFcHle1DLltNJhlScnqVRsXCWz61Fo/FGKlbm4lb9c7rYzYNoLMlTXkZiK4GREvvjgwLwc7LC8M6zorFqa9j3z4m/MudCaFVtw0AUnejjVRhTbZEJik8QEbhx5azBNSp3h+G865LZ+ygDdd0VZKdq53KB9j0F8ybkdvUcSs/m3GMjWEAip4WnrDY9FLZfx+pCpANOAbTNvciiKAwOkQGDEI1FqTCuInZiHRvmifOQsOnSExIu3sW7vQcEtTbF+UZxhjbH5EvbdoEnaLM6TBJyul7tzWuj4Y4XTckvdSCnrASwsgyQ9uN9whPvAVnxGVBXIETEtUA8myP43TKsJAgMBAAGjggJwMIICbDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUqVM2UMZVAK5CyQY6FGrtSI71s2owHwYDVR0jBBgwFoAUJeIYDrJXkZQq5dRdhpCD3lOzuJIwbQYIKwYBBQUHAQEEYTBfMCoGCCsGAQUFBzABhh5odHRwOi8vb2NzcC5wa2kuZ29vZy9ndHMxZDRpbnQwMQYIKwYBBQUHMAKGJWh0dHA6Ly9wa2kuZ29vZy9yZXBvL2NlcnRzL2d0czFkNC5kZXIwHQYDVR0RBBYwFIISYXR0ZXN0LmFuZHJvaWQuY29tMCEGA1UdIAQaMBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybHMucGtpLmdvb2cvZ3RzMWQ0aW50L1I3OGY1ejNqN3lnLmNybDCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1AFGjsPX9AXmcVm24N3iPDKR6zBsny/eeiEKaDf7UiwXlAAABfpDlDAIAAAQDAEYwRAIgI45lPq05WVxIzo1UlhhSEvrIoAV5Eqt0+lVEnilXq8UCICWpGFH9D/DyfgagW3/2gEuHZZ8KGK9B9JZzBCJ+BvSeAHYAKXm+8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4QAAAF+kOUL4gAABAMARzBFAiEAocmVdclCD2bFPONoV21tb8GseWd2Fm3WSGqWM0wD0BsCIEetDyp5zcn58j8hRDRo/VUGtg3mv2+Y6JF4jnzBRKEQMA0GCSqGSIb3DQEBCwUAA4IBAQAInlxnIIvCKkViJe5btE6MPYAjx3GHZ1K/zltpseMRQ8bFUKMFLSSq7uNFPQr7OW3hChgLCCVoEzG4bqFuMxWb+Ht9PHtFxVXzbgJyjbvD7HSOTqk8AY1a/NQ5ujsCLSJ4Df6RdhH/OvpteP3NflUWNMIBEv0Uv1tvLEfQGW0hSbg6L/HGgAcWuL7l6/PXIEu2eL7kaGFRhI2bj4JN9YEHGnvhcGp55yB37hIx1l8U75X9hH1O6MMmzvJ05qtXCsTXQiejD0TtxTjGV+VKtpLXICpTfxNspBzCLh91ILm2pG4V9dkmEVo90tJzJI/AK6aPfogcJoBgnpS8UYwANmSC',
'MIIFjDCCA3SgAwIBAgINAgCOsgIzNmWLZM3bmzANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzMDAwMDQyWhcNMjcwOTMwMDAwMDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFENDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKvAqqPCE27l0w9zC8dTPIE89bA+xTmDaG7y7VfQ4c+mOWhlUebUQpK0yv2r678RJExK0HWDjeq+nLIHN1Em5j6rARZixmyRSjhIR0KOQPGBMUldsaztIIJ7O0g/82qj/vGDl//3t4tTqxiRhLQnTLXJdeB+2DhkdU6IIgx6wN7E5NcUH3Rcsejcqj8p5Sj19vBm6i1FhqLGymhMFroWVUGO3xtIH91dsgy4eFKcfKVLWK3o2190Q0Lm/SiKmLbRJ5Au4y1euFJm2JM9eB84Fkqa3ivrXWUeVtye0CQdKvsY2FkazvxtxvusLJzLWYHk55zcRAacDA2SeEtBbQfD1qsCAwEAAaOCAXYwggFyMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUJeIYDrJXkZQq5dRdhpCD3lOzuJIwHwYDVR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4waAYIKwYBBQUHAQEEXDBaMCYGCCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHNyMTAwBggrBgEFBQcwAoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ3RzcjEuZGVyMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ3RzcjEvZ3RzcjEuY3JsME0GA1UdIARGMEQwCAYGZ4EMAQIBMDgGCisGAQQB1nkCBQMwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly9wa2kuZ29vZy9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAgEAIVToy24jwXUr0rAPc924vuSVbKQuYw3nLflLfLh5AYWEeVl/Du18QAWUMdcJ6o/qFZbhXkBH0PNcw97thaf2BeoDYY9Ck/b+UGluhx06zd4EBf7H9P84nnrwpR+4GBDZK+Xh3I0tqJy2rgOqNDflr5IMQ8ZTWA3yltakzSBKZ6XpF0PpqyCRvp/NCGv2KX2TuPCJvscp1/m2pVTtyBjYPRQ+QuCQGAJKjtN7R5DFrfTqMWvYgVlpCJBkwlu7+7KY3cTIfzE7cmALskMKNLuDz+RzCcsYTsVaU7Vp3xL60OYhqFkuAOOxDZ6pHOj9+OJmYgPmOT4X3+7L51fXJyRH9KfLRP6nT31D5nmsGAOgZ26/8T9hsBW1uo9ju5fZLZXVVS5H0HyIBMEKyGMIPhFWrlt/hFS28N1zaKI0ZBGD3gYgDLbiDT9fGXstpk+Fmc4olVlWPzXe81vdoEnFbr5M272HdgJWo+WhT9BYM0Ji+wdVmnRffXgloEoluTNcWzc41dFpgJu8fF3LG0gl2ibSYiCi9a6hvU0TppjJyIWXhkJTcMJlPrWx1VytEUGrX2l0JDwRjW/656r0KVB02xHRKvm2ZKI03TglLIpmVCK3kBKkKNpBNkFt8rhafcCKOb9Jx/9tpNFlQTl7B39rJlJWkR17QnZqVptFePFORoZmFzM=',
- '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'
+ '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',
];
- const credentialPublicKey = 'pQECAyYgASFYIAKH2NrGZT-lUEA3tbBXR9owjW_7OnA1UqoL1UuKY_VCIlggpjeOH0xyBCpGDya55JLXXKrzyOieQN3dvG1pV-Qs-Gs';
+ const credentialPublicKey =
+ 'pQECAyYgASFYIAKH2NrGZT-lUEA3tbBXR9owjW_7OnA1UqoL1UuKY_VCIlggpjeOH0xyBCpGDya55JLXXKrzyOieQN3dvG1pV-Qs-Gs';
const verified = await verifyAttestationWithMetadata(
metadataStatementJSONSafetyNet,
diff --git a/packages/server/src/metadata/verifyAttestationWithMetadata.ts b/packages/server/src/metadata/verifyAttestationWithMetadata.ts
index 3d6931a..9def501 100644
--- a/packages/server/src/metadata/verifyAttestationWithMetadata.ts
+++ b/packages/server/src/metadata/verifyAttestationWithMetadata.ts
@@ -48,8 +48,8 @@ export async function verifyAttestationWithMetadata(
if (keypairAlg.alg === publicKeyCOSEInfo.alg && keypairAlg.kty === publicKeyCOSEInfo.kty) {
// If not an RSA keypair then make sure curve numbers match too
if (
- (keypairAlg.kty === COSEKTY.EC2 || keypairAlg.kty === COSEKTY.OKP)
- && keypairAlg.crv === publicKeyCOSEInfo.crv
+ (keypairAlg.kty === COSEKTY.EC2 || keypairAlg.kty === COSEKTY.OKP) &&
+ keypairAlg.crv === publicKeyCOSEInfo.crv
) {
foundMatch = true;
} else {
@@ -66,7 +66,9 @@ export async function verifyAttestationWithMetadata(
// Make sure the public key is one of the allowed algorithms
if (!foundMatch) {
const debugAlgs = Array.from(keypairCOSEAlgs).join(', ');
- throw new Error(`Public key algorithm ${publicKeyCOSEInfo} did not match any metadata algorithms [${debugAlgs}]`);
+ throw new Error(
+ `Public key algorithm ${publicKeyCOSEInfo} did not match any metadata algorithms [${debugAlgs}]`,
+ );
}
try {
@@ -76,7 +78,9 @@ export async function verifyAttestationWithMetadata(
);
} catch (err) {
const _err = err as Error;
- throw new Error(`Could not validate certificate path with any metadata root certificates: ${_err.message}`);
+ throw new Error(
+ `Could not validate certificate path with any metadata root certificates: ${_err.message}`,
+ );
}
return true;
diff --git a/packages/server/src/registration/verifyRegistrationResponse.test.ts b/packages/server/src/registration/verifyRegistrationResponse.test.ts
index de11a7b..3660844 100644
--- a/packages/server/src/registration/verifyRegistrationResponse.test.ts
+++ b/packages/server/src/registration/verifyRegistrationResponse.test.ts
@@ -531,20 +531,21 @@ test('should throw an error if RP ID not in list of possible RP IDs', async () =
test('should pass verification if custom challenge verifier returns true', async () => {
const verification = await verifyRegistrationResponse({
credential: {
- "id": "AUywDsPYEOoucI3-o-jB1J6Kt6QAxLMa1WwFKj1bNi4pAakWAsZX-pJ4gAeDmocL7SXnl8vzUfLkfrOGIVmds1RhjU1DYIWlxcGhAA",
- "rawId": "AUywDsPYEOoucI3-o-jB1J6Kt6QAxLMa1WwFKj1bNi4pAakWAsZX-pJ4gAeDmocL7SXnl8vzUfLkfrOGIVmds1RhjU1DYIWlxcGhAA",
- "response": {
- "attestationObject": "o2NmbXRmcGFja2VkZ2F0dFN0bXSiY2FsZyZjc2lnWEcwRQIhAPgoy3sxIeUvN9Mo8twyIQb9hXDHxQ2urIaEq14u6vNHAiB8ltlCippsMIIsh6AqMoZlUH_BH0bXT1xsN2zKoCEy72hhdXRoRGF0YVjQSZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFYfWYqK3OAAI1vMYKZIsLJfHwVQMATAFMsA7D2BDqLnCN_qPowdSeirekAMSzGtVsBSo9WzYuKQGpFgLGV_qSeIAHg5qHC-0l55fL81Hy5H6zhiFZnbNUYY1NQ2CFpcXBoQClAQIDJiABIVggPzMMB0nPKu9zvu6tvvyaP7MlGKJi4zazYQw5kyCjGykiWCCyHxcnMCwcj4llYwRY-MedgOCQzcz_TgKeabY4yFQyrA",
- "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiZXlKaFkzUjFZV3hEYUdGc2JHVnVaMlVpT2lKNFVuTlpaRU5SZGpWWFdrOXhiWGhTWldsYWJEWkRPWEUxVTJaeVdtNWxOR3hPVTNJNVVWWjBVR2xuSWl3aVlYSmlhWFJ5WVhKNVJHRjBZU0k2SW1GeVltbDBjbUZ5ZVVSaGRHRkdiM0pUYVdkdWFXNW5JbjAiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjgwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9"
+ id: 'AUywDsPYEOoucI3-o-jB1J6Kt6QAxLMa1WwFKj1bNi4pAakWAsZX-pJ4gAeDmocL7SXnl8vzUfLkfrOGIVmds1RhjU1DYIWlxcGhAA',
+ rawId:
+ 'AUywDsPYEOoucI3-o-jB1J6Kt6QAxLMa1WwFKj1bNi4pAakWAsZX-pJ4gAeDmocL7SXnl8vzUfLkfrOGIVmds1RhjU1DYIWlxcGhAA',
+ response: {
+ attestationObject:
+ 'o2NmbXRmcGFja2VkZ2F0dFN0bXSiY2FsZyZjc2lnWEcwRQIhAPgoy3sxIeUvN9Mo8twyIQb9hXDHxQ2urIaEq14u6vNHAiB8ltlCippsMIIsh6AqMoZlUH_BH0bXT1xsN2zKoCEy72hhdXRoRGF0YVjQSZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFYfWYqK3OAAI1vMYKZIsLJfHwVQMATAFMsA7D2BDqLnCN_qPowdSeirekAMSzGtVsBSo9WzYuKQGpFgLGV_qSeIAHg5qHC-0l55fL81Hy5H6zhiFZnbNUYY1NQ2CFpcXBoQClAQIDJiABIVggPzMMB0nPKu9zvu6tvvyaP7MlGKJi4zazYQw5kyCjGykiWCCyHxcnMCwcj4llYwRY-MedgOCQzcz_TgKeabY4yFQyrA',
+ clientDataJSON:
+ 'eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiZXlKaFkzUjFZV3hEYUdGc2JHVnVaMlVpT2lKNFVuTlpaRU5SZGpWWFdrOXhiWGhTWldsYWJEWkRPWEUxVTJaeVdtNWxOR3hPVTNJNVVWWjBVR2xuSWl3aVlYSmlhWFJ5WVhKNVJHRjBZU0k2SW1GeVltbDBjbUZ5ZVVSaGRHRkdiM0pUYVdkdWFXNW5JbjAiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjgwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9',
},
- "type": "public-key",
- "clientExtensionResults": {},
- "transports": [
- "internal"
- ]
+ type: 'public-key',
+ clientExtensionResults: {},
+ transports: ['internal'],
},
expectedChallenge: (challenge: string) => {
- const parsedChallenge: { actualChallenge: string; arbitraryData: string; } = JSON.parse(
+ const parsedChallenge: { actualChallenge: string; arbitraryData: string } = JSON.parse(
base64url.decode(challenge),
);
return parsedChallenge.actualChallenge === 'xRsYdCQv5WZOqmxReiZl6C9q5SfrZne4lNSr9QVtPig';
@@ -557,7 +558,6 @@ test('should pass verification if custom challenge verifier returns true', async
});
test('should fail verification if custom challenge verifier returns false', async () => {
-
await expect(
verifyRegistrationResponse({
credential: attestationNone,
@@ -608,13 +608,19 @@ test('should return authenticator extension output', async () => {
});
expect(verification.registrationInfo?.authenticatorExtensionResults).toMatchObject({
- 'devicePublicKey': {
- "dpk": Buffer.from('A5010203262001215820991AABED9DE4271A9EDEAD8806F9DC96D6DCCD0C476253A5510489EC8379BE5B225820A0973CFDEDBB79E27FEF4EE7481673FB3312504DDCA5434CFD23431D6AD29EDA', 'hex'),
- "sig": Buffer.from('3045022100EFB38074BD15B8C82CF09F87FBC6FB3C7169EA4F1806B7E90937374302345B7A02202B7113040731A0E727D338D48542863CE65880AA79E5EA740AC8CCD94347988E', 'hex'),
- "nonce": Buffer.from('', 'hex'),
- "scope": Buffer.from('00', 'hex'),
- "aaguid": Buffer.from('00000000000000000000000000000000', 'hex')
- }
+ devicePublicKey: {
+ dpk: Buffer.from(
+ 'A5010203262001215820991AABED9DE4271A9EDEAD8806F9DC96D6DCCD0C476253A5510489EC8379BE5B225820A0973CFDEDBB79E27FEF4EE7481673FB3312504DDCA5434CFD23431D6AD29EDA',
+ 'hex',
+ ),
+ sig: Buffer.from(
+ '3045022100EFB38074BD15B8C82CF09F87FBC6FB3C7169EA4F1806B7E90937374302345B7A02202B7113040731A0E727D338D48542863CE65880AA79E5EA740AC8CCD94347988E',
+ 'hex',
+ ),
+ nonce: Buffer.from('', 'hex'),
+ scope: Buffer.from('00', 'hex'),
+ aaguid: Buffer.from('00000000000000000000000000000000', 'hex'),
+ },
});
});
diff --git a/packages/server/src/registration/verifyRegistrationResponse.ts b/packages/server/src/registration/verifyRegistrationResponse.ts
index 2f783f9..14c2110 100644
--- a/packages/server/src/registration/verifyRegistrationResponse.ts
+++ b/packages/server/src/registration/verifyRegistrationResponse.ts
@@ -134,15 +134,8 @@ export async function verifyRegistrationResponse(
const { fmt, authData, attStmt } = decodedAttestationObject;
const parsedAuthData = parseAuthenticatorData(authData);
- const {
- aaguid,
- rpIdHash,
- flags,
- credentialID,
- counter,
- credentialPublicKey,
- extensionsData,
- } = parsedAuthData;
+ const { aaguid, rpIdHash, flags, credentialID, counter, credentialPublicKey, extensionsData } =
+ parsedAuthData;
// Make sure the response's RP ID is ours
if (expectedRPID) {
@@ -296,7 +289,7 @@ export type VerifiedRegistrationResponse = {
aaguid: string;
credentialID: Buffer;
credentialPublicKey: Buffer;
- credentialType: "public-key";
+ credentialType: 'public-key';
attestationObject: Buffer;
userVerified: boolean;
credentialDeviceType: CredentialDeviceType;
diff --git a/packages/server/src/services/metadataService.ts b/packages/server/src/services/metadataService.ts
index ecf2ce8..daed3cb 100644
--- a/packages/server/src/services/metadataService.ts
+++ b/packages/server/src/services/metadataService.ts
@@ -73,11 +73,7 @@ export class BaseMetadataService {
verificationMode?: VerificationMode;
} = {},
): Promise<void> {
- const {
- mdsServers = [defaultURLMDS],
- statements,
- verificationMode,
- } = opts;
+ const { mdsServers = [defaultURLMDS], statements, verificationMode } = opts;
this.setState(SERVICE_STATE.REFRESHING);