@simplewebauthn/server
Advanced tools
Comparing version 10.0.1 to 11.0.0
@@ -1,2 +0,2 @@ | ||
import type { AuthenticationResponseJSON, AuthenticatorDevice, Base64URLString, CredentialDeviceType, UserVerificationRequirement } from '../deps.js'; | ||
import type { AuthenticationResponseJSON, Base64URLString, CredentialDeviceType, UserVerificationRequirement, WebAuthnCredential } from '../deps.js'; | ||
import { AuthenticationExtensionsAuthenticatorOutputs } from '../helpers/decodeAuthenticatorExtensions.js'; | ||
@@ -8,3 +8,3 @@ export type VerifyAuthenticationResponseOpts = { | ||
expectedRPID: string | string[]; | ||
authenticator: AuthenticatorDevice; | ||
credential: WebAuthnCredential; | ||
expectedType?: string | string[]; | ||
@@ -25,3 +25,3 @@ requireUserVerification?: boolean; | ||
* @param expectedRPID - RP ID (or array of IDs) that was specified in the registration options | ||
* @param authenticator - An internal {@link AuthenticatorDevice} matching the credential's ID | ||
* @param credential - An internal {@link WebAuthnCredential} corresponding to `id` in the authentication response | ||
* @param expectedType **(Optional)** - The response type expected ('webauthn.get') | ||
@@ -28,0 +28,0 @@ * @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true` |
@@ -17,3 +17,3 @@ import { decodeClientDataJSON } from '../helpers/decodeClientDataJSON.js'; | ||
* @param expectedRPID - RP ID (or array of IDs) that was specified in the registration options | ||
* @param authenticator - An internal {@link AuthenticatorDevice} matching the credential's ID | ||
* @param credential - An internal {@link WebAuthnCredential} corresponding to `id` in the authentication response | ||
* @param expectedType **(Optional)** - The response type expected ('webauthn.get') | ||
@@ -25,3 +25,3 @@ * @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true` | ||
export async function verifyAuthenticationResponse(options) { | ||
const { response, expectedChallenge, expectedOrigin, expectedRPID, expectedType, authenticator, requireUserVerification = true, advancedFIDOConfig, } = options; | ||
const { response, expectedChallenge, expectedOrigin, expectedRPID, expectedType, credential, requireUserVerification = true, advancedFIDOConfig, } = options; | ||
const { id, rawId, type: credentialType, response: assertionResponse } = response; | ||
@@ -146,4 +146,4 @@ // Ensure credential specified an ID | ||
const signature = isoBase64URL.toBuffer(assertionResponse.signature); | ||
if ((counter > 0 || authenticator.counter > 0) && | ||
counter <= authenticator.counter) { | ||
if ((counter > 0 || credential.counter > 0) && | ||
counter <= credential.counter) { | ||
// Error out when the counter in the DB is greater than or equal to the counter in the | ||
@@ -153,3 +153,3 @@ // dataStruct. It's related to how the authenticator maintains the number of times its been | ||
// on the device without going through this site | ||
throw new Error(`Response counter value ${counter} was lower than expected ${authenticator.counter}`); | ||
throw new Error(`Response counter value ${counter} was lower than expected ${credential.counter}`); | ||
} | ||
@@ -161,7 +161,7 @@ const { credentialDeviceType, credentialBackedUp } = parseBackupFlags(flags); | ||
data: signatureBase, | ||
credentialPublicKey: authenticator.credentialPublicKey, | ||
credentialPublicKey: credential.publicKey, | ||
}), | ||
authenticationInfo: { | ||
newCounter: counter, | ||
credentialID: authenticator.credentialID, | ||
credentialID: credential.id, | ||
userVerified: flags.uv, | ||
@@ -168,0 +168,0 @@ credentialDeviceType, |
@@ -1,9 +0,9 @@ | ||
export type { AttestationConveyancePreference, AuthenticationExtensionsClientInputs, AuthenticationResponseJSON, AuthenticatorDevice, AuthenticatorSelectionCriteria, AuthenticatorTransportFuture, Base64URLString, COSEAlgorithmIdentifier, CredentialDeviceType, Crypto, PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialParameters, PublicKeyCredentialRequestOptionsJSON, RegistrationResponseJSON, UserVerificationRequirement, } from '@simplewebauthn/types'; | ||
export type { AttestationConveyancePreference, AuthenticationExtensionsClientInputs, AuthenticationResponseJSON, AuthenticatorSelectionCriteria, AuthenticatorTransportFuture, Base64URLString, COSEAlgorithmIdentifier, CredentialDeviceType, Crypto, PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialParameters, PublicKeyCredentialRequestOptionsJSON, RegistrationResponseJSON, UserVerificationRequirement, WebAuthnCredential, } from '@simplewebauthn/types'; | ||
export * as tinyCbor from '@levischuck/tiny-cbor'; | ||
export { default as base64 } from '@hexagon/base64'; | ||
export { fetch as crossFetch } from 'cross-fetch'; | ||
export { AsnParser, AsnSerializer } from '@peculiar/asn1-schema'; | ||
export { AuthorityKeyIdentifier, BasicConstraints, Certificate, CertificateList, CRLDistributionPoints, ExtendedKeyUsage, id_ce_authorityKeyIdentifier, id_ce_basicConstraints, id_ce_cRLDistributionPoints, id_ce_extKeyUsage, id_ce_subjectAltName, id_ce_subjectKeyIdentifier, Name, SubjectAlternativeName, SubjectKeyIdentifier, } from '@peculiar/asn1-x509'; | ||
export { AsnParser, AsnSerializer, OctetString } from '@peculiar/asn1-schema'; | ||
export { AuthorityKeyIdentifier, BasicConstraints, Certificate, CertificateList, CRLDistributionPoints, ExtendedKeyUsage, Extensions, id_ce_authorityKeyIdentifier, id_ce_basicConstraints, id_ce_cRLDistributionPoints, id_ce_extKeyUsage, id_ce_subjectAltName, id_ce_subjectKeyIdentifier, Name, SubjectAlternativeName, SubjectKeyIdentifier, } from '@peculiar/asn1-x509'; | ||
export { ECDSASigValue, ECParameters, id_ecPublicKey, id_secp256r1, id_secp384r1, } from '@peculiar/asn1-ecc'; | ||
export { RSAPublicKey } from '@peculiar/asn1-rsa'; | ||
export { id_ce_keyDescription, KeyDescription } from '@peculiar/asn1-android'; |
@@ -8,6 +8,6 @@ // tiny_cbor (a.k.a. tiny-cbor in Node land) | ||
// @peculiar libraries | ||
export { AsnParser, AsnSerializer } from '@peculiar/asn1-schema'; | ||
export { AuthorityKeyIdentifier, BasicConstraints, Certificate, CertificateList, CRLDistributionPoints, ExtendedKeyUsage, id_ce_authorityKeyIdentifier, id_ce_basicConstraints, id_ce_cRLDistributionPoints, id_ce_extKeyUsage, id_ce_subjectAltName, id_ce_subjectKeyIdentifier, Name, SubjectAlternativeName, SubjectKeyIdentifier, } from '@peculiar/asn1-x509'; | ||
export { AsnParser, AsnSerializer, OctetString } from '@peculiar/asn1-schema'; | ||
export { AuthorityKeyIdentifier, BasicConstraints, Certificate, CertificateList, CRLDistributionPoints, ExtendedKeyUsage, Extensions, id_ce_authorityKeyIdentifier, id_ce_basicConstraints, id_ce_cRLDistributionPoints, id_ce_extKeyUsage, id_ce_subjectAltName, id_ce_subjectKeyIdentifier, Name, SubjectAlternativeName, SubjectKeyIdentifier, } from '@peculiar/asn1-x509'; | ||
export { ECDSASigValue, ECParameters, id_ecPublicKey, id_secp256r1, id_secp384r1, } from '@peculiar/asn1-ecc'; | ||
export { RSAPublicKey } from '@peculiar/asn1-rsa'; | ||
export { id_ce_keyDescription, KeyDescription } from '@peculiar/asn1-android'; |
@@ -7,15 +7,5 @@ /** | ||
export declare function decodeAuthenticatorExtensions(extensionData: Uint8Array): AuthenticationExtensionsAuthenticatorOutputs | undefined; | ||
export type AuthenticationExtensionsAuthenticatorOutputs = { | ||
devicePubKey?: DevicePublicKeyAuthenticatorOutput; | ||
uvm?: UVMAuthenticatorOutput; | ||
}; | ||
export type DevicePublicKeyAuthenticatorOutput = { | ||
dpk?: Uint8Array; | ||
sig?: string; | ||
nonce?: Uint8Array; | ||
scope?: Uint8Array; | ||
aaguid?: Uint8Array; | ||
}; | ||
export type UVMAuthenticatorOutput = { | ||
uvm?: Uint8Array[]; | ||
}; | ||
/** | ||
* Attempt to support authenticator extensions we might not know about in WebAuthn | ||
*/ | ||
export type AuthenticationExtensionsAuthenticatorOutputs = unknown; |
@@ -112,2 +112,6 @@ // deno-lint-ignore-file no-dupe-keys | ||
}, | ||
'id:49424D00': { | ||
name: 'IBM', | ||
id: 'IBM', | ||
}, | ||
'id:49465800': { | ||
@@ -114,0 +118,0 @@ name: 'Infineon', |
@@ -10,2 +10,3 @@ import { AsnParser, Certificate, ExtendedKeyUsage, id_ce_extKeyUsage, id_ce_subjectAltName, SubjectAlternativeName, } from '../../../deps.js'; | ||
import { isoUint8Array } from '../../../helpers/iso/index.js'; | ||
import { validateExtFIDOGenCEAAGUID } from '../../../helpers/validateExtFIDOGenCEAAGUID.js'; | ||
import { MetadataService } from '../../../services/metadataService.js'; | ||
@@ -210,4 +211,10 @@ import { verifyAttestationWithMetadata } from '../../../metadata/verifyAttestationWithMetadata.js'; | ||
} | ||
// TODO: If certificate contains id-fido-gen-ce-aaguid(1.3.6.1.4.1.45724.1.1.4) extension, check | ||
// that it’s value is set to the same AAGUID as in authData. | ||
// Validate attestation statement AAGUID against leaf cert AAGUID | ||
try { | ||
await validateExtFIDOGenCEAAGUID(parsedCert.tbsCertificate.extensions, aaguid); | ||
} | ||
catch (err) { | ||
const _err = err; | ||
throw new Error(`${_err.message} (TPM)`); | ||
} | ||
// Run some metadata checks if a statement exists for this authenticator | ||
@@ -214,0 +221,0 @@ const statement = await MetadataService.getStatement(aaguid); |
@@ -7,2 +7,3 @@ import { isCOSEAlg } from '../../helpers/cose.js'; | ||
import { isoUint8Array } from '../../helpers/iso/index.js'; | ||
import { validateExtFIDOGenCEAAGUID } from '../../helpers/validateExtFIDOGenCEAAGUID.js'; | ||
import { MetadataService } from '../../services/metadataService.js'; | ||
@@ -30,3 +31,3 @@ import { verifyAttestationWithMetadata } from '../../metadata/verifyAttestationWithMetadata.js'; | ||
if (x5c) { | ||
const { subject, basicConstraintsCA, version, notBefore, notAfter } = getCertificateInfo(x5c[0]); | ||
const { subject, basicConstraintsCA, version, notBefore, notAfter, parsedCertificate, } = getCertificateInfo(x5c[0]); | ||
const { OU, CN, O, C } = subject; | ||
@@ -59,4 +60,10 @@ if (OU !== 'Authenticator Attestation') { | ||
} | ||
// TODO: If certificate contains id-fido-gen-ce-aaguid(1.3.6.1.4.1.45724.1.1.4) extension, check | ||
// that it’s value is set to the same AAGUID as in authData. | ||
// Validate attestation statement AAGUID against leaf cert AAGUID | ||
try { | ||
await validateExtFIDOGenCEAAGUID(parsedCertificate.tbsCertificate.extensions, aaguid); | ||
} | ||
catch (err) { | ||
const _err = err; | ||
throw new Error(`${_err.message} (Packed|Full)`); | ||
} | ||
// If available, validate attestation alg and x5c with info in the metadata statement | ||
@@ -63,0 +70,0 @@ const statement = await MetadataService.getStatement(aaguid); |
@@ -1,2 +0,2 @@ | ||
import type { Base64URLString, COSEAlgorithmIdentifier, CredentialDeviceType, RegistrationResponseJSON } from '../deps.js'; | ||
import type { COSEAlgorithmIdentifier, CredentialDeviceType, RegistrationResponseJSON, WebAuthnCredential } from '../deps.js'; | ||
import { AttestationFormat, AttestationStatement } from '../helpers/decodeAttestationObject.js'; | ||
@@ -10,2 +10,3 @@ import { AuthenticationExtensionsAuthenticatorOutputs } from '../helpers/decodeAuthenticatorExtensions.js'; | ||
expectedType?: string | string[]; | ||
requireUserPresence?: boolean; | ||
requireUserVerification?: boolean; | ||
@@ -24,2 +25,3 @@ supportedAlgorithmIDs?: COSEAlgorithmIdentifier[]; | ||
* @param expectedType **(Optional)** - The response type expected ('webauthn.create') | ||
* @param requireUserPresence **(Optional)** - Enforce user presence by the authenticator (or skip it during auto registration) Defaults to `true` | ||
* @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true` | ||
@@ -59,6 +61,4 @@ * @param supportedAlgorithmIDs **(Optional)** - Array of numeric COSE algorithm identifiers supported for attestation by this RP. See https://www.iana.org/assignments/cose/cose.xhtml#algorithms. Defaults to all supported algorithm IDs | ||
fmt: AttestationFormat; | ||
counter: number; | ||
aaguid: string; | ||
credentialID: Base64URLString; | ||
credentialPublicKey: Uint8Array; | ||
credential: WebAuthnCredential; | ||
credentialType: 'public-key'; | ||
@@ -65,0 +65,0 @@ attestationObject: Uint8Array; |
@@ -29,2 +29,3 @@ import { decodeAttestationObject, } from '../helpers/decodeAttestationObject.js'; | ||
* @param expectedType **(Optional)** - The response type expected ('webauthn.create') | ||
* @param requireUserPresence **(Optional)** - Enforce user presence by the authenticator (or skip it during auto registration) Defaults to `true` | ||
* @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true` | ||
@@ -34,3 +35,3 @@ * @param supportedAlgorithmIDs **(Optional)** - Array of numeric COSE algorithm identifiers supported for attestation by this RP. See https://www.iana.org/assignments/cose/cose.xhtml#algorithms. Defaults to all supported algorithm IDs | ||
export async function verifyRegistrationResponse(options) { | ||
const { response, expectedChallenge, expectedOrigin, expectedRPID, expectedType, requireUserVerification = true, supportedAlgorithmIDs = supportedCOSEAlgorithmIdentifiers, } = options; | ||
const { response, expectedChallenge, expectedOrigin, expectedRPID, expectedType, requireUserPresence = true, requireUserVerification = true, supportedAlgorithmIDs = supportedCOSEAlgorithmIdentifiers, } = options; | ||
const { id, rawId, type: credentialType, response: attestationResponse } = response; | ||
@@ -114,8 +115,8 @@ // Ensure credential specified an ID | ||
// Make sure someone was physically present | ||
if (!flags.up) { | ||
throw new Error('User not present during registration'); | ||
if (requireUserPresence && !flags.up) { | ||
throw new Error('User presence was required, but user was not present'); | ||
} | ||
// Enforce user verification if specified | ||
if (requireUserVerification && !flags.uv) { | ||
throw new Error('User verification required, but user could not be verified'); | ||
throw new Error('User verification was required, but user could not be verified'); | ||
} | ||
@@ -195,7 +196,10 @@ if (!credentialID) { | ||
fmt, | ||
counter, | ||
aaguid: convertAAGUIDToString(aaguid), | ||
credentialID: isoBase64URL.fromBuffer(credentialID), | ||
credentialPublicKey, | ||
credentialType, | ||
credential: { | ||
id: isoBase64URL.fromBuffer(credentialID), | ||
publicKey: credentialPublicKey, | ||
counter, | ||
transports: response.response.transports, | ||
}, | ||
attestationObject, | ||
@@ -202,0 +206,0 @@ userVerified: flags.uv, |
@@ -5,3 +5,3 @@ { | ||
"name": "@simplewebauthn/server", | ||
"version": "10.0.1", | ||
"version": "11.0.0", | ||
"description": "SimpleWebAuthn for Servers", | ||
@@ -60,3 +60,3 @@ "license": "MIT", | ||
"@peculiar/asn1-x509": "^2.3.8", | ||
"@simplewebauthn/types": "^10.0.0", | ||
"@simplewebauthn/types": "^11.0.0", | ||
"cross-fetch": "^4.0.0" | ||
@@ -63,0 +63,0 @@ }, |
@@ -1,2 +0,2 @@ | ||
import type { AuthenticationResponseJSON, AuthenticatorDevice, Base64URLString, CredentialDeviceType, UserVerificationRequirement } from '../deps.js'; | ||
import type { AuthenticationResponseJSON, Base64URLString, CredentialDeviceType, UserVerificationRequirement, WebAuthnCredential } from '../deps.js'; | ||
import { AuthenticationExtensionsAuthenticatorOutputs } from '../helpers/decodeAuthenticatorExtensions.js'; | ||
@@ -8,3 +8,3 @@ export type VerifyAuthenticationResponseOpts = { | ||
expectedRPID: string | string[]; | ||
authenticator: AuthenticatorDevice; | ||
credential: WebAuthnCredential; | ||
expectedType?: string | string[]; | ||
@@ -25,3 +25,3 @@ requireUserVerification?: boolean; | ||
* @param expectedRPID - RP ID (or array of IDs) that was specified in the registration options | ||
* @param authenticator - An internal {@link AuthenticatorDevice} matching the credential's ID | ||
* @param credential - An internal {@link WebAuthnCredential} corresponding to `id` in the authentication response | ||
* @param expectedType **(Optional)** - The response type expected ('webauthn.get') | ||
@@ -28,0 +28,0 @@ * @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true` |
@@ -20,3 +20,3 @@ "use strict"; | ||
* @param expectedRPID - RP ID (or array of IDs) that was specified in the registration options | ||
* @param authenticator - An internal {@link AuthenticatorDevice} matching the credential's ID | ||
* @param credential - An internal {@link WebAuthnCredential} corresponding to `id` in the authentication response | ||
* @param expectedType **(Optional)** - The response type expected ('webauthn.get') | ||
@@ -28,3 +28,3 @@ * @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true` | ||
async function verifyAuthenticationResponse(options) { | ||
const { response, expectedChallenge, expectedOrigin, expectedRPID, expectedType, authenticator, requireUserVerification = true, advancedFIDOConfig, } = options; | ||
const { response, expectedChallenge, expectedOrigin, expectedRPID, expectedType, credential, requireUserVerification = true, advancedFIDOConfig, } = options; | ||
const { id, rawId, type: credentialType, response: assertionResponse } = response; | ||
@@ -149,4 +149,4 @@ // Ensure credential specified an ID | ||
const signature = index_js_1.isoBase64URL.toBuffer(assertionResponse.signature); | ||
if ((counter > 0 || authenticator.counter > 0) && | ||
counter <= authenticator.counter) { | ||
if ((counter > 0 || credential.counter > 0) && | ||
counter <= credential.counter) { | ||
// Error out when the counter in the DB is greater than or equal to the counter in the | ||
@@ -156,3 +156,3 @@ // dataStruct. It's related to how the authenticator maintains the number of times its been | ||
// on the device without going through this site | ||
throw new Error(`Response counter value ${counter} was lower than expected ${authenticator.counter}`); | ||
throw new Error(`Response counter value ${counter} was lower than expected ${credential.counter}`); | ||
} | ||
@@ -164,7 +164,7 @@ const { credentialDeviceType, credentialBackedUp } = (0, parseBackupFlags_js_1.parseBackupFlags)(flags); | ||
data: signatureBase, | ||
credentialPublicKey: authenticator.credentialPublicKey, | ||
credentialPublicKey: credential.publicKey, | ||
}), | ||
authenticationInfo: { | ||
newCounter: counter, | ||
credentialID: authenticator.credentialID, | ||
credentialID: credential.id, | ||
userVerified: flags.uv, | ||
@@ -171,0 +171,0 @@ credentialDeviceType, |
@@ -1,9 +0,9 @@ | ||
export type { AttestationConveyancePreference, AuthenticationExtensionsClientInputs, AuthenticationResponseJSON, AuthenticatorDevice, AuthenticatorSelectionCriteria, AuthenticatorTransportFuture, Base64URLString, COSEAlgorithmIdentifier, CredentialDeviceType, Crypto, PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialParameters, PublicKeyCredentialRequestOptionsJSON, RegistrationResponseJSON, UserVerificationRequirement, } from '@simplewebauthn/types'; | ||
export type { AttestationConveyancePreference, AuthenticationExtensionsClientInputs, AuthenticationResponseJSON, AuthenticatorSelectionCriteria, AuthenticatorTransportFuture, Base64URLString, COSEAlgorithmIdentifier, CredentialDeviceType, Crypto, PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialParameters, PublicKeyCredentialRequestOptionsJSON, RegistrationResponseJSON, UserVerificationRequirement, WebAuthnCredential, } from '@simplewebauthn/types'; | ||
export * as tinyCbor from '@levischuck/tiny-cbor'; | ||
export { default as base64 } from '@hexagon/base64'; | ||
export { fetch as crossFetch } from 'cross-fetch'; | ||
export { AsnParser, AsnSerializer } from '@peculiar/asn1-schema'; | ||
export { AuthorityKeyIdentifier, BasicConstraints, Certificate, CertificateList, CRLDistributionPoints, ExtendedKeyUsage, id_ce_authorityKeyIdentifier, id_ce_basicConstraints, id_ce_cRLDistributionPoints, id_ce_extKeyUsage, id_ce_subjectAltName, id_ce_subjectKeyIdentifier, Name, SubjectAlternativeName, SubjectKeyIdentifier, } from '@peculiar/asn1-x509'; | ||
export { AsnParser, AsnSerializer, OctetString } from '@peculiar/asn1-schema'; | ||
export { AuthorityKeyIdentifier, BasicConstraints, Certificate, CertificateList, CRLDistributionPoints, ExtendedKeyUsage, Extensions, id_ce_authorityKeyIdentifier, id_ce_basicConstraints, id_ce_cRLDistributionPoints, id_ce_extKeyUsage, id_ce_subjectAltName, id_ce_subjectKeyIdentifier, Name, SubjectAlternativeName, SubjectKeyIdentifier, } from '@peculiar/asn1-x509'; | ||
export { ECDSASigValue, ECParameters, id_ecPublicKey, id_secp256r1, id_secp384r1, } from '@peculiar/asn1-ecc'; | ||
export { RSAPublicKey } from '@peculiar/asn1-rsa'; | ||
export { id_ce_keyDescription, KeyDescription } from '@peculiar/asn1-android'; |
@@ -29,3 +29,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.KeyDescription = exports.id_ce_keyDescription = exports.RSAPublicKey = exports.id_secp384r1 = exports.id_secp256r1 = exports.id_ecPublicKey = exports.ECParameters = exports.ECDSASigValue = exports.SubjectKeyIdentifier = exports.SubjectAlternativeName = exports.Name = exports.id_ce_subjectKeyIdentifier = exports.id_ce_subjectAltName = exports.id_ce_extKeyUsage = exports.id_ce_cRLDistributionPoints = exports.id_ce_basicConstraints = exports.id_ce_authorityKeyIdentifier = exports.ExtendedKeyUsage = exports.CRLDistributionPoints = exports.CertificateList = exports.Certificate = exports.BasicConstraints = exports.AuthorityKeyIdentifier = exports.AsnSerializer = exports.AsnParser = exports.crossFetch = exports.base64 = exports.tinyCbor = void 0; | ||
exports.KeyDescription = exports.id_ce_keyDescription = exports.RSAPublicKey = exports.id_secp384r1 = exports.id_secp256r1 = exports.id_ecPublicKey = exports.ECParameters = exports.ECDSASigValue = exports.SubjectKeyIdentifier = exports.SubjectAlternativeName = exports.Name = exports.id_ce_subjectKeyIdentifier = exports.id_ce_subjectAltName = exports.id_ce_extKeyUsage = exports.id_ce_cRLDistributionPoints = exports.id_ce_basicConstraints = exports.id_ce_authorityKeyIdentifier = exports.Extensions = exports.ExtendedKeyUsage = exports.CRLDistributionPoints = exports.CertificateList = exports.Certificate = exports.BasicConstraints = exports.AuthorityKeyIdentifier = exports.OctetString = exports.AsnSerializer = exports.AsnParser = exports.crossFetch = exports.base64 = exports.tinyCbor = void 0; | ||
// tiny_cbor (a.k.a. tiny-cbor in Node land) | ||
@@ -43,2 +43,3 @@ exports.tinyCbor = __importStar(require("@levischuck/tiny-cbor")); | ||
Object.defineProperty(exports, "AsnSerializer", { enumerable: true, get: function () { return asn1_schema_1.AsnSerializer; } }); | ||
Object.defineProperty(exports, "OctetString", { enumerable: true, get: function () { return asn1_schema_1.OctetString; } }); | ||
var asn1_x509_1 = require("@peculiar/asn1-x509"); | ||
@@ -51,2 +52,3 @@ Object.defineProperty(exports, "AuthorityKeyIdentifier", { enumerable: true, get: function () { return asn1_x509_1.AuthorityKeyIdentifier; } }); | ||
Object.defineProperty(exports, "ExtendedKeyUsage", { enumerable: true, get: function () { return asn1_x509_1.ExtendedKeyUsage; } }); | ||
Object.defineProperty(exports, "Extensions", { enumerable: true, get: function () { return asn1_x509_1.Extensions; } }); | ||
Object.defineProperty(exports, "id_ce_authorityKeyIdentifier", { enumerable: true, get: function () { return asn1_x509_1.id_ce_authorityKeyIdentifier; } }); | ||
@@ -53,0 +55,0 @@ Object.defineProperty(exports, "id_ce_basicConstraints", { enumerable: true, get: function () { return asn1_x509_1.id_ce_basicConstraints; } }); |
@@ -7,15 +7,5 @@ /** | ||
export declare function decodeAuthenticatorExtensions(extensionData: Uint8Array): AuthenticationExtensionsAuthenticatorOutputs | undefined; | ||
export type AuthenticationExtensionsAuthenticatorOutputs = { | ||
devicePubKey?: DevicePublicKeyAuthenticatorOutput; | ||
uvm?: UVMAuthenticatorOutput; | ||
}; | ||
export type DevicePublicKeyAuthenticatorOutput = { | ||
dpk?: Uint8Array; | ||
sig?: string; | ||
nonce?: Uint8Array; | ||
scope?: Uint8Array; | ||
aaguid?: Uint8Array; | ||
}; | ||
export type UVMAuthenticatorOutput = { | ||
uvm?: Uint8Array[]; | ||
}; | ||
/** | ||
* Attempt to support authenticator extensions we might not know about in WebAuthn | ||
*/ | ||
export type AuthenticationExtensionsAuthenticatorOutputs = unknown; |
@@ -115,2 +115,6 @@ "use strict"; | ||
}, | ||
'id:49424D00': { | ||
name: 'IBM', | ||
id: 'IBM', | ||
}, | ||
'id:49465800': { | ||
@@ -117,0 +121,0 @@ name: 'Infineon', |
@@ -13,2 +13,3 @@ "use strict"; | ||
const index_js_1 = require("../../../helpers/iso/index.js"); | ||
const validateExtFIDOGenCEAAGUID_js_1 = require("../../../helpers/validateExtFIDOGenCEAAGUID.js"); | ||
const metadataService_js_1 = require("../../../services/metadataService.js"); | ||
@@ -213,4 +214,10 @@ const verifyAttestationWithMetadata_js_1 = require("../../../metadata/verifyAttestationWithMetadata.js"); | ||
} | ||
// TODO: If certificate contains id-fido-gen-ce-aaguid(1.3.6.1.4.1.45724.1.1.4) extension, check | ||
// that it’s value is set to the same AAGUID as in authData. | ||
// Validate attestation statement AAGUID against leaf cert AAGUID | ||
try { | ||
await (0, validateExtFIDOGenCEAAGUID_js_1.validateExtFIDOGenCEAAGUID)(parsedCert.tbsCertificate.extensions, aaguid); | ||
} | ||
catch (err) { | ||
const _err = err; | ||
throw new Error(`${_err.message} (TPM)`); | ||
} | ||
// Run some metadata checks if a statement exists for this authenticator | ||
@@ -217,0 +224,0 @@ const statement = await metadataService_js_1.MetadataService.getStatement(aaguid); |
@@ -10,2 +10,3 @@ "use strict"; | ||
const index_js_1 = require("../../helpers/iso/index.js"); | ||
const validateExtFIDOGenCEAAGUID_js_1 = require("../../helpers/validateExtFIDOGenCEAAGUID.js"); | ||
const metadataService_js_1 = require("../../services/metadataService.js"); | ||
@@ -33,3 +34,3 @@ const verifyAttestationWithMetadata_js_1 = require("../../metadata/verifyAttestationWithMetadata.js"); | ||
if (x5c) { | ||
const { subject, basicConstraintsCA, version, notBefore, notAfter } = (0, getCertificateInfo_js_1.getCertificateInfo)(x5c[0]); | ||
const { subject, basicConstraintsCA, version, notBefore, notAfter, parsedCertificate, } = (0, getCertificateInfo_js_1.getCertificateInfo)(x5c[0]); | ||
const { OU, CN, O, C } = subject; | ||
@@ -62,4 +63,10 @@ if (OU !== 'Authenticator Attestation') { | ||
} | ||
// TODO: If certificate contains id-fido-gen-ce-aaguid(1.3.6.1.4.1.45724.1.1.4) extension, check | ||
// that it’s value is set to the same AAGUID as in authData. | ||
// Validate attestation statement AAGUID against leaf cert AAGUID | ||
try { | ||
await (0, validateExtFIDOGenCEAAGUID_js_1.validateExtFIDOGenCEAAGUID)(parsedCertificate.tbsCertificate.extensions, aaguid); | ||
} | ||
catch (err) { | ||
const _err = err; | ||
throw new Error(`${_err.message} (Packed|Full)`); | ||
} | ||
// If available, validate attestation alg and x5c with info in the metadata statement | ||
@@ -66,0 +73,0 @@ const statement = await metadataService_js_1.MetadataService.getStatement(aaguid); |
@@ -1,2 +0,2 @@ | ||
import type { Base64URLString, COSEAlgorithmIdentifier, CredentialDeviceType, RegistrationResponseJSON } from '../deps.js'; | ||
import type { COSEAlgorithmIdentifier, CredentialDeviceType, RegistrationResponseJSON, WebAuthnCredential } from '../deps.js'; | ||
import { AttestationFormat, AttestationStatement } from '../helpers/decodeAttestationObject.js'; | ||
@@ -10,2 +10,3 @@ import { AuthenticationExtensionsAuthenticatorOutputs } from '../helpers/decodeAuthenticatorExtensions.js'; | ||
expectedType?: string | string[]; | ||
requireUserPresence?: boolean; | ||
requireUserVerification?: boolean; | ||
@@ -24,2 +25,3 @@ supportedAlgorithmIDs?: COSEAlgorithmIdentifier[]; | ||
* @param expectedType **(Optional)** - The response type expected ('webauthn.create') | ||
* @param requireUserPresence **(Optional)** - Enforce user presence by the authenticator (or skip it during auto registration) Defaults to `true` | ||
* @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true` | ||
@@ -59,6 +61,4 @@ * @param supportedAlgorithmIDs **(Optional)** - Array of numeric COSE algorithm identifiers supported for attestation by this RP. See https://www.iana.org/assignments/cose/cose.xhtml#algorithms. Defaults to all supported algorithm IDs | ||
fmt: AttestationFormat; | ||
counter: number; | ||
aaguid: string; | ||
credentialID: Base64URLString; | ||
credentialPublicKey: Uint8Array; | ||
credential: WebAuthnCredential; | ||
credentialType: 'public-key'; | ||
@@ -65,0 +65,0 @@ attestationObject: Uint8Array; |
@@ -32,2 +32,3 @@ "use strict"; | ||
* @param expectedType **(Optional)** - The response type expected ('webauthn.create') | ||
* @param requireUserPresence **(Optional)** - Enforce user presence by the authenticator (or skip it during auto registration) Defaults to `true` | ||
* @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true` | ||
@@ -37,3 +38,3 @@ * @param supportedAlgorithmIDs **(Optional)** - Array of numeric COSE algorithm identifiers supported for attestation by this RP. See https://www.iana.org/assignments/cose/cose.xhtml#algorithms. Defaults to all supported algorithm IDs | ||
async function verifyRegistrationResponse(options) { | ||
const { response, expectedChallenge, expectedOrigin, expectedRPID, expectedType, requireUserVerification = true, supportedAlgorithmIDs = generateRegistrationOptions_js_1.supportedCOSEAlgorithmIdentifiers, } = options; | ||
const { response, expectedChallenge, expectedOrigin, expectedRPID, expectedType, requireUserPresence = true, requireUserVerification = true, supportedAlgorithmIDs = generateRegistrationOptions_js_1.supportedCOSEAlgorithmIdentifiers, } = options; | ||
const { id, rawId, type: credentialType, response: attestationResponse } = response; | ||
@@ -117,8 +118,8 @@ // Ensure credential specified an ID | ||
// Make sure someone was physically present | ||
if (!flags.up) { | ||
throw new Error('User not present during registration'); | ||
if (requireUserPresence && !flags.up) { | ||
throw new Error('User presence was required, but user was not present'); | ||
} | ||
// Enforce user verification if specified | ||
if (requireUserVerification && !flags.uv) { | ||
throw new Error('User verification required, but user could not be verified'); | ||
throw new Error('User verification was required, but user could not be verified'); | ||
} | ||
@@ -198,7 +199,10 @@ if (!credentialID) { | ||
fmt, | ||
counter, | ||
aaguid: (0, convertAAGUIDToString_js_1.convertAAGUIDToString)(aaguid), | ||
credentialID: index_js_1.isoBase64URL.fromBuffer(credentialID), | ||
credentialPublicKey, | ||
credentialType, | ||
credential: { | ||
id: index_js_1.isoBase64URL.fromBuffer(credentialID), | ||
publicKey: credentialPublicKey, | ||
counter, | ||
transports: response.response.transports, | ||
}, | ||
attestationObject, | ||
@@ -205,0 +209,0 @@ userVerified: flags.uv, |
488037
273
11207
+ Added@simplewebauthn/types@11.0.0(transitive)
- Removed@simplewebauthn/types@10.0.0(transitive)