diff options
Diffstat (limited to 'packages/server/src')
56 files changed, 200 insertions, 201 deletions
diff --git a/packages/server/src/authentication/generateAuthenticationOptions.test.ts b/packages/server/src/authentication/generateAuthenticationOptions.test.ts index 3f11437..78c6473 100644 --- a/packages/server/src/authentication/generateAuthenticationOptions.test.ts +++ b/packages/server/src/authentication/generateAuthenticationOptions.test.ts @@ -1,6 +1,6 @@ jest.mock('../helpers/generateChallenge'); -import generateAuthenticationOptions from './generateAuthenticationOptions'; +import { generateAuthenticationOptions } from './generateAuthenticationOptions'; test('should generate credential request options suitable for sending via JSON', () => { const challenge = 'totallyrandomvalue'; diff --git a/packages/server/src/authentication/generateAuthenticationOptions.ts b/packages/server/src/authentication/generateAuthenticationOptions.ts index 54a81a3..b80473e 100644 --- a/packages/server/src/authentication/generateAuthenticationOptions.ts +++ b/packages/server/src/authentication/generateAuthenticationOptions.ts @@ -6,7 +6,7 @@ import type { } from '@simplewebauthn/typescript-types'; import base64url from 'base64url'; -import generateChallenge from '../helpers/generateChallenge'; +import { generateChallenge } from '../helpers/generateChallenge'; export type GenerateAuthenticationOptionsOpts = { allowCredentials?: PublicKeyCredentialDescriptorFuture[]; @@ -30,7 +30,7 @@ export type GenerateAuthenticationOptionsOpts = { * @param extensions Additional plugins the authenticator or browser should use during authentication * @param rpID Valid domain name (after `https://`) */ -export default function generateAuthenticationOptions( +export function generateAuthenticationOptions( options: GenerateAuthenticationOptionsOpts = {}, ): PublicKeyCredentialRequestOptionsJSON { const { diff --git a/packages/server/src/authentication/verifyAuthenticationResponse.test.ts b/packages/server/src/authentication/verifyAuthenticationResponse.test.ts index dbaa946..e5b6667 100644 --- a/packages/server/src/authentication/verifyAuthenticationResponse.test.ts +++ b/packages/server/src/authentication/verifyAuthenticationResponse.test.ts @@ -1,9 +1,9 @@ import base64url from 'base64url'; -import verifyAuthenticationResponse from './verifyAuthenticationResponse'; +import { verifyAuthenticationResponse } from './verifyAuthenticationResponse'; -import * as decodeClientDataJSON from '../helpers/decodeClientDataJSON'; -import * as parseAuthenticatorData from '../helpers/parseAuthenticatorData'; -import toHash from '../helpers/toHash'; +import * as esmDecodeClientDataJSON from '../helpers/decodeClientDataJSON'; +import * as esmParseAuthenticatorData from '../helpers/parseAuthenticatorData'; +import { toHash } from '../helpers/toHash'; import { AuthenticatorDevice, AuthenticationCredentialJSON, @@ -13,8 +13,8 @@ let mockDecodeClientData: jest.SpyInstance; let mockParseAuthData: jest.SpyInstance; beforeEach(() => { - mockDecodeClientData = jest.spyOn(decodeClientDataJSON, 'default'); - mockParseAuthData = jest.spyOn(parseAuthenticatorData, 'default'); + mockDecodeClientData = jest.spyOn(esmDecodeClientDataJSON, 'decodeClientDataJSON'); + mockParseAuthData = jest.spyOn(esmParseAuthenticatorData, 'parseAuthenticatorData'); }); afterEach(() => { @@ -156,7 +156,7 @@ test('should not compare counters if both are 0', () => { }); test('should throw an error if user verification is required but user was not verified', () => { - const actualData = parseAuthenticatorData.default( + const actualData = esmParseAuthenticatorData.parseAuthenticatorData( base64url.toBuffer(assertionResponse.response.authenticatorData), ); diff --git a/packages/server/src/authentication/verifyAuthenticationResponse.ts b/packages/server/src/authentication/verifyAuthenticationResponse.ts index ebc1dca..e3dc770 100644 --- a/packages/server/src/authentication/verifyAuthenticationResponse.ts +++ b/packages/server/src/authentication/verifyAuthenticationResponse.ts @@ -5,12 +5,12 @@ import { CredentialDeviceType, } from '@simplewebauthn/typescript-types'; -import decodeClientDataJSON from '../helpers/decodeClientDataJSON'; -import toHash from '../helpers/toHash'; -import convertPublicKeyToPEM from '../helpers/convertPublicKeyToPEM'; -import verifySignature from '../helpers/verifySignature'; -import parseAuthenticatorData from '../helpers/parseAuthenticatorData'; -import isBase64URLString from '../helpers/isBase64URLString'; +import { decodeClientDataJSON } from '../helpers/decodeClientDataJSON'; +import { toHash } from '../helpers/toHash'; +import { convertPublicKeyToPEM } from '../helpers/convertPublicKeyToPEM'; +import { verifySignature } from '../helpers/verifySignature'; +import { parseAuthenticatorData } from '../helpers/parseAuthenticatorData'; +import { isBase64URLString } from '../helpers/isBase64URLString'; import { parseBackupFlags } from '../helpers/parseBackupFlags'; import { AuthenticationExtensionsAuthenticatorOutputs } from '../helpers/decodeAuthenticatorExtensions'; @@ -37,7 +37,7 @@ export type VerifyAuthenticationResponseOpts = { * @param requireUserVerification (Optional) Enforce user verification by the authenticator * (via PIN, fingerprint, etc...) */ -export default function verifyAuthenticationResponse( +export function verifyAuthenticationResponse( options: VerifyAuthenticationResponseOpts, ): VerifiedAuthenticationResponse { const { diff --git a/packages/server/src/helpers/__mocks__/generateChallenge.ts b/packages/server/src/helpers/__mocks__/generateChallenge.ts index 04cfd6d..a339e56 100644 --- a/packages/server/src/helpers/__mocks__/generateChallenge.ts +++ b/packages/server/src/helpers/__mocks__/generateChallenge.ts @@ -1,3 +1,3 @@ -export default function generateChallenge(): Buffer { +export function generateChallenge(): Buffer { return Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); } diff --git a/packages/server/src/helpers/convertAAGUIDToString.test.ts b/packages/server/src/helpers/convertAAGUIDToString.test.ts index acef3b9..8c149c4 100644 --- a/packages/server/src/helpers/convertAAGUIDToString.test.ts +++ b/packages/server/src/helpers/convertAAGUIDToString.test.ts @@ -1,4 +1,4 @@ -import convertAAGUIDToString from './convertAAGUIDToString'; +import { convertAAGUIDToString } from './convertAAGUIDToString'; test('should convert buffer to UUID string', () => { const uuid = convertAAGUIDToString(Buffer.from('adce000235bcc60a648b0b25f1f05503', 'hex')); diff --git a/packages/server/src/helpers/convertAAGUIDToString.ts b/packages/server/src/helpers/convertAAGUIDToString.ts index 36e251b..0fb8356 100644 --- a/packages/server/src/helpers/convertAAGUIDToString.ts +++ b/packages/server/src/helpers/convertAAGUIDToString.ts @@ -1,7 +1,7 @@ /** * Convert the aaguid buffer in authData into a UUID string */ -export default function convertAAGUIDToString(aaguid: Buffer): string { +export function convertAAGUIDToString(aaguid: Buffer): string { // Raw Hex: adce000235bcc60a648b0b25f1f05503 const hex = aaguid.toString('hex'); diff --git a/packages/server/src/helpers/convertCOSEtoPKCS.test.ts b/packages/server/src/helpers/convertCOSEtoPKCS.test.ts index f25ac49..de2d10f 100644 --- a/packages/server/src/helpers/convertCOSEtoPKCS.test.ts +++ b/packages/server/src/helpers/convertCOSEtoPKCS.test.ts @@ -1,13 +1,13 @@ -import * as decodeCbor from './decodeCbor'; +import * as esmDecodeCbor from './decodeCbor'; -import convertCOSEtoPKCS, { COSEKEYS } from './convertCOSEtoPKCS'; +import { convertCOSEtoPKCS, COSEKEYS } from './convertCOSEtoPKCS'; test('should throw an error curve if, somehow, curve coordinate x is missing', () => { const mockCOSEKey = new Map<number, number | Buffer>(); mockCOSEKey.set(COSEKEYS.y, 1); - jest.spyOn(decodeCbor, 'decodeCborFirst').mockReturnValue(mockCOSEKey); + jest.spyOn(esmDecodeCbor, 'decodeCborFirst').mockReturnValue(mockCOSEKey); expect(() => { convertCOSEtoPKCS(Buffer.from('123', 'ascii')); @@ -19,7 +19,7 @@ test('should throw an error curve if, somehow, curve coordinate y is missing', ( mockCOSEKey.set(COSEKEYS.x, 1); - jest.spyOn(decodeCbor, 'decodeCborFirst').mockReturnValue(mockCOSEKey); + jest.spyOn(esmDecodeCbor, 'decodeCborFirst').mockReturnValue(mockCOSEKey); expect(() => { convertCOSEtoPKCS(Buffer.from('123', 'ascii')); diff --git a/packages/server/src/helpers/convertCOSEtoPKCS.ts b/packages/server/src/helpers/convertCOSEtoPKCS.ts index fe88ca6..5108209 100644 --- a/packages/server/src/helpers/convertCOSEtoPKCS.ts +++ b/packages/server/src/helpers/convertCOSEtoPKCS.ts @@ -5,7 +5,7 @@ import { decodeCborFirst } from './decodeCbor'; /** * Takes COSE-encoded public key and converts it to PKCS key */ -export default function convertCOSEtoPKCS(cosePublicKey: Buffer): Buffer { +export function convertCOSEtoPKCS(cosePublicKey: Buffer): Buffer { const struct: COSEPublicKey = decodeCborFirst(cosePublicKey); const tag = Buffer.from([0x04]); diff --git a/packages/server/src/helpers/convertCertBufferToPEM.test.ts b/packages/server/src/helpers/convertCertBufferToPEM.test.ts index 9f99128..5960c25 100644 --- a/packages/server/src/helpers/convertCertBufferToPEM.test.ts +++ b/packages/server/src/helpers/convertCertBufferToPEM.test.ts @@ -1,4 +1,4 @@ -import convertCertBufferToPEM from "./convertCertBufferToPEM"; +import { convertCertBufferToPEM } from "./convertCertBufferToPEM"; test('should return pem when input is base64URLString', () => { const input = "Y2VydEJ1ZmZlclN0cmluZyBjZXJ0QnVmZmVyU3RyaW5nIGNlcnRCdWZmZXJTdHJpbmcgY2VydEJ1ZmZlclN0cmluZyBjZXJ0QnVmZmVyU3RyaW5nIGNlcnRCdWZmZXJTdHJpbmcgY2VydEJ1ZmZlclN0cmluZw"; diff --git a/packages/server/src/helpers/convertCertBufferToPEM.ts b/packages/server/src/helpers/convertCertBufferToPEM.ts index e02a4c3..8de140d 100644 --- a/packages/server/src/helpers/convertCertBufferToPEM.ts +++ b/packages/server/src/helpers/convertCertBufferToPEM.ts @@ -4,7 +4,7 @@ import type { Base64URLString } from '@simplewebauthn/typescript-types'; /** * Convert buffer to an OpenSSL-compatible PEM text format. */ -export default function convertCertBufferToPEM(certBuffer: Buffer | Base64URLString): string { +export function convertCertBufferToPEM(certBuffer: Buffer | Base64URLString): string { let buffer: Buffer; if (typeof certBuffer === 'string') { buffer = base64url.toBuffer(certBuffer); diff --git a/packages/server/src/helpers/convertPublicKeyToPEM.test.ts b/packages/server/src/helpers/convertPublicKeyToPEM.test.ts index 1e8edd2..2c2655f 100644 --- a/packages/server/src/helpers/convertPublicKeyToPEM.test.ts +++ b/packages/server/src/helpers/convertPublicKeyToPEM.test.ts @@ -1,7 +1,7 @@ import base64url from "base64url"; import cbor from "cbor"; import { COSEKEYS } from "./convertCOSEtoPKCS"; -import convertPublicKeyToPEM from "./convertPublicKeyToPEM"; +import { convertPublicKeyToPEM } from "./convertPublicKeyToPEM"; test('should return pem when input is base64URLString', () => { const mockCOSEKey = new Map<number, number | Buffer>(); diff --git a/packages/server/src/helpers/convertPublicKeyToPEM.ts b/packages/server/src/helpers/convertPublicKeyToPEM.ts index 091f68e..5c0e39a 100644 --- a/packages/server/src/helpers/convertPublicKeyToPEM.ts +++ b/packages/server/src/helpers/convertPublicKeyToPEM.ts @@ -3,7 +3,7 @@ import jwkToPem from 'jwk-to-pem'; import { COSEKEYS, COSEKTY, COSECRV } from './convertCOSEtoPKCS'; -export default function convertPublicKeyToPEM(publicKey: Buffer): string { +export function convertPublicKeyToPEM(publicKey: Buffer): string { let struct; try { struct = cbor.decodeAllSync(publicKey)[0]; diff --git a/packages/server/src/helpers/decodeAttestationObject.test.ts b/packages/server/src/helpers/decodeAttestationObject.test.ts index 6ba29e9..1ba6bd0 100644 --- a/packages/server/src/helpers/decodeAttestationObject.test.ts +++ b/packages/server/src/helpers/decodeAttestationObject.test.ts @@ -1,4 +1,4 @@ -import decodeAttestationObject from './decodeAttestationObject'; +import { decodeAttestationObject } from './decodeAttestationObject'; test('should decode base64url-encoded indirect attestationObject', () => { const decoded = decodeAttestationObject( diff --git a/packages/server/src/helpers/decodeAttestationObject.ts b/packages/server/src/helpers/decodeAttestationObject.ts index 3aa39d7..5385106 100644 --- a/packages/server/src/helpers/decodeAttestationObject.ts +++ b/packages/server/src/helpers/decodeAttestationObject.ts @@ -5,7 +5,7 @@ import cbor from 'cbor'; * * @param base64AttestationObject Attestation Object buffer */ -export default function decodeAttestationObject(attestationObject: Buffer): AttestationObject { +export function decodeAttestationObject(attestationObject: Buffer): AttestationObject { const toCBOR: AttestationObject = cbor.decodeAllSync(attestationObject)[0]; return toCBOR; } diff --git a/packages/server/src/helpers/decodeClientDataJSON.test.ts b/packages/server/src/helpers/decodeClientDataJSON.test.ts index b51f7ce..c72cb88 100644 --- a/packages/server/src/helpers/decodeClientDataJSON.test.ts +++ b/packages/server/src/helpers/decodeClientDataJSON.test.ts @@ -1,4 +1,4 @@ -import decodeClientDataJSON from './decodeClientDataJSON'; +import { decodeClientDataJSON } from './decodeClientDataJSON'; test('should convert base64url-encoded attestation clientDataJSON to JSON', () => { expect( diff --git a/packages/server/src/helpers/decodeClientDataJSON.ts b/packages/server/src/helpers/decodeClientDataJSON.ts index 40ce0c0..b3094db 100644 --- a/packages/server/src/helpers/decodeClientDataJSON.ts +++ b/packages/server/src/helpers/decodeClientDataJSON.ts @@ -3,7 +3,7 @@ import base64url from 'base64url'; /** * Decode an authenticator's base64url-encoded clientDataJSON to JSON */ -export default function decodeClientDataJSON(data: string): ClientDataJSON { +export function decodeClientDataJSON(data: string): ClientDataJSON { const toString = base64url.decode(data); const clientData: ClientDataJSON = JSON.parse(toString); diff --git a/packages/server/src/helpers/decodeCredentialPublicKey.ts b/packages/server/src/helpers/decodeCredentialPublicKey.ts index a3fb45f..cd7a4a2 100644 --- a/packages/server/src/helpers/decodeCredentialPublicKey.ts +++ b/packages/server/src/helpers/decodeCredentialPublicKey.ts @@ -1,6 +1,6 @@ import { COSEPublicKey } from './convertCOSEtoPKCS'; import { decodeCborFirst } from './decodeCbor'; -export default function decodeCredentialPublicKey(publicKey: Buffer): COSEPublicKey { +export function decodeCredentialPublicKey(publicKey: Buffer): COSEPublicKey { return decodeCborFirst(publicKey); } diff --git a/packages/server/src/helpers/generateChallenge.test.ts b/packages/server/src/helpers/generateChallenge.test.ts index 065ad7f..b1f2fd0 100644 --- a/packages/server/src/helpers/generateChallenge.test.ts +++ b/packages/server/src/helpers/generateChallenge.test.ts @@ -1,4 +1,4 @@ -import generateChallenge from './generateChallenge'; +import { generateChallenge } from './generateChallenge'; test('should return a buffer of at least 32 bytes', () => { const challenge = generateChallenge(); diff --git a/packages/server/src/helpers/generateChallenge.ts b/packages/server/src/helpers/generateChallenge.ts index 44969b3..4acecf3 100644 --- a/packages/server/src/helpers/generateChallenge.ts +++ b/packages/server/src/helpers/generateChallenge.ts @@ -3,7 +3,7 @@ import crypto from 'crypto'; /** * Generate a suitably random value to be used as an attestation or assertion challenge */ -export default function generateChallenge(): Buffer { +export function generateChallenge(): Buffer { /** * WebAuthn spec says that 16 bytes is a good minimum: * diff --git a/packages/server/src/helpers/getCertificateInfo.ts b/packages/server/src/helpers/getCertificateInfo.ts index 021ad77..02183c5 100644 --- a/packages/server/src/helpers/getCertificateInfo.ts +++ b/packages/server/src/helpers/getCertificateInfo.ts @@ -36,7 +36,7 @@ const issuerSubjectIDKey: { [key: string]: 'C' | 'O' | 'OU' | 'CN' } = { * * @param pemCertificate Result from call to `convertASN1toPEM(x5c[0])` */ -export default function getCertificateInfo(leafCertBuffer: Buffer): CertificateInfo { +export function getCertificateInfo(leafCertBuffer: Buffer): CertificateInfo { const asnx509 = AsnParser.parse(leafCertBuffer, Certificate); const parsedCert = asnx509.tbsCertificate; diff --git a/packages/server/src/helpers/index.ts b/packages/server/src/helpers/index.ts index 248a31f..d0c4f42 100644 --- a/packages/server/src/helpers/index.ts +++ b/packages/server/src/helpers/index.ts @@ -1,19 +1,19 @@ -import convertAAGUIDToString from './convertAAGUIDToString'; -import convertCertBufferToPEM from './convertCertBufferToPEM'; -import convertCOSEtoPKCS from './convertCOSEtoPKCS'; -import convertPublicKeyToPEM from './convertPublicKeyToPEM'; -import decodeAttestationObject from './decodeAttestationObject'; +import { convertAAGUIDToString } from './convertAAGUIDToString'; +import { convertCertBufferToPEM } from './convertCertBufferToPEM'; +import { convertCOSEtoPKCS } from './convertCOSEtoPKCS'; +import { convertPublicKeyToPEM } from './convertPublicKeyToPEM'; +import { decodeAttestationObject } from './decodeAttestationObject'; import { decodeCborFirst } from './decodeCbor'; -import decodeClientDataJSON from './decodeClientDataJSON'; -import decodeCredentialPublicKey from './decodeCredentialPublicKey'; -import generateChallenge from './generateChallenge'; -import getCertificateInfo from './getCertificateInfo'; -import isBase64URLString from './isBase64URLString'; -import isCertRevoked from './isCertRevoked'; -import parseAuthenticatorData from './parseAuthenticatorData'; -import toHash from './toHash'; -import validateCertificatePath from './validateCertificatePath'; -import verifySignature from './verifySignature'; +import { decodeClientDataJSON } from './decodeClientDataJSON'; +import { decodeCredentialPublicKey } from './decodeCredentialPublicKey'; +import { generateChallenge } from './generateChallenge'; +import { getCertificateInfo } from './getCertificateInfo'; +import { isBase64URLString } from './isBase64URLString'; +import { isCertRevoked } from './isCertRevoked'; +import { parseAuthenticatorData } from './parseAuthenticatorData'; +import { toHash } from './toHash'; +import { validateCertificatePath } from './validateCertificatePath'; +import { verifySignature } from './verifySignature'; export { convertAAGUIDToString, diff --git a/packages/server/src/helpers/isBase64URLString.test.ts b/packages/server/src/helpers/isBase64URLString.test.ts index f91aeb1..545ff93 100644 --- a/packages/server/src/helpers/isBase64URLString.test.ts +++ b/packages/server/src/helpers/isBase64URLString.test.ts @@ -1,4 +1,4 @@ -import isBase64URLString from './isBase64URLString'; +import { isBase64URLString } from './isBase64URLString'; test('should return true when input is base64URLString', () => { const actual = isBase64URLString("U2ltcGxlV2ViQXV0aG4") diff --git a/packages/server/src/helpers/isBase64URLString.ts b/packages/server/src/helpers/isBase64URLString.ts index 09a6404..f229bf3 100644 --- a/packages/server/src/helpers/isBase64URLString.ts +++ b/packages/server/src/helpers/isBase64URLString.ts @@ -4,7 +4,7 @@ const base64urlRegEx = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z /** * Check to see if a string only contains valid Base64URL values */ -export default function isBase64URLString(value: string): boolean { +export function isBase64URLString(value: string): boolean { if (!value) { return false; } diff --git a/packages/server/src/helpers/isCertRevoked.ts b/packages/server/src/helpers/isCertRevoked.ts index 0e44017..cc8c3f1 100644 --- a/packages/server/src/helpers/isCertRevoked.ts +++ b/packages/server/src/helpers/isCertRevoked.ts @@ -3,7 +3,7 @@ import fetch from 'node-fetch'; import { AsnParser } from '@peculiar/asn1-schema'; import { CertificateList } from '@peculiar/asn1-x509'; -import convertCertBufferToPEM from './convertCertBufferToPEM'; +import { convertCertBufferToPEM } from './convertCertBufferToPEM'; /** * A cache of revoked cert serial numbers by Authority Key ID @@ -22,7 +22,7 @@ const cacheRevokedCerts: { [certAuthorityKeyID: string]: CAAuthorityInfo } = {}; * * CRL certificate structure referenced from https://tools.ietf.org/html/rfc5280#page-117 */ -export default async function isCertRevoked(cert: X509): Promise<boolean> { +export async function isCertRevoked(cert: X509): Promise<boolean> { const certSerialHex = cert.getSerialNumberHex(); // Check to see if we've got cached info for the cert's CA diff --git a/packages/server/src/helpers/parseAuthenticatorData.test.ts b/packages/server/src/helpers/parseAuthenticatorData.test.ts index e199898..a706718 100644 --- a/packages/server/src/helpers/parseAuthenticatorData.test.ts +++ b/packages/server/src/helpers/parseAuthenticatorData.test.ts @@ -1,6 +1,6 @@ import cbor from 'cbor'; -import parseAuthenticatorData from './parseAuthenticatorData'; +import { parseAuthenticatorData } from './parseAuthenticatorData'; // Grabbed this from a Conformance test, contains attestation data const authDataWithAT = Buffer.from( diff --git a/packages/server/src/helpers/parseAuthenticatorData.ts b/packages/server/src/helpers/parseAuthenticatorData.ts index 199513a..b130a5e 100644 --- a/packages/server/src/helpers/parseAuthenticatorData.ts +++ b/packages/server/src/helpers/parseAuthenticatorData.ts @@ -5,7 +5,7 @@ import { decodeAuthenticatorExtensions, AuthenticationExtensionsAuthenticatorOut /** * Make sense of the authData buffer contained in an Attestation */ -export default function parseAuthenticatorData(authData: Buffer): ParsedAuthenticatorData { +export function parseAuthenticatorData(authData: Buffer): ParsedAuthenticatorData { if (authData.byteLength < 37) { throw new Error( `Authenticator data was ${authData.byteLength} bytes, expected at least 37 bytes`, diff --git a/packages/server/src/helpers/toHash.test.ts b/packages/server/src/helpers/toHash.test.ts index 4f012e5..86c9142 100644 --- a/packages/server/src/helpers/toHash.test.ts +++ b/packages/server/src/helpers/toHash.test.ts @@ -1,4 +1,4 @@ -import toHash from './toHash'; +import { toHash } from './toHash'; test('should return a buffer of at 32 bytes for input string', () => { const hash = toHash("string"); diff --git a/packages/server/src/helpers/toHash.ts b/packages/server/src/helpers/toHash.ts index 68ed089..007b1ab 100644 --- a/packages/server/src/helpers/toHash.ts +++ b/packages/server/src/helpers/toHash.ts @@ -5,6 +5,6 @@ import crypto from 'crypto'; * @param data Data to hash * @return The hash */ -export default function toHash(data: Buffer | string, algo = 'SHA256'): Buffer { +export function toHash(data: Buffer | string, algo = 'SHA256'): Buffer { return crypto.createHash(algo).update(data).digest(); } diff --git a/packages/server/src/helpers/validateCertificatePath.ts b/packages/server/src/helpers/validateCertificatePath.ts index 96d3f50..11c1689 100644 --- a/packages/server/src/helpers/validateCertificatePath.ts +++ b/packages/server/src/helpers/validateCertificatePath.ts @@ -3,7 +3,7 @@ // @ts-ignore 2305 import { KJUR, X509, ASN1HEX, zulutodate } from 'jsrsasign'; -import isCertRevoked from './isCertRevoked'; +import { isCertRevoked } from './isCertRevoked'; const { crypto } = KJUR; @@ -12,7 +12,7 @@ const { crypto } = KJUR; * @param certificates Typically the result of `x5c.map(convertASN1toPEM)` * @param rootCertificates Possible root certificates to complete the path */ -export default async function validateCertificatePath( +export async function validateCertificatePath( certificates: string[], rootCertificates: string[] = [], ): Promise<boolean> { diff --git a/packages/server/src/helpers/verifySignature.ts b/packages/server/src/helpers/verifySignature.ts index 2268d54..14089a2 100644 --- a/packages/server/src/helpers/verifySignature.ts +++ b/packages/server/src/helpers/verifySignature.ts @@ -8,7 +8,7 @@ import crypto from 'crypto'; * @param publicKey Authenticator's public key as a PEM certificate * @param algo Which algorithm to use to verify the signature (default: `'sha256'`) */ -export default function verifySignature( +export function verifySignature( signature: Buffer, signatureBase: Buffer, publicKey: string, diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index c0af4f5..e15054a 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -2,12 +2,12 @@ * @packageDocumentation * @module @simplewebauthn/server */ -import generateRegistrationOptions from './registration/generateRegistrationOptions'; -import verifyRegistrationResponse from './registration/verifyRegistrationResponse'; -import generateAuthenticationOptions from './authentication/generateAuthenticationOptions'; -import verifyAuthenticationResponse from './authentication/verifyAuthenticationResponse'; -import MetadataService from './services/metadataService'; -import SettingsService from './services/settingsService'; +import { generateRegistrationOptions } from './registration/generateRegistrationOptions'; +import { verifyRegistrationResponse } from './registration/verifyRegistrationResponse'; +import { generateAuthenticationOptions } from './authentication/generateAuthenticationOptions'; +import { verifyAuthenticationResponse } from './authentication/verifyAuthenticationResponse'; +import { MetadataService } from './services/metadataService'; +import { SettingsService } from './services/settingsService'; export { generateRegistrationOptions, diff --git a/packages/server/src/metadata/parseJWT.ts b/packages/server/src/metadata/parseJWT.ts index e4dd8f5..254e14e 100644 --- a/packages/server/src/metadata/parseJWT.ts +++ b/packages/server/src/metadata/parseJWT.ts @@ -3,7 +3,7 @@ import base64url from 'base64url'; /** * Process a JWT into Javascript-friendly data structures */ -export default function parseJWT<T1, T2>(jwt: string): [T1, T2, string] { +export function parseJWT<T1, T2>(jwt: string): [T1, T2, string] { const parts = jwt.split('.'); return [ JSON.parse(base64url.decode(parts[0])) as T1, diff --git a/packages/server/src/metadata/verifyAttestationWithMetadata.test.ts b/packages/server/src/metadata/verifyAttestationWithMetadata.test.ts index f938951..57f8aa7 100644 --- a/packages/server/src/metadata/verifyAttestationWithMetadata.test.ts +++ b/packages/server/src/metadata/verifyAttestationWithMetadata.test.ts @@ -1,6 +1,6 @@ import base64url from 'base64url'; -import verifyAttestationWithMetadata from './verifyAttestationWithMetadata'; +import { verifyAttestationWithMetadata } from './verifyAttestationWithMetadata'; import { MetadataStatement } from '../metadata/mdsTypes'; test('should verify attestation with metadata (android-safetynet)', async () => { diff --git a/packages/server/src/metadata/verifyAttestationWithMetadata.ts b/packages/server/src/metadata/verifyAttestationWithMetadata.ts index 5a4a0bb..3d6931a 100644 --- a/packages/server/src/metadata/verifyAttestationWithMetadata.ts +++ b/packages/server/src/metadata/verifyAttestationWithMetadata.ts @@ -1,16 +1,16 @@ import { Base64URLString } from '@simplewebauthn/typescript-types'; import { MetadataStatement, AlgSign } from '../metadata/mdsTypes'; -import convertCertBufferToPEM from '../helpers/convertCertBufferToPEM'; -import validateCertificatePath from '../helpers/validateCertificatePath'; -import decodeCredentialPublicKey from '../helpers/decodeCredentialPublicKey'; +import { convertCertBufferToPEM } from '../helpers/convertCertBufferToPEM'; +import { validateCertificatePath } from '../helpers/validateCertificatePath'; +import { decodeCredentialPublicKey } from '../helpers/decodeCredentialPublicKey'; import { COSEKEYS, COSEKTY } from '../helpers/convertCOSEtoPKCS'; /** * Match properties of the authenticator's attestation statement against expected values as * registered with the FIDO Alliance Metadata Service */ -export default async function verifyAttestationWithMetadata( +export async function verifyAttestationWithMetadata( statement: MetadataStatement, credentialPublicKey: Buffer, x5c: Buffer[] | Base64URLString[], diff --git a/packages/server/src/registration/generateRegistrationOptions.test.ts b/packages/server/src/registration/generateRegistrationOptions.test.ts index 19fa0a6..db4e11e 100644 --- a/packages/server/src/registration/generateRegistrationOptions.test.ts +++ b/packages/server/src/registration/generateRegistrationOptions.test.ts @@ -1,6 +1,6 @@ jest.mock('../helpers/generateChallenge'); -import generateRegistrationOptions from './generateRegistrationOptions'; +import { generateRegistrationOptions } from './generateRegistrationOptions'; test('should generate credential request options suitable for sending via JSON', () => { const rpName = 'SimpleWebAuthn'; diff --git a/packages/server/src/registration/generateRegistrationOptions.ts b/packages/server/src/registration/generateRegistrationOptions.ts index f3cf5c2..d8d0ab5 100644 --- a/packages/server/src/registration/generateRegistrationOptions.ts +++ b/packages/server/src/registration/generateRegistrationOptions.ts @@ -9,7 +9,7 @@ import type { } from '@simplewebauthn/typescript-types'; import base64url from 'base64url'; -import generateChallenge from '../helpers/generateChallenge'; +import { generateChallenge } from '../helpers/generateChallenge'; export type GenerateRegistrationOptionsOpts = { rpName: string; @@ -93,7 +93,7 @@ const defaultSupportedAlgorithmIDs = supportedCOSEAlgorithmIdentifiers.filter(id * @param supportedAlgorithmIDs Array of numeric COSE algorithm identifiers supported for * attestation by this RP. See https://www.iana.org/assignments/cose/cose.xhtml#algorithms */ -export default function generateRegistrationOptions( +export function generateRegistrationOptions( options: GenerateRegistrationOptionsOpts, ): PublicKeyCredentialCreationOptionsJSON { const { diff --git a/packages/server/src/registration/verifications/tpm/parseCertInfo.ts b/packages/server/src/registration/verifications/tpm/parseCertInfo.ts index 1ac391e..6e3d4c3 100644 --- a/packages/server/src/registration/verifications/tpm/parseCertInfo.ts +++ b/packages/server/src/registration/verifications/tpm/parseCertInfo.ts @@ -3,7 +3,7 @@ import { TPM_ST, TPM_ALG } from './constants'; /** * Cut up a TPM attestation's certInfo into intelligible chunks */ -export default function parseCertInfo(certInfo: Buffer): ParsedCertInfo { +export function parseCertInfo(certInfo: Buffer): ParsedCertInfo { let pointer = 0; // Get a magic constant diff --git a/packages/server/src/registration/verifications/tpm/parsePubArea.ts b/packages/server/src/registration/verifications/tpm/parsePubArea.ts index 5f0d63b..693f7bb 100644 --- a/packages/server/src/registration/verifications/tpm/parsePubArea.ts +++ b/packages/server/src/registration/verifications/tpm/parsePubArea.ts @@ -3,7 +3,7 @@ import { TPM_ALG, TPM_ECC_CURVE } from './constants'; /** * Break apart a TPM attestation's pubArea buffer */ -export default function parsePubArea(pubArea: Buffer): ParsedPubArea { +export function parsePubArea(pubArea: Buffer): ParsedPubArea { let pointer = 0; const typeBuffer = pubArea.slice(pointer, (pointer += 2)); diff --git a/packages/server/src/registration/verifications/tpm/verifyTPM.test.ts b/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.test.ts index 819ed81..0584ebd 100644 --- a/packages/server/src/registration/verifications/tpm/verifyTPM.test.ts +++ b/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.test.ts @@ -1,4 +1,4 @@ -import verifyRegistrationResponse from '../../verifyRegistrationResponse'; +import { verifyRegistrationResponse } from '../../verifyRegistrationResponse'; import base64url from 'base64url'; test('should verify TPM response', async () => { diff --git a/packages/server/src/registration/verifications/tpm/verifyTPM.ts b/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts index 1a4582d..1b97056 100644 --- a/packages/server/src/registration/verifications/tpm/verifyTPM.ts +++ b/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts @@ -10,21 +10,21 @@ import { import type { AttestationFormatVerifierOpts } from '../../verifyRegistrationResponse'; -import decodeCredentialPublicKey from '../../../helpers/decodeCredentialPublicKey'; +import { decodeCredentialPublicKey } from '../../../helpers/decodeCredentialPublicKey'; import { COSEKEYS, COSEALGHASH } from '../../../helpers/convertCOSEtoPKCS'; -import toHash from '../../../helpers/toHash'; -import convertCertBufferToPEM from '../../../helpers/convertCertBufferToPEM'; -import validateCertificatePath from '../../../helpers/validateCertificatePath'; -import getCertificateInfo from '../../../helpers/getCertificateInfo'; -import verifySignature from '../../../helpers/verifySignature'; -import MetadataService from '../../../services/metadataService'; -import verifyAttestationWithMetadata from '../../../metadata/verifyAttestationWithMetadata'; +import { toHash } from '../../../helpers/toHash'; +import { convertCertBufferToPEM } from '../../../helpers/convertCertBufferToPEM'; +import { validateCertificatePath } from '../../../helpers/validateCertificatePath'; +import { getCertificateInfo } from '../../../helpers/getCertificateInfo'; +import { verifySignature } from '../../../helpers/verifySignature'; +import { MetadataService } from '../../../services/metadataService'; +import { verifyAttestationWithMetadata } from '../../../metadata/verifyAttestationWithMetadata'; import { TPM_ECC_CURVE, TPM_MANUFACTURERS } from './constants'; -import parseCertInfo from './parseCertInfo'; -import parsePubArea from './parsePubArea'; +import { parseCertInfo } from './parseCertInfo'; +import { parsePubArea } from './parsePubArea'; -export default async function verifyTPM(options: AttestationFormatVerifierOpts): Promise<boolean> { +export async function verifyAttestationTPM(options: AttestationFormatVerifierOpts): Promise<boolean> { const { aaguid, attStmt, authData, credentialPublicKey, clientDataHash, rootCertificates } = options; const { ver, sig, alg, x5c, pubArea, certInfo } = attStmt; diff --git a/packages/server/src/registration/verifications/verifyAndroidKey.test.ts b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.test.ts index d7f5ce7..f7cdd4f 100644 --- a/packages/server/src/registration/verifications/verifyAndroidKey.test.ts +++ b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.test.ts @@ -1,8 +1,8 @@ import base64url from 'base64url'; -import SettingsService from '../../services/settingsService'; +import { SettingsService } from '../../services/settingsService'; -import verifyRegistrationResponse from '../verifyRegistrationResponse'; +import { verifyRegistrationResponse } from '../verifyRegistrationResponse'; /** * Clear out root certs for android-key since responses were captured from FIDO Conformance testing diff --git a/packages/server/src/registration/verifications/verifyAndroidKey.ts b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts index 8198203..dcc3670 100644 --- a/packages/server/src/registration/verifications/verifyAndroidKey.ts +++ b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts @@ -4,17 +4,17 @@ import { KeyDescription, id_ce_keyDescription } from '@peculiar/asn1-android'; import type { AttestationFormatVerifierOpts } from '../verifyRegistrationResponse'; -import convertCertBufferToPEM from '../../helpers/convertCertBufferToPEM'; -import validateCertificatePath from '../../helpers/validateCertificatePath'; -import verifySignature from '../../helpers/verifySignature'; -import convertCOSEtoPKCS, { COSEALGHASH } from '../../helpers/convertCOSEtoPKCS'; -import MetadataService from '../../services/metadataService'; -import verifyAttestationWithMetadata from '../../metadata/verifyAttestationWithMetadata'; +import { convertCertBufferToPEM } from '../../helpers/convertCertBufferToPEM'; +import { validateCertificatePath } from '../../helpers/validateCertificatePath'; +import { verifySignature } from '../../helpers/verifySignature'; +import { COSEALGHASH, convertCOSEtoPKCS } from '../../helpers/convertCOSEtoPKCS'; +import { MetadataService } from '../../services/metadataService'; +import { verifyAttestationWithMetadata } from '../../metadata/verifyAttestationWithMetadata'; /** * Verify an attestation response with fmt 'android-key' */ -export default async function verifyAttestationAndroidKey( +export async function verifyAttestationAndroidKey( options: AttestationFormatVerifierOpts, ): Promise<boolean> { const { authData, clientDataHash, attStmt, credentialPublicKey, aaguid, rootCertificates } = diff --git a/packages/server/src/registration/verifications/verifyAndroidSafetyNet.test.ts b/packages/server/src/registration/verifications/verifyAttestationAndroidSafetyNet.test.ts index cef374f..5df3bee 100644 --- a/packages/server/src/registration/verifications/verifyAndroidSafetyNet.test.ts +++ b/packages/server/src/registration/verifications/verifyAttestationAndroidSafetyNet.test.ts @@ -1,15 +1,16 @@ import base64url from 'base64url'; -import verifyAndroidSafetyNet from './verifyAndroidSafetyNet'; +import { verifyAttestationAndroidSafetyNet } from './verifyAttestationAndroidSafetyNet'; -import decodeAttestationObject, { +import { + decodeAttestationObject, AttestationStatement, } from '../../helpers/decodeAttestationObject'; -import parseAuthenticatorData from '../../helpers/parseAuthenticatorData'; -import toHash from '../../helpers/toHash'; -import settingsService from '../../services/settingsService'; +import { parseAuthenticatorData } from '../../helpers/parseAuthenticatorData'; +import { toHash } from '../../helpers/toHash'; +import { SettingsService } from '../../services/settingsService'; -const rootCertificates = settingsService.getRootCertificates({ +const rootCertificates = SettingsService.getRootCertificates({ identifier: 'android-safetynet', }); @@ -51,7 +52,7 @@ test('should verify Android SafetyNet attestation', async () => { // notAfter: 2021-12-15T00:00:42.000Z spyDate.mockReturnValue(new Date('2021-11-15T00:00:42.000Z')); - const verified = await verifyAndroidSafetyNet({ + const verified = await verifyAttestationAndroidSafetyNet({ attStmt, authData, clientDataHash, @@ -68,7 +69,7 @@ test('should verify Android SafetyNet attestation', async () => { test('should throw error when timestamp is not within one minute of now', async () => { await expect( - verifyAndroidSafetyNet({ + verifyAttestationAndroidSafetyNet({ attStmt, authData, clientDataHash, @@ -96,7 +97,7 @@ test('should validate response with cert path completed with GlobalSign R1 root const parsedAuthData = parseAuthenticatorData(_authData); const _aaguid = parsedAuthData.aaguid!; - const verified = await verifyAndroidSafetyNet({ + const verified = await verifyAttestationAndroidSafetyNet({ attStmt: _attStmt, authData: _authData, clientDataHash: _clientDataHash, diff --git a/packages/server/src/registration/verifications/verifyAndroidSafetyNet.ts b/packages/server/src/registration/verifications/verifyAttestationAndroidSafetyNet.ts index a61311a..14be27e 100644 --- a/packages/server/src/registration/verifications/verifyAndroidSafetyNet.ts +++ b/packages/server/src/registration/verifications/verifyAttestationAndroidSafetyNet.ts @@ -2,18 +2,18 @@ import base64url from 'base64url'; import type { AttestationFormatVerifierOpts } from '../verifyRegistrationResponse'; -import toHash from '../../helpers/toHash'; -import verifySignature from '../../helpers/verifySignature'; -import getCertificateInfo from '../../helpers/getCertificateInfo'; -import validateCertificatePath from '../../helpers/validateCertificatePath'; -import convertCertBufferToPEM from '../../helpers/convertCertBufferToPEM'; -import MetadataService from '../../services/metadataService'; -import verifyAttestationWithMetadata from '../../metadata/verifyAttestationWithMetadata'; +import { toHash } from '../../helpers/toHash'; +import { verifySignature } from '../../helpers/verifySignature'; +import { getCertificateInfo } from '../../helpers/getCertificateInfo'; +import { validateCertificatePath } from '../../helpers/validateCertificatePath'; +import { convertCertBufferToPEM } from '../../helpers/convertCertBufferToPEM'; +import { MetadataService } from '../../services/metadataService'; +import { verifyAttestationWithMetadata } from '../../metadata/verifyAttestationWithMetadata'; /** * Verify an attestation response with fmt 'android-safetynet' */ -export default async function verifyAttestationAndroidSafetyNet( +export async function verifyAttestationAndroidSafetyNet( options: AttestationFormatVerifierOpts, ): Promise<boolean> { const { diff --git a/packages/server/src/registration/verifications/verifyApple.test.ts b/packages/server/src/registration/verifications/verifyAttestationApple.test.ts index e1f5e89..c2d4a49 100644 --- a/packages/server/src/registration/verifications/verifyApple.test.ts +++ b/packages/server/src/registration/verifications/verifyAttestationApple.test.ts @@ -1,6 +1,6 @@ import base64url from 'base64url'; -import verifyRegistrationResponse from '../verifyRegistrationResponse'; +import { verifyRegistrationResponse } from '../verifyRegistrationResponse'; test('should verify Apple attestation', async () => { const expectedChallenge = 'h5xSyIRMx2IQPr1mQk6GD98XSQOBHgMHVpJIkMV9Nkc'; diff --git a/packages/server/src/registration/verifications/verifyApple.ts b/packages/server/src/registration/verifications/verifyAttestationApple.ts index cbf8527..e0c7890 100644 --- a/packages/server/src/registration/verifications/verifyApple.ts +++ b/packages/server/src/registration/verifications/verifyAttestationApple.ts @@ -3,12 +3,12 @@ import { Certificate } from '@peculiar/asn1-x509'; import type { AttestationFormatVerifierOpts } from '../verifyRegistrationResponse'; -import validateCertificatePath from '../../helpers/validateCertificatePath'; -import convertCertBufferToPEM from '../../helpers/convertCertBufferToPEM'; -import toHash from '../../helpers/toHash'; -import convertCOSEtoPKCS from '../../helpers/convertCOSEtoPKCS'; +import { validateCertificatePath } from '../../helpers/validateCertificatePath'; +import { convertCertBufferToPEM } from '../../helpers/convertCertBufferToPEM'; +import { toHash } from '../../helpers/toHash'; +import { convertCOSEtoPKCS } from '../../helpers/convertCOSEtoPKCS'; -export default async function verifyApple( +export async function verifyAttestationApple( options: AttestationFormatVerifierOpts, ): Promise<boolean> { const { attStmt, authData, clientDataHash, credentialPublicKey, rootCertificates } = options; diff --git a/packages/server/src/registration/verifications/verifyFIDOU2F.ts b/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts index d1d67b5..bd6ac8e 100644 --- a/packages/server/src/registration/verifications/verifyFIDOU2F.ts +++ b/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts @@ -1,14 +1,14 @@ import type { AttestationFormatVerifierOpts } from '../verifyRegistrationResponse'; -import convertCOSEtoPKCS from '../../helpers/convertCOSEtoPKCS'; -import convertCertBufferToPEM from '../../helpers/convertCertBufferToPEM'; -import validateCertificatePath from '../../helpers/validateCertificatePath'; -import verifySignature from '../../helpers/verifySignature'; +import { convertCOSEtoPKCS } from '../../helpers/convertCOSEtoPKCS'; +import { convertCertBufferToPEM } from '../../helpers/convertCertBufferToPEM'; +import { validateCertificatePath } from '../../helpers/validateCertificatePath'; +import { verifySignature } from '../../helpers/verifySignature'; /** * Verify an attestation response with fmt 'fido-u2f' */ -export default async function verifyAttestationFIDOU2F( +export async function verifyAttestationFIDOU2F( options: AttestationFormatVerifierOpts, ): Promise<boolean> { const { diff --git a/packages/server/src/registration/verifications/verifyPacked.test.ts b/packages/server/src/registration/verifications/verifyAttestationPacked.test.ts index 43c7d9d..b38a0e6 100644 --- a/packages/server/src/registration/verifications/verifyPacked.test.ts +++ b/packages/server/src/registration/verifications/verifyAttestationPacked.test.ts @@ -1,4 +1,4 @@ -import verifyRegistrationResponse from '../verifyRegistrationResponse'; +import { verifyRegistrationResponse } from '../verifyRegistrationResponse'; test('should verify (broken) Packed response from Chrome virtual authenticator', async () => { /** diff --git a/packages/server/src/registration/verifications/verifyPacked.ts b/packages/server/src/registration/verifications/verifyAttestationPacked.ts index 76f6b59..844a1ed 100644 --- a/packages/server/src/registration/verifications/verifyPacked.ts +++ b/packages/server/src/registration/verifications/verifyAttestationPacked.ts @@ -3,26 +3,27 @@ import NodeRSA from 'node-rsa'; import type { AttestationFormatVerifierOpts } from '../verifyRegistrationResponse'; -import convertCOSEtoPKCS, { +import { COSEKEYS, COSEALGHASH, COSECRV, COSEKTY, COSERSASCHEME, + convertCOSEtoPKCS, } from '../../helpers/convertCOSEtoPKCS'; -import toHash from '../../helpers/toHash'; -import convertCertBufferToPEM from '../../helpers/convertCertBufferToPEM'; -import validateCertificatePath from '../../helpers/validateCertificatePath'; -import getCertificateInfo from '../../helpers/getCertificateInfo'; -import verifySignature from '../../helpers/verifySignature'; -import decodeCredentialPublicKey from '../../helpers/decodeCredentialPublicKey'; -import MetadataService from '../../services/metadataService'; -import verifyAttestationWithMetadata from '../../metadata/verifyAttestationWithMetadata'; +import { toHash } from '../../helpers/toHash'; +import { convertCertBufferToPEM } from '../../helpers/convertCertBufferToPEM'; +import { validateCertificatePath } from '../../helpers/validateCertificatePath'; +import { getCertificateInfo } from '../../helpers/getCertificateInfo'; +import { verifySignature } from '../../helpers/verifySignature'; +import { decodeCredentialPublicKey } from '../../helpers/decodeCredentialPublicKey'; +import { MetadataService } from '../../services/metadataService'; +import { verifyAttestationWithMetadata } from '../../metadata/verifyAttestationWithMetadata'; /** * Verify an attestation response with fmt 'packed' */ -export default async function verifyAttestationPacked( +export async function verifyAttestationPacked( options: AttestationFormatVerifierOpts, ): Promise<boolean> { const { attStmt, clientDataHash, authData, credentialPublicKey, aaguid, rootCertificates } = diff --git a/packages/server/src/registration/verifyRegistrationResponse.test.ts b/packages/server/src/registration/verifyRegistrationResponse.test.ts index d4c4f20..de11a7b 100644 --- a/packages/server/src/registration/verifyRegistrationResponse.test.ts +++ b/packages/server/src/registration/verifyRegistrationResponse.test.ts @@ -1,16 +1,16 @@ import base64url from 'base64url'; -import verifyRegistrationResponse from './verifyRegistrationResponse'; +import { verifyRegistrationResponse } from './verifyRegistrationResponse'; -import * as decodeAttestationObject from '../helpers/decodeAttestationObject'; -import * as decodeClientDataJSON from '../helpers/decodeClientDataJSON'; -import * as parseAuthenticatorData from '../helpers/parseAuthenticatorData'; -import * as decodeCredentialPublicKey from '../helpers/decodeCredentialPublicKey'; -import SettingsService from '../services/settingsService'; +import * as esmDecodeAttestationObject from '../helpers/decodeAttestationObject'; +import * as esmDecodeClientDataJSON from '../helpers/decodeClientDataJSON'; +import * as esmParseAuthenticatorData from '../helpers/parseAuthenticatorData'; +import * as esmDecodeCredentialPublicKey from '../helpers/decodeCredentialPublicKey'; +import { SettingsService } from '../services/settingsService'; -import * as verifyFIDOU2F from './verifications/verifyFIDOU2F'; +import * as esmVerifyAttestationFIDOU2F from './verifications/verifyAttestationFIDOU2F'; -import toHash from '../helpers/toHash'; +import { toHash } from '../helpers/toHash'; import { RegistrationCredentialJSON } from '@simplewebauthn/typescript-types'; /** @@ -26,11 +26,11 @@ let mockDecodePubKey: jest.SpyInstance; let mockVerifyFIDOU2F: jest.SpyInstance; beforeEach(() => { - mockDecodeAttestation = jest.spyOn(decodeAttestationObject, 'default'); - mockDecodeClientData = jest.spyOn(decodeClientDataJSON, 'default'); - mockParseAuthData = jest.spyOn(parseAuthenticatorData, 'default'); - mockDecodePubKey = jest.spyOn(decodeCredentialPublicKey, 'default'); - mockVerifyFIDOU2F = jest.spyOn(verifyFIDOU2F, 'default'); + mockDecodeAttestation = jest.spyOn(esmDecodeAttestationObject, 'decodeAttestationObject'); + mockDecodeClientData = jest.spyOn(esmDecodeClientDataJSON, 'decodeClientDataJSON'); + mockParseAuthData = jest.spyOn(esmParseAuthenticatorData, 'parseAuthenticatorData'); + mockDecodePubKey = jest.spyOn(esmDecodeCredentialPublicKey, 'decodeCredentialPublicKey'); + mockVerifyFIDOU2F = jest.spyOn(esmVerifyAttestationFIDOU2F, 'verifyAttestationFIDOU2F'); }); afterEach(() => { @@ -219,7 +219,7 @@ test('should throw when attestation type is not webauthn.create', async () => { test('should throw if an unexpected attestation format is specified', async () => { const fmt = 'fizzbuzz'; - const realAtteObj = decodeAttestationObject.default( + const realAtteObj = esmDecodeAttestationObject.decodeAttestationObject( base64url.toBuffer(attestationNone.response.attestationObject), ); @@ -240,10 +240,10 @@ test('should throw if an unexpected attestation format is specified', async () = }); test('should throw error if assertion RP ID is unexpected value', async () => { - const { authData } = decodeAttestationObject.default( + const { authData } = esmDecodeAttestationObject.decodeAttestationObject( base64url.toBuffer(attestationNone.response.attestationObject), ); - const actualAuthData = parseAuthenticatorData.default(authData); + const actualAuthData = esmParseAuthenticatorData.parseAuthenticatorData(authData); mockParseAuthData.mockReturnValue({ ...actualAuthData, diff --git a/packages/server/src/registration/verifyRegistrationResponse.ts b/packages/server/src/registration/verifyRegistrationResponse.ts index 8829db1..2f783f9 100644 --- a/packages/server/src/registration/verifyRegistrationResponse.ts +++ b/packages/server/src/registration/verifyRegistrationResponse.ts @@ -5,27 +5,28 @@ import { CredentialDeviceType, } from '@simplewebauthn/typescript-types'; -import decodeAttestationObject, { +import { AttestationFormat, AttestationStatement, + decodeAttestationObject, } from '../helpers/decodeAttestationObject'; import { AuthenticationExtensionsAuthenticatorOutputs } from '../helpers/decodeAuthenticatorExtensions'; -import decodeClientDataJSON from '../helpers/decodeClientDataJSON'; -import parseAuthenticatorData from '../helpers/parseAuthenticatorData'; -import toHash from '../helpers/toHash'; -import decodeCredentialPublicKey from '../helpers/decodeCredentialPublicKey'; +import { decodeClientDataJSON } from '../helpers/decodeClientDataJSON'; +import { parseAuthenticatorData } from '../helpers/parseAuthenticatorData'; +import { toHash } from '../helpers/toHash'; +import { decodeCredentialPublicKey } from '../helpers/decodeCredentialPublicKey'; import { COSEKEYS } from '../helpers/convertCOSEtoPKCS'; -import convertAAGUIDToString from '../helpers/convertAAGUIDToString'; +import { convertAAGUIDToString } from '../helpers/convertAAGUIDToString'; import { parseBackupFlags } from '../helpers/parseBackupFlags'; -import settingsService from '../services/settingsService'; +import { SettingsService } from '../services/settingsService'; import { supportedCOSEAlgorithmIdentifiers } from './generateRegistrationOptions'; -import verifyFIDOU2F from './verifications/verifyFIDOU2F'; -import verifyPacked from './verifications/verifyPacked'; -import verifyAndroidSafetynet from './verifications/verifyAndroidSafetyNet'; -import verifyTPM from './verifications/tpm/verifyTPM'; -import verifyAndroidKey from './verifications/verifyAndroidKey'; -import verifyApple from './verifications/verifyApple'; +import { verifyAttestationFIDOU2F } from './verifications/verifyAttestationFIDOU2F'; +import { verifyAttestationPacked } from './verifications/verifyAttestationPacked'; +import { verifyAttestationAndroidSafetyNet } from './verifications/verifyAttestationAndroidSafetyNet'; +import { verifyAttestationTPM } from './verifications/tpm/verifyAttestationTPM'; +import { verifyAttestationAndroidKey } from './verifications/verifyAttestationAndroidKey'; +import { verifyAttestationApple } from './verifications/verifyAttestationApple'; export type VerifyRegistrationResponseOpts = { credential: RegistrationCredentialJSON; @@ -51,7 +52,7 @@ export type VerifyRegistrationResponseOpts = { * @param supportedAlgorithmIDs Array of numeric COSE algorithm identifiers supported for * attestation by this RP. See https://www.iana.org/assignments/cose/cose.xhtml#algorithms */ -export default async function verifyRegistrationResponse( +export async function verifyRegistrationResponse( options: VerifyRegistrationResponseOpts, ): Promise<VerifiedRegistrationResponse> { const { @@ -199,7 +200,7 @@ export default async function verifyRegistrationResponse( } const clientDataHash = toHash(base64url.toBuffer(response.clientDataJSON)); - const rootCertificates = settingsService.getRootCertificates({ identifier: fmt }); + const rootCertificates = SettingsService.getRootCertificates({ identifier: fmt }); // Prepare arguments to pass to the relevant verification method const verifierOpts: AttestationFormatVerifierOpts = { @@ -218,17 +219,17 @@ export default async function verifyRegistrationResponse( */ let verified = false; if (fmt === 'fido-u2f') { - verified = await verifyFIDOU2F(verifierOpts); + verified = await verifyAttestationFIDOU2F(verifierOpts); } else if (fmt === 'packed') { - verified = await verifyPacked(verifierOpts); + verified = await verifyAttestationPacked(verifierOpts); } else if (fmt === 'android-safetynet') { - verified = await verifyAndroidSafetynet(verifierOpts); + verified = await verifyAttestationAndroidSafetyNet(verifierOpts); } else if (fmt === 'android-key') { - verified = await verifyAndroidKey(verifierOpts); + verified = await verifyAttestationAndroidKey(verifierOpts); } else if (fmt === 'tpm') { - verified = await verifyTPM(verifierOpts); + verified = await verifyAttestationTPM(verifierOpts); } else if (fmt === 'apple') { - verified = await verifyApple(verifierOpts); + verified = await verifyAttestationApple(verifierOpts); } else if (fmt === 'none') { if (Object.keys(attStmt).length > 0) { throw new Error('None attestation had unexpected attestation statement'); diff --git a/packages/server/src/services/metadataService.test.ts b/packages/server/src/services/metadataService.test.ts index b4b056e..fdf0979 100644 --- a/packages/server/src/services/metadataService.test.ts +++ b/packages/server/src/services/metadataService.test.ts @@ -1,7 +1,7 @@ jest.mock('node-fetch'); import fetch from 'node-fetch'; -import MetadataService, { BaseMetadataService } from './metadataService'; +import { MetadataService, BaseMetadataService } from './metadataService'; import type { MetadataStatement } from '../metadata/mdsTypes'; const _fetch = fetch as unknown as jest.Mock; diff --git a/packages/server/src/services/metadataService.ts b/packages/server/src/services/metadataService.ts index 41fb39e..ecf2ce8 100644 --- a/packages/server/src/services/metadataService.ts +++ b/packages/server/src/services/metadataService.ts @@ -1,19 +1,19 @@ import fetch from 'node-fetch'; import { KJUR } from 'jsrsasign'; -import validateCertificatePath from '../helpers/validateCertificatePath'; -import convertCertBufferToPEM from '../helpers/convertCertBufferToPEM'; -import convertAAGUIDToString from '../helpers/convertAAGUIDToString'; +import { validateCertificatePath } from '../helpers/validateCertificatePath'; +import { convertCertBufferToPEM } from '../helpers/convertCertBufferToPEM'; +import { convertAAGUIDToString } from '../helpers/convertAAGUIDToString'; import type { MDSJWTHeader, MDSJWTPayload, MetadataStatement, MetadataBLOBPayloadEntry, } from '../metadata/mdsTypes'; -import SettingsService from '../services/settingsService'; +import { SettingsService } from '../services/settingsService'; import { getLogger } from '../helpers/logging'; -import parseJWT from '../metadata/parseJWT'; +import { parseJWT } from '../metadata/parseJWT'; // Cached MDS APIs from which BLOBs are downloaded type CachedMDS = { @@ -323,6 +323,4 @@ export class BaseMetadataService { } // Export a service singleton -const MetadataService = new BaseMetadataService(); - -export default MetadataService; +export const MetadataService = new BaseMetadataService(); diff --git a/packages/server/src/services/settingsService.test.ts b/packages/server/src/services/settingsService.test.ts index 28ff656..e236d06 100644 --- a/packages/server/src/services/settingsService.test.ts +++ b/packages/server/src/services/settingsService.test.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; -import settingsService from './settingsService'; +import { SettingsService } from './settingsService'; import { GlobalSign_Root_CA } from './defaultRootCerts/android-safetynet'; import { Apple_WebAuthn_Root_CA } from './defaultRootCerts/apple'; @@ -17,29 +17,29 @@ function pemToBuffer(pem: string): Buffer { describe('setRootCertificate/getRootCertificate', () => { test('should accept cert as Buffer', () => { const gsr1Buffer = pemToBuffer(GlobalSign_Root_CA); - settingsService.setRootCertificates({ + SettingsService.setRootCertificates({ identifier: 'android-safetynet', certificates: [gsr1Buffer], }); - const certs = settingsService.getRootCertificates({ identifier: 'android-safetynet' }); + const certs = SettingsService.getRootCertificates({ identifier: 'android-safetynet' }); expect(certs).toEqual([GlobalSign_Root_CA]); }); test('should accept cert as PEM string', () => { - settingsService.setRootCertificates({ + SettingsService.setRootCertificates({ identifier: 'apple', certificates: [Apple_WebAuthn_Root_CA], }); - const certs = settingsService.getRootCertificates({ identifier: 'apple' }); + const certs = SettingsService.getRootCertificates({ identifier: 'apple' }); expect(certs).toEqual([Apple_WebAuthn_Root_CA]); }); test('should return empty array when certificate is not set', () => { - const certs = settingsService.getRootCertificates({ identifier: 'none' }); + const certs = SettingsService.getRootCertificates({ identifier: 'none' }); expect(Array.isArray(certs)).toEqual(true); expect(certs.length).toEqual(0); diff --git a/packages/server/src/services/settingsService.ts b/packages/server/src/services/settingsService.ts index 499e4a6..6dce26b 100644 --- a/packages/server/src/services/settingsService.ts +++ b/packages/server/src/services/settingsService.ts @@ -1,5 +1,5 @@ import { AttestationFormat } from '../helpers/decodeAttestationObject'; -import convertCertBufferToPEM from '../helpers/convertCertBufferToPEM'; +import { convertCertBufferToPEM } from '../helpers/convertCertBufferToPEM'; import { GlobalSign_Root_CA } from './defaultRootCerts/android-safetynet'; import { @@ -11,7 +11,7 @@ import { GlobalSign_Root_CA_R3 } from './defaultRootCerts/mds'; type RootCertIdentifier = AttestationFormat | 'mds'; -class SettingsService { +class BaseSettingsService { // Certificates are stored as PEM-formatted strings private pemCertificates: Map<RootCertIdentifier, string[]>; @@ -53,27 +53,25 @@ class SettingsService { } } -const settingsService = new SettingsService(); +export const SettingsService = new BaseSettingsService(); // Initialize default certificates -settingsService.setRootCertificates({ +SettingsService.setRootCertificates({ identifier: 'android-key', certificates: [Google_Hardware_Attestation_Root_1, Google_Hardware_Attestation_Root_2], }); -settingsService.setRootCertificates({ +SettingsService.setRootCertificates({ identifier: 'android-safetynet', certificates: [GlobalSign_Root_CA], }); -settingsService.setRootCertificates({ +SettingsService.setRootCertificates({ identifier: 'apple', certificates: [Apple_WebAuthn_Root_CA], }); -settingsService.setRootCertificates({ +SettingsService.setRootCertificates({ identifier: 'mds', certificates: [GlobalSign_Root_CA_R3], }); - -export default settingsService; |