summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/server/src/assertion/verifyAssertionResponse.ts17
-rw-r--r--packages/server/src/attestation/parseAttestationAuthData.ts4
-rw-r--r--packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts26
-rw-r--r--packages/server/src/attestation/verifications/verifyFIDOU2F.ts10
-rw-r--r--packages/server/src/attestation/verifications/verifyNone.ts14
-rw-r--r--packages/server/src/attestation/verifications/verifyPacked.ts40
-rw-r--r--packages/server/src/attestation/verifyAttestationResponse.ts20
7 files changed, 37 insertions, 94 deletions
diff --git a/packages/server/src/assertion/verifyAssertionResponse.ts b/packages/server/src/assertion/verifyAssertionResponse.ts
index c126b84..fb668f4 100644
--- a/packages/server/src/assertion/verifyAssertionResponse.ts
+++ b/packages/server/src/assertion/verifyAssertionResponse.ts
@@ -27,28 +27,20 @@ export default function verifyAssertionResponse(
const { base64AuthenticatorData, base64ClientDataJSON, base64Signature } = response;
const clientDataJSON = decodeClientDataJSON(base64ClientDataJSON);
- console.debug('decodedClientDataJSON:', clientDataJSON);
-
const { type, origin } = clientDataJSON;
// Check that the origin is our site
if (origin !== expectedOrigin) {
- console.error('client origin did not equal our origin');
- console.debug('expectedOrigin:', expectedOrigin);
- console.debug('assertion\'s origin:', origin);
- throw new Error('Assertion origin was an unexpected value');
+ throw new Error(`Unexpected assertion origin: ${origin}`);
}
// Make sure we're handling an assertion
if (type !== 'webauthn.get') {
- console.error('type did not equal "webauthn.get"');
- console.debug('attestation\'s type:', type);
- throw new Error('Assertion type was an unexpected value');
+ throw new Error(`Unexpected assertion type: ${type}`);
}
const authDataBuffer = base64url.toBuffer(base64AuthenticatorData);
const authData = parseAssertionAuthData(authDataBuffer);
- console.log('parsed authData:', authData);
if (!(authData.flags & U2F_USER_PRESENTED)) {
throw new Error('User was NOT present during assertion!');
@@ -66,8 +58,9 @@ export default function verifyAssertionResponse(
// dataStruct. It's related to how the authenticator maintains the number of times its been
// used for this client. If this happens, then someone's somehow increased the counter
// on the device without going through this site
- console.debug(`Response counter ${counter} was not greater than ${authenticator.counter}`);
- throw new Error(`Counter in response did not increment from ${authenticator.counter}`);
+ throw new Error(
+ `Response counter value ${counter} was lower than expected ${authenticator.counter}`,
+ );
}
const clientDataHash = toHash(base64url.toBuffer(base64ClientDataJSON));
diff --git a/packages/server/src/attestation/parseAttestationAuthData.ts b/packages/server/src/attestation/parseAttestationAuthData.ts
index 8326c85..b51af5f 100644
--- a/packages/server/src/attestation/parseAttestationAuthData.ts
+++ b/packages/server/src/attestation/parseAttestationAuthData.ts
@@ -4,8 +4,6 @@ import { ParsedAttestationAuthData } from "@webauthntine/typescript-types";
* Make sense of the authData buffer contained in an Attestation
*/
export default function parseAttestationAuthData(authData: Buffer): ParsedAttestationAuthData {
- console.log('parsing attestation auth data');
-
let intBuffer = authData;
const rpIdHash = intBuffer.slice(0, 32);
@@ -24,8 +22,6 @@ export default function parseAttestationAuthData(authData: Buffer): ParsedAttest
flagsInt,
};
- console.debug('flags:', flags);
-
const counterBuf = intBuffer.slice(0, 4);
intBuffer = intBuffer.slice(4);
diff --git a/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts b/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts
index 0f92613..6f5365a 100644
--- a/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts
+++ b/packages/server/src/attestation/verifications/verifyAndroidSafetyNet.ts
@@ -25,7 +25,7 @@ export default function verifyAttestationAndroidSafetyNet(
const { attStmt, authData, fmt } = attestationObject;
if (!attStmt.response) {
- throw new Error('No response was included in attStmt by authenticator');
+ throw new Error('No response was included in attStmt by authenticator (SafetyNet)');
}
// Prepare to verify a JWT
@@ -36,10 +36,6 @@ export default function verifyAttestationAndroidSafetyNet(
const PAYLOAD: SafetyNetJWTPayload = JSON.parse(base64url.decode(jwtParts[1]));
const SIGNATURE: SafetyNetJWTSignature = jwtParts[2];
- console.debug('HEADER:', HEADER);
- console.debug('PAYLOAD:', PAYLOAD);
- console.debug('SIGNATURE:', SIGNATURE);
-
/**
* START Verify PAYLOAD
*/
@@ -54,16 +50,11 @@ export default function verifyAttestationAndroidSafetyNet(
const expectedNonce = nonceBuffer.toString('base64');
if (nonce !== expectedNonce) {
- console.error('Payload nonce was not the expected value!');
- console.debug('payload nonce:', PAYLOAD.nonce);
- console.debug('expected nonce:', expectedNonce);
- throw new Error('Could not verify response payload nonce');
+ throw new Error('Could not verify payload nonce (SafetyNet)');
}
if (!ctsProfileMatch) {
- console.error('ctsProfileMatch was false!');
- console.debug('ctsProfileMatch:', ctsProfileMatch);
- throw new Error('Could not verify response payload profile');
+ throw new Error('Could not verify device integrity (SafetyNet)');
}
/**
* END Verify PAYLOAD
@@ -83,19 +74,15 @@ export default function verifyAttestationAndroidSafetyNet(
return `-----BEGIN CERTIFICATE-----\n${pem}-----END CERTIFICATE-----`;
});
- console.debug('fullpathCert:', fullpathCert);
-
const certificate = fullpathCert[0];
const commonCertInfo = getCertificateInfo(certificate);
- console.debug('commonCertInfo:', commonCertInfo);
const { subject } = commonCertInfo;
// TODO: Find out where this CN string is specified and if it might change
if (subject.CN !== 'attest.android.com') {
- console.error('common name was not "attest.android.com"');
- throw new Error('Could not verify certificate common name');
+ throw new Error('Certificate common name was not "attest.android.com" (SafetyNet)');
}
// TODO: Re-investigate this if we decide to "use MDS or Metadata Statements"
@@ -121,17 +108,16 @@ export default function verifyAttestationAndroidSafetyNet(
if (toReturn.verified) {
const authDataStruct = parseAttestationAuthData(authData);
- console.debug('authDataStruct:', authDataStruct);
const { counter, credentialID, COSEPublicKey, flags } = authDataStruct;
toReturn.userVerified = flags.uv;
if (!COSEPublicKey) {
- throw new Error('No public key was provided by authenticator');
+ throw new Error('No public key was provided by authenticator (SafetyNet)');
}
if (!credentialID) {
- throw new Error('No credential ID was provided by authenticator');
+ throw new Error('No credential ID was provided by authenticator (SafetyNet)');
}
const publicKey = convertCOSEtoPKCS(COSEPublicKey);
diff --git a/packages/server/src/attestation/verifications/verifyFIDOU2F.ts b/packages/server/src/attestation/verifications/verifyFIDOU2F.ts
index b60597d..75e664f 100644
--- a/packages/server/src/attestation/verifications/verifyFIDOU2F.ts
+++ b/packages/server/src/attestation/verifications/verifyFIDOU2F.ts
@@ -28,15 +28,15 @@ export default function verifyAttestationFIDOU2F(
} = authDataStruct;
if (!(flags.flagsInt & U2F_USER_PRESENTED)) {
- throw new Error('User was NOT present during authentication');
+ throw new Error('User was NOT present during authentication (FIDOU2F)');
}
if (!COSEPublicKey) {
- throw new Error('No public key was provided by authenticator');
+ throw new Error('No public key was provided by authenticator (FIDOU2F)');
}
if (!credentialID) {
- throw new Error('No credential ID was provided by authenticator');
+ throw new Error('No credential ID was provided by authenticator (FIDOU2F)');
}
const clientDataHash = toHash(base64url.toBuffer(base64ClientDataJSON));
@@ -54,11 +54,11 @@ export default function verifyAttestationFIDOU2F(
const { sig, x5c } = attStmt;
if (!x5c) {
- throw new Error('No attestation certificate provided in attestation statement');
+ throw new Error('No attestation certificate provided in attestation statement (FIDOU2F)');
}
if (!sig) {
- throw new Error('No attestation signature provided in attestation statement');
+ throw new Error('No attestation signature provided in attestation statement (FIDOU2F)');
}
const publicKeyCertPEM = convertASN1toPEM(x5c[0]);
diff --git a/packages/server/src/attestation/verifications/verifyNone.ts b/packages/server/src/attestation/verifications/verifyNone.ts
index a6b742a..4f967d1 100644
--- a/packages/server/src/attestation/verifications/verifyNone.ts
+++ b/packages/server/src/attestation/verifications/verifyNone.ts
@@ -17,8 +17,6 @@ export default function verifyAttestationNone(
const { fmt, authData } = attestationObject;
const authDataStruct = parseAttestationAuthData(authData);
- console.log('authDataStruct:', authDataStruct);
-
const {
credentialID,
COSEPublicKey,
@@ -27,22 +25,16 @@ export default function verifyAttestationNone(
} = authDataStruct;
if (!COSEPublicKey) {
- throw new Error('No public key was provided by authenticator');
+ throw new Error('No public key was provided by authenticator (None)');
}
if (!credentialID) {
- throw new Error('No credential ID was provided by authenticator');
+ throw new Error('No credential ID was provided by authenticator (None)');
}
// Make sure the (U)ser (P)resent for the attestation
if (!flags.up) {
- console.error('User was not Present for attestation');
- console.debug('attestation\'s flags:', flags);
- throw new Error('User presence could not be verified');
- }
-
- if (!flags.uv) {
- console.warn('The authenticator could not uniquely Verify the user');
+ throw new Error('User was not present for attestation (None)');
}
const publicKey = convertCOSEtoPKCS(COSEPublicKey);
diff --git a/packages/server/src/attestation/verifications/verifyPacked.ts b/packages/server/src/attestation/verifications/verifyPacked.ts
index 04aff7b..18e195f 100644
--- a/packages/server/src/attestation/verifications/verifyPacked.ts
+++ b/packages/server/src/attestation/verifications/verifyPacked.ts
@@ -27,15 +27,15 @@ export default function verifyAttestationPacked(attestationObject: AttestationOb
const { COSEPublicKey, counter, credentialID, flags } = authDataStruct;
if (!COSEPublicKey) {
- throw new Error('No public key was provided by authenticator');
+ throw new Error('No public key was provided by authenticator (Packed)');
}
if (!credentialID) {
- throw new Error('No credential ID was provided by authenticator');
+ throw new Error('No credential ID was provided by authenticator (Packed)');
}
if (!sig) {
- throw new Error('No attestation signature provided in attestation statement');
+ throw new Error('No attestation signature provided in attestation statement (Packed)');
}
const clientDataHash = toHash(base64url.toBuffer(base64ClientDataJSON));
@@ -52,8 +52,6 @@ export default function verifyAttestationPacked(attestationObject: AttestationOb
const publicKey = convertCOSEtoPKCS(COSEPublicKey);
if (x5c) {
- console.log('FULL Attestation');
-
const leafCert = convertASN1toPEM(x5c[0]);
const leafCertInfo = getCertificateInfo(leafCert);
@@ -66,57 +64,53 @@ export default function verifyAttestationPacked(attestationObject: AttestationOb
} = subject;
if (OU !== 'Authenticator Attestation') {
- throw new Error('Batch certificate OU MUST be set strictly to "Authenticator Attestation"!');
+ throw new Error('Batch certificate OU MUST be set strictly to "Authenticator Attestation"! (Packed|Full');
}
if (!CN) {
- throw new Error('Batch certificate CN MUST no be empty!');
+ throw new Error('Batch certificate CN MUST no be empty! (Packed|Full');
}
if (!O) {
- throw new Error('Batch certificate CN MUST no be empty!');
+ throw new Error('Batch certificate CN MUST no be empty! (Packed|Full');
}
if (!C || C.length !== 2) {
- throw new Error('Batch certificate C MUST be set to two character ISO 3166 code!');
+ throw new Error('Batch certificate C MUST be set to two character ISO 3166 code! (Packed|Full');
}
if (basicConstraintsCA) {
- throw new Error('Batch certificate basic constraints CA MUST be false!');
+ throw new Error('Batch certificate basic constraints CA MUST be false! (Packed|Full');
}
if (version !== 3) {
- throw new Error('Batch certificate version MUST be 3(ASN1 2)!');
+ throw new Error('Batch certificate version MUST be 3(ASN1 2)! (Packed|Full');
}
toReturn.verified = verifySignature(sig, signatureBase, leafCert);
} else if (ecdaaKeyId) {
- throw new Error('ECDAA not supported yet');
+ throw new Error('ECDAA not supported yet (Packed|ECDAA)');
} else {
- console.log('SELF Attestation');
-
const cosePublicKey: COSEPublicKey = cbor.decodeAllSync(COSEPublicKey)[0];
const kty = cosePublicKey.get(COSEKEYS.kty);
const alg = cosePublicKey.get(COSEKEYS.alg);
if (!alg) {
- throw new Error('COSE public key was missing alg');
+ throw new Error('COSE public key was missing alg (Packed|Self)');
}
if (!kty) {
- throw new Error('COSE public key was missing kty');
+ throw new Error('COSE public key was missing kty (Packed|Self)');
}
const hashAlg: string = COSEALGHASH[(alg as number)];
if (kty === COSEKTY.EC2) {
- console.log('EC2');
-
const crv = cosePublicKey.get(COSEKEYS.crv);
if (!crv) {
- throw new Error('COSE public key was missing kty crv');
+ throw new Error('COSE public key was missing kty crv (Packed|EC2)');
}
const pkcsPublicKey = convertCOSEtoPKCS(cosePublicKey);
@@ -127,12 +121,10 @@ export default function verifyAttestationPacked(attestationObject: AttestationOb
toReturn.verified = key.verify(signatureBaseHash, sig);
} else if (kty === COSEKTY.RSA) {
- console.log('RSA');
-
const n = cosePublicKey.get(COSEKEYS.n);
if (!n) {
- throw new Error('COSE public key was missing n');
+ throw new Error('COSE public key was missing n (Packed|RSA)');
}
const signingScheme = COSERSASCHEME[alg as number];
@@ -147,12 +139,10 @@ export default function verifyAttestationPacked(attestationObject: AttestationOb
toReturn.verified = key.verify(signatureBase, sig);
} else if (kty === COSEKTY.OKP) {
- console.log('OKP');
-
const x = cosePublicKey.get(COSEKEYS.x);
if (!x) {
- throw new Error('COSE public key was missing x');
+ throw new Error('COSE public key was missing x (Packed|OKP)');
}
const signatureBaseHash = toHash(signatureBase, hashAlg);
diff --git a/packages/server/src/attestation/verifyAttestationResponse.ts b/packages/server/src/attestation/verifyAttestationResponse.ts
index 9b90391..f302771 100644
--- a/packages/server/src/attestation/verifyAttestationResponse.ts
+++ b/packages/server/src/attestation/verifyAttestationResponse.ts
@@ -21,24 +21,16 @@ export default function verifyAttestationResponse(
const attestationObject = decodeAttestationObject(base64AttestationObject);
const clientDataJSON = decodeClientDataJSON(base64ClientDataJSON);
- console.debug('decoded attestationObject:', attestationObject);
- console.debug('decoded clientDataJSON:', clientDataJSON);
-
const { type, origin } = clientDataJSON;
// Check that the origin is our site
if (origin !== expectedOrigin) {
- console.error('client origin did not equal our origin');
- console.debug('Expected Origin:', expectedOrigin);
- console.debug('attestation\'s origin:', origin);
- throw new Error('Attestation origin was an unexpected value');
+ throw new Error(`Unexpected attestation origin: ${origin}`);
}
// Make sure we're handling an attestation
if (type !== 'webauthn.create') {
- console.error('type did not equal "webauthn.create"');
- console.debug('attestation\'s type:', type);
- throw new Error('Attestation type was an unexpected value');
+ throw new Error(`Unexpected attestation type: ${type}`);
}
const { fmt } = attestationObject;
@@ -47,26 +39,20 @@ export default function verifyAttestationResponse(
* Verification can only be performed when attestation = 'direct'
*/
if (fmt === ATTESTATION_FORMATS.FIDO_U2F) {
- console.log('Decoding FIDO-U2F attestation');
return verifyFIDOU2F(attestationObject, base64ClientDataJSON);
}
if (fmt === ATTESTATION_FORMATS.PACKED) {
- console.log('Decoding Packed attestation');
return verifyPacked(attestationObject, base64ClientDataJSON);
}
if (fmt === ATTESTATION_FORMATS.ANDROID_SAFETYNET) {
- console.log('Decoding Android Safetynet attestation');
return verifyAndroidSafetynet(attestationObject, base64ClientDataJSON);
}
if (fmt === ATTESTATION_FORMATS.NONE) {
- console.log('Decoding None attestation');
return verifyNone(attestationObject);
}
- const reason = `Unsupported Attestation Format: ${fmt}`;
- console.error(reason);
- throw new Error(reason);
+ throw new Error(`Unsupported Attestation Format: ${fmt}`);
}