From 17f71884ab151b521241bc5aad4b74cc65c73890 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Wed, 20 May 2020 18:09:32 -0700 Subject: Rename “typings” package to “types” MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/typescript-types/src/index.ts | 155 +++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 packages/typescript-types/src/index.ts (limited to 'packages/typescript-types/src') diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts new file mode 100644 index 0000000..58cc90c --- /dev/null +++ b/packages/typescript-types/src/index.ts @@ -0,0 +1,155 @@ +/** + * An object that can be passed into navigator.credentials.create(...) in the browser + */ +export type AttestationCredentials = { + publicKey: PublicKeyCredentialCreationOptions, +}; + +/** + * An object that can be passed into navigator.credentials.get(...) in the browser + */ +export type AssertionCredentials = { + publicKey: PublicKeyCredentialRequestOptions, +}; + +/** + * A slightly-modified AuthenticatorAttestationResponse to simplify working with ArrayBuffers that + * are base64-encoded in the browser so that they can be sent as JSON to the server. + */ +export interface EncodedAuthenticatorAttestationResponse extends Omit< +AuthenticatorAttestationResponse, 'clientDataJSON' | 'attestationObject' +> { + base64ClientDataJSON: string, + base64AttestationObject: string; +} + +/** + * A slightly-modified AuthenticatorAttestationResponse to simplify working with ArrayBuffers that + * are base64-encoded in the browser so that they can be sent as JSON to the server. + */ +export interface EncodedAuthenticatorAssertionResponse extends Omit< +AuthenticatorAssertionResponse, 'clientDataJSON' | 'authenticatorData' | 'signature' +> { + base64AuthenticatorData: string; + base64ClientDataJSON: string; + base64Signature: string; +} + +export enum ATTESTATION_FORMATS { + FIDO_U2F = 'fido-u2f', + PACKED = 'packed', + ANDROID_SAFETYNET = 'android-safetynet', + NONE = 'none', +} + +export type AttestationObject = { + fmt: ATTESTATION_FORMATS, + attStmt: { + sig?: Buffer, + x5c?: Buffer[], + ecdaaKeyId?: Buffer, + response?: Buffer, + }, + authData: Buffer, +}; + +export type ParsedAttestationAuthData = { + rpIdHash: Buffer, + flagsBuf: Buffer, + flags: { + up: boolean, + uv: boolean, + at: boolean, + ed: boolean, + flagsInt: number, + }, + counter: number, + counterBuf: Buffer, + aaguid?: Buffer, + credentialID?: Buffer, + COSEPublicKey?: Buffer, +}; + +export type ClientDataJSON = { + type: string, + challenge: string, + origin: string, +}; + +/** + * Result of attestation verification + */ +export type VerifiedAttestation = { + verified: boolean, + authenticatorInfo?: { + fmt: ATTESTATION_FORMATS, + counter: number, + base64PublicKey: string, + base64CredentialID: string, + }, +}; + +/** + * Result of assertion verification + */ +export type VerifiedAssertion = { + verified: boolean; +}; + +export type CertificateInfo = { + subject: { [key: string]: string }, + version: number, + basicConstraintsCA: boolean, +}; + +export enum COSEKEYS { + kty = 1, + alg = 3, + crv = -1, + x = -2, + y = -3, + n = -1, + e = -2, +} + +export type COSEPublicKey = Map; + +export type SafetyNetJWTHeader = { + alg: 'string', + x5c: string[], +}; + +export type SafetyNetJWTPayload = { + nonce: string, + timestampMs: number, + apkPackageName: string, + apkDigestSha256: string, + ctsProfileMatch: boolean, + apkCertificateDigestSha256: string[], + basicIntegrity: boolean, +}; + +export type SafetyNetJWTSignature = string; + +export type ParsedAssertionAuthData = { + rpIdHash: Buffer, + flagsBuf: Buffer, + flags: number, + counter: number, + counterBuf: Buffer, +}; + +/** + * U2F Presence constant + */ +export const U2F_USER_PRESENTED = 0x01; + +/** + * A WebAuthn-compatible device and the information needed to verify assertions by it + */ +export type AuthenticatorDevice = { + base64PublicKey: string, + base64CredentialID: string, + // Number of times this device is expected to have been used + counter: number, +}; -- cgit v1.2.3 From ec4993382244b1153df3d92dd14280a252db4bde Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Wed, 20 May 2020 22:58:00 -0700 Subject: Add new types for credentials as JSON --- packages/typescript-types/src/index.ts | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'packages/typescript-types/src') diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts index 58cc90c..2d9f8d2 100644 --- a/packages/typescript-types/src/index.ts +++ b/packages/typescript-types/src/index.ts @@ -5,6 +5,36 @@ export type AttestationCredentials = { publicKey: PublicKeyCredentialCreationOptions, }; +/** + * A variant of AttestationCredentials suitable for JSON transmission to the browser + * + * Noteworthy values: + * @param challenge A random string of characters. Will be converted to a Uint8Array in the browser + * @param user.id Your unique, internal ID for the user. Will be converted to a Uint8Array in the + * browser + */ +export type AttestationCredentialsJSON = { + publicKey: { + challenge: string, + // The organization registering and authenticating the user + rp: { + name: string, + id: string, + }, + user: { + id: string, + name: string, + displayName: string, + }, + pubKeyCredParams: [{ + alg: -7, + type: 'public-key', + }], + timeout?: number, + attestation: 'direct' | 'indirect', + }, +}; + /** * An object that can be passed into navigator.credentials.get(...) in the browser */ @@ -12,6 +42,31 @@ export type AssertionCredentials = { publicKey: PublicKeyCredentialRequestOptions, }; +/** + * A variant of AssertionCredentials suitable for JSON transmission to the browser + * + * Noteworthy values: + * @param challenge A random string of characters. Will be converted to a Uint8Array in the browser + * @param allowCredentials.id Base64-encoded credentialId. Will be converted to a Uint8Array in the + * browser + */ +export type AssertionCredentialsJSON = { + publicKey: { + // + challenge: string, + allowCredentials: { + // Will be converted to a Uint8Array in the browser + id: string, + type: 'public-key', + transports?: AuthenticatorTransport[], + }[], + // extensions?: AuthenticationExtensionsClientInputs, + rpId?: string, + timeout?: number, + userVerification?: UserVerificationRequirement, + }, +}; + /** * A slightly-modified AuthenticatorAttestationResponse to simplify working with ArrayBuffers that * are base64-encoded in the browser so that they can be sent as JSON to the server. @@ -33,6 +88,7 @@ AuthenticatorAssertionResponse, 'clientDataJSON' | 'authenticatorData' | 'signat base64AuthenticatorData: string; base64ClientDataJSON: string; base64Signature: string; + base64UserHandle: string; } export enum ATTESTATION_FORMATS { -- cgit v1.2.3 From 4b5c9163395b2ba76a784ef51a81e7b1721bd595 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Wed, 20 May 2020 23:27:12 -0700 Subject: Remove unused types --- packages/typescript-types/src/index.ts | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'packages/typescript-types/src') diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts index 2d9f8d2..71e888b 100644 --- a/packages/typescript-types/src/index.ts +++ b/packages/typescript-types/src/index.ts @@ -1,12 +1,6 @@ /** - * An object that can be passed into navigator.credentials.create(...) in the browser - */ -export type AttestationCredentials = { - publicKey: PublicKeyCredentialCreationOptions, -}; - -/** - * A variant of AttestationCredentials suitable for JSON transmission to the browser + * A variant of AttestationCredentials suitable for JSON transmission to the browser to + * (eventually) get passed into navigator.credentials.create(...) in the browser. * * Noteworthy values: * @param challenge A random string of characters. Will be converted to a Uint8Array in the browser @@ -36,14 +30,8 @@ export type AttestationCredentialsJSON = { }; /** - * An object that can be passed into navigator.credentials.get(...) in the browser - */ -export type AssertionCredentials = { - publicKey: PublicKeyCredentialRequestOptions, -}; - -/** - * A variant of AssertionCredentials suitable for JSON transmission to the browser + * A variant of AssertionCredentials suitable for JSON transmission to the browser to + * (eventually) get passed into navigator.credentials.get(...) in the browser. * * Noteworthy values: * @param challenge A random string of characters. Will be converted to a Uint8Array in the browser -- cgit v1.2.3 From 1bf99eca9c356fc41f520491d96963438a18ce00 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Wed, 20 May 2020 23:27:36 -0700 Subject: Add new types for casting credential responses --- packages/typescript-types/src/index.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'packages/typescript-types/src') diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts index 71e888b..4411fec 100644 --- a/packages/typescript-types/src/index.ts +++ b/packages/typescript-types/src/index.ts @@ -55,6 +55,20 @@ export type AssertionCredentialsJSON = { }, }; +/** + * The value returned from navigator.credentials.create() + */ +export interface AttestationCredential extends PublicKeyCredential { + response: AuthenticatorAttestationResponse; +} + +/** + * The value returned from navigator.credentials.get() + */ +export interface AssertionCredential extends PublicKeyCredential { + response: AuthenticatorAssertionResponse; +} + /** * A slightly-modified AuthenticatorAttestationResponse to simplify working with ArrayBuffers that * are base64-encoded in the browser so that they can be sent as JSON to the server. -- cgit v1.2.3 From e9cb351795ca31b583be534b3347376e61b1c2c3 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Wed, 20 May 2020 23:37:27 -0700 Subject: Rename some types --- packages/server/src/assertion/generateAssertionCredentials.ts | 4 ++-- packages/server/src/attestation/generateAttestationCredentials.ts | 4 ++-- packages/typescript-types/src/index.ts | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'packages/typescript-types/src') diff --git a/packages/server/src/assertion/generateAssertionCredentials.ts b/packages/server/src/assertion/generateAssertionCredentials.ts index 91232e9..b6c5d0c 100644 --- a/packages/server/src/assertion/generateAssertionCredentials.ts +++ b/packages/server/src/assertion/generateAssertionCredentials.ts @@ -1,4 +1,4 @@ -import { AssertionCredentialsJSON } from '@webauthntine/typescript-types'; +import { PublicKeyCredentialRequestOptionsJSON } from '@webauthntine/typescript-types'; /** @@ -13,7 +13,7 @@ export default function generateAssertionCredentials( challenge: string, base64CredentialIDs: string[], timeout: number = 60000, -): AssertionCredentialsJSON { +): PublicKeyCredentialRequestOptionsJSON { return { publicKey: { challenge, diff --git a/packages/server/src/attestation/generateAttestationCredentials.ts b/packages/server/src/attestation/generateAttestationCredentials.ts index 53afc84..15cd947 100644 --- a/packages/server/src/attestation/generateAttestationCredentials.ts +++ b/packages/server/src/attestation/generateAttestationCredentials.ts @@ -1,4 +1,4 @@ -import { AttestationCredentialsJSON } from '@webauthntine/typescript-types'; +import { PublicKeyCredentialCreationOptionsJSON } from '@webauthntine/typescript-types'; /** @@ -20,7 +20,7 @@ export default function generateAttestationCredentials( username: string, timeout: number = 60000, attestationType: 'direct' | 'indirect' = 'direct', -): AttestationCredentialsJSON { +): PublicKeyCredentialCreationOptionsJSON { return { publicKey: { // Cryptographically random bytes to prevent replay attacks diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts index 4411fec..8ab5763 100644 --- a/packages/typescript-types/src/index.ts +++ b/packages/typescript-types/src/index.ts @@ -1,5 +1,5 @@ /** - * A variant of AttestationCredentials suitable for JSON transmission to the browser to + * A variant of PublicKeyCredentialCreationOptions suitable for JSON transmission to the browser to * (eventually) get passed into navigator.credentials.create(...) in the browser. * * Noteworthy values: @@ -7,7 +7,7 @@ * @param user.id Your unique, internal ID for the user. Will be converted to a Uint8Array in the * browser */ -export type AttestationCredentialsJSON = { +export type PublicKeyCredentialCreationOptionsJSON = { publicKey: { challenge: string, // The organization registering and authenticating the user @@ -30,7 +30,7 @@ export type AttestationCredentialsJSON = { }; /** - * A variant of AssertionCredentials suitable for JSON transmission to the browser to + * A variant of PublicKeyCredentialRequestOptions suitable for JSON transmission to the browser to * (eventually) get passed into navigator.credentials.get(...) in the browser. * * Noteworthy values: @@ -38,7 +38,7 @@ export type AttestationCredentialsJSON = { * @param allowCredentials.id Base64-encoded credentialId. Will be converted to a Uint8Array in the * browser */ -export type AssertionCredentialsJSON = { +export type PublicKeyCredentialRequestOptionsJSON = { publicKey: { // challenge: string, -- cgit v1.2.3 From dddf3c30d104de7c5fa9da055dd52ed00d8ddaf9 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Wed, 20 May 2020 23:53:15 -0700 Subject: Refine type naming --- packages/browser/src/methods/startAttestation.ts | 4 ++-- packages/server/src/assertion/verifyAssertionResponse.ts | 4 ++-- packages/server/src/attestation/verifyAttestationResponse.ts | 4 ++-- packages/typescript-types/src/index.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'packages/typescript-types/src') diff --git a/packages/browser/src/methods/startAttestation.ts b/packages/browser/src/methods/startAttestation.ts index 3b955cc..af28e13 100644 --- a/packages/browser/src/methods/startAttestation.ts +++ b/packages/browser/src/methods/startAttestation.ts @@ -1,6 +1,6 @@ import { PublicKeyCredentialCreationOptionsJSON, - EncodedAuthenticatorAttestationResponse, + AuthenticatorAttestationResponseJSON, AttestationCredential, } from '@webauthntine/typescript-types'; @@ -13,7 +13,7 @@ import supportsWebauthn from '../helpers/supportsWebauthn'; */ export default async function startAttestation( creationOptionsJSON: PublicKeyCredentialCreationOptionsJSON -): Promise { +): Promise { if (!supportsWebauthn()) { throw new Error('Webauthn is not supported in this browser'); } diff --git a/packages/server/src/assertion/verifyAssertionResponse.ts b/packages/server/src/assertion/verifyAssertionResponse.ts index d906e76..2a5dd8f 100644 --- a/packages/server/src/assertion/verifyAssertionResponse.ts +++ b/packages/server/src/assertion/verifyAssertionResponse.ts @@ -1,6 +1,6 @@ import base64url from 'base64url'; import { - EncodedAuthenticatorAssertionResponse, + AuthenticatorAssertionResponseJSON, U2F_USER_PRESENTED, AuthenticatorDevice, VerifiedAssertion, @@ -20,7 +20,7 @@ import verifySignature from '@helpers/verifySignature'; * @param expectedOrigin Expected URL of website attestation should have occurred on */ export default function verifyAssertionResponse( - response: EncodedAuthenticatorAssertionResponse, + response: AuthenticatorAssertionResponseJSON, expectedOrigin: string, authenticator: AuthenticatorDevice, ): VerifiedAssertion { diff --git a/packages/server/src/attestation/verifyAttestationResponse.ts b/packages/server/src/attestation/verifyAttestationResponse.ts index ad226eb..9b90391 100644 --- a/packages/server/src/attestation/verifyAttestationResponse.ts +++ b/packages/server/src/attestation/verifyAttestationResponse.ts @@ -1,6 +1,6 @@ import decodeAttestationObject from '@helpers/decodeAttestationObject'; import decodeClientDataJSON from '@helpers/decodeClientDataJSON'; -import { ATTESTATION_FORMATS, EncodedAuthenticatorAttestationResponse, VerifiedAttestation } from '@webauthntine/typescript-types'; +import { ATTESTATION_FORMATS, AuthenticatorAttestationResponseJSON, VerifiedAttestation } from '@webauthntine/typescript-types'; import verifyFIDOU2F from './verifications/verifyFIDOU2F'; import verifyPacked from './verifications/verifyPacked'; @@ -14,7 +14,7 @@ import verifyAndroidSafetynet from './verifications/verifyAndroidSafetyNet'; * @param expectedOrigin Expected URL of website attestation should have occurred on */ export default function verifyAttestationResponse( - response: EncodedAuthenticatorAttestationResponse, + response: AuthenticatorAttestationResponseJSON, expectedOrigin: string, ): VerifiedAttestation { const { base64AttestationObject, base64ClientDataJSON } = response; diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts index 8ab5763..8cb15de 100644 --- a/packages/typescript-types/src/index.ts +++ b/packages/typescript-types/src/index.ts @@ -73,7 +73,7 @@ export interface AssertionCredential extends PublicKeyCredential { * A slightly-modified AuthenticatorAttestationResponse to simplify working with ArrayBuffers that * are base64-encoded in the browser so that they can be sent as JSON to the server. */ -export interface EncodedAuthenticatorAttestationResponse extends Omit< +export interface AuthenticatorAttestationResponseJSON extends Omit< AuthenticatorAttestationResponse, 'clientDataJSON' | 'attestationObject' > { base64ClientDataJSON: string, @@ -84,7 +84,7 @@ AuthenticatorAttestationResponse, 'clientDataJSON' | 'attestationObject' * A slightly-modified AuthenticatorAttestationResponse to simplify working with ArrayBuffers that * are base64-encoded in the browser so that they can be sent as JSON to the server. */ -export interface EncodedAuthenticatorAssertionResponse extends Omit< +export interface AuthenticatorAssertionResponseJSON extends Omit< AuthenticatorAssertionResponse, 'clientDataJSON' | 'authenticatorData' | 'signature' > { base64AuthenticatorData: string; -- cgit v1.2.3 From 916fd7b32ba03b13b1309faae0ca077eebc4efb9 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Thu, 21 May 2020 08:40:39 -0700 Subject: Refine AuthenticatorAssertionResponseJSON interface --- packages/typescript-types/src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/typescript-types/src') diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts index 8cb15de..f4cb6ae 100644 --- a/packages/typescript-types/src/index.ts +++ b/packages/typescript-types/src/index.ts @@ -85,12 +85,12 @@ AuthenticatorAttestationResponse, 'clientDataJSON' | 'attestationObject' * are base64-encoded in the browser so that they can be sent as JSON to the server. */ export interface AuthenticatorAssertionResponseJSON extends Omit< -AuthenticatorAssertionResponse, 'clientDataJSON' | 'authenticatorData' | 'signature' +AuthenticatorAssertionResponse, 'clientDataJSON' | 'authenticatorData' | 'signature' | 'userHandle' > { base64AuthenticatorData: string; base64ClientDataJSON: string; base64Signature: string; - base64UserHandle: string; + base64UserHandle?: string; } export enum ATTESTATION_FORMATS { -- cgit v1.2.3 From 99e6a2e86472530cb4be12bef34ea72975a6b75d Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Thu, 21 May 2020 16:45:24 -0700 Subject: Add userVerified property to verified attestations --- .../server/src/attestation/verifications/verifyAndroidSafetyNet.ts | 5 ++++- packages/server/src/attestation/verifications/verifyFIDOU2F.ts | 1 + packages/server/src/attestation/verifications/verifyNone.ts | 1 + packages/server/src/attestation/verifications/verifyPacked.ts | 7 +++++-- packages/typescript-types/src/index.ts | 1 + 5 files changed, 12 insertions(+), 3 deletions(-) (limited to 'packages/typescript-types/src') diff --git a/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts b/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts index e7853aa..0f92613 100644 --- a/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts +++ b/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts @@ -112,6 +112,7 @@ export default function verifyAttestationAndroidSafetyNet( const toReturn: VerifiedAttestation = { verified: verifySignature(signatureBuffer, signatureBaseBuffer, certificate), + userVerified: false, }; /** * END Verify Signature @@ -121,7 +122,9 @@ export default function verifyAttestationAndroidSafetyNet( if (toReturn.verified) { const authDataStruct = parseAttestationAuthData(authData); console.debug('authDataStruct:', authDataStruct); - const { counter, credentialID, COSEPublicKey } = authDataStruct; + const { counter, credentialID, COSEPublicKey, flags } = authDataStruct; + + toReturn.userVerified = flags.uv; if (!COSEPublicKey) { throw new Error('No public key was provided by authenticator'); diff --git a/packages/server/src/attestation/verifications/verifyFIDOU2F.ts b/packages/server/src/attestation/verifications/verifyFIDOU2F.ts index ad9ef63..b60597d 100644 --- a/packages/server/src/attestation/verifications/verifyFIDOU2F.ts +++ b/packages/server/src/attestation/verifications/verifyFIDOU2F.ts @@ -65,6 +65,7 @@ export default function verifyAttestationFIDOU2F( const toReturn: VerifiedAttestation = { verified: verifySignature(sig, signatureBase, publicKeyCertPEM), + userVerified: flags.uv, }; if (toReturn.verified) { diff --git a/packages/server/src/attestation/verifications/verifyNone.ts b/packages/server/src/attestation/verifications/verifyNone.ts index cafb77a..a6b742a 100644 --- a/packages/server/src/attestation/verifications/verifyNone.ts +++ b/packages/server/src/attestation/verifications/verifyNone.ts @@ -49,6 +49,7 @@ export default function verifyAttestationNone( const toReturn: VerifiedAttestation = { verified: true, + userVerified: flags.uv, authenticatorInfo: { fmt, counter, diff --git a/packages/server/src/attestation/verifications/verifyPacked.ts b/packages/server/src/attestation/verifications/verifyPacked.ts index 63b3248..04aff7b 100644 --- a/packages/server/src/attestation/verifications/verifyPacked.ts +++ b/packages/server/src/attestation/verifications/verifyPacked.ts @@ -24,7 +24,7 @@ export default function verifyAttestationPacked(attestationObject: AttestationOb const authDataStruct = parseAttestationAuthData(authData); - const { COSEPublicKey, counter, credentialID } = authDataStruct; + const { COSEPublicKey, counter, credentialID, flags } = authDataStruct; if (!COSEPublicKey) { throw new Error('No public key was provided by authenticator'); @@ -45,7 +45,10 @@ export default function verifyAttestationPacked(attestationObject: AttestationOb clientDataHash, ]); - const toReturn: VerifiedAttestation = { verified: false }; + const toReturn: VerifiedAttestation = { + verified: false, + userVerified: flags.uv, + }; const publicKey = convertCOSEtoPKCS(COSEPublicKey); if (x5c) { diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts index f4cb6ae..15771b0 100644 --- a/packages/typescript-types/src/index.ts +++ b/packages/typescript-types/src/index.ts @@ -139,6 +139,7 @@ export type ClientDataJSON = { */ export type VerifiedAttestation = { verified: boolean, + userVerified: boolean; authenticatorInfo?: { fmt: ATTESTATION_FORMATS, counter: number, -- cgit v1.2.3