summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/server/src/attestation/generateAttestationOptions.test.ts98
-rw-r--r--packages/server/src/attestation/generateAttestationOptions.ts97
2 files changed, 104 insertions, 91 deletions
diff --git a/packages/server/src/attestation/generateAttestationOptions.test.ts b/packages/server/src/attestation/generateAttestationOptions.test.ts
index 3885dfc..73218bf 100644
--- a/packages/server/src/attestation/generateAttestationOptions.test.ts
+++ b/packages/server/src/attestation/generateAttestationOptions.test.ts
@@ -5,58 +5,54 @@ test('should generate credential request options suitable for sending via JSON',
const rpID = 'not.real';
const challenge = 'totallyrandomvalue';
const userID = '1234';
- const username = 'usernameHere';
+ const userName = 'usernameHere';
const timeout = 1;
const attestationType = 'indirect';
- const options = generateAttestationOptions(
+ const options = generateAttestationOptions({
serviceName,
rpID,
challenge,
userID,
- username,
+ userName,
timeout,
attestationType,
- );
+ });
expect(options).toEqual({
- publicKey: {
- challenge,
- rp: {
- name: serviceName,
- id: rpID,
- },
- user: {
- id: userID,
- name: username,
- displayName: username,
- },
- pubKeyCredParams: [
- {
- alg: -7,
- type: 'public-key',
- },
- ],
- timeout,
- attestation: attestationType,
- excludeCredentials: [],
+ challenge,
+ rp: {
+ name: serviceName,
+ id: rpID,
+ },
+ user: {
+ id: userID,
+ name: userName,
+ displayName: userName,
},
+ pubKeyCredParams: [
+ {
+ alg: -7,
+ type: 'public-key',
+ },
+ ],
+ timeout,
+ attestation: attestationType,
+ excludeCredentials: [],
});
});
test('should map excluded credential IDs if specified', () => {
- const options = generateAttestationOptions(
- 'SimpleWebAuthn',
- 'not.real',
- 'totallyrandomvalue',
- '1234',
- 'usernameHere',
- undefined,
- undefined,
- ['someIDhere'],
- );
+ const options = generateAttestationOptions({
+ serviceName: 'SimpleWebAuthn',
+ rpID: 'not.real',
+ challenge: 'totallyrandomvalue',
+ userID: '1234',
+ userName: 'usernameHere',
+ excludedBase64CredentialIDs: ['someIDhere'],
+ });
- expect(options.publicKey.excludeCredentials).toEqual([{
+ expect(options.excludeCredentials).toEqual([{
id: 'someIDhere',
type: 'public-key',
transports: ['usb', 'ble', 'nfc', 'internal'],
@@ -64,25 +60,25 @@ test('should map excluded credential IDs if specified', () => {
});
test('defaults to 60 seconds if no timeout is specified', () => {
- const options = generateAttestationOptions(
- 'SimpleWebAuthn',
- 'not.real',
- 'totallyrandomvalue',
- '1234',
- 'usernameHere',
- );
+ const options = generateAttestationOptions({
+ serviceName: 'SimpleWebAuthn',
+ rpID: 'not.real',
+ challenge: 'totallyrandomvalue',
+ userID: '1234',
+ userName: 'usernameHere',
+ });
- expect(options.publicKey.timeout).toEqual(60000);
+ expect(options.timeout).toEqual(60000);
});
test('defaults to direct attestation if no attestation type is specified', () => {
- const options = generateAttestationOptions(
- 'SimpleWebAuthn',
- 'not.real',
- 'totallyrandomvalue',
- '1234',
- 'usernameHere',
- );
+ const options = generateAttestationOptions({
+ serviceName: 'SimpleWebAuthn',
+ rpID: 'not.real',
+ challenge: 'totallyrandomvalue',
+ userID: '1234',
+ userName: 'usernameHere',
+ });
- expect(options.publicKey.attestation).toEqual('direct');
+ expect(options.attestation).toEqual('none');
});
diff --git a/packages/server/src/attestation/generateAttestationOptions.ts b/packages/server/src/attestation/generateAttestationOptions.ts
index 27931fa..65fbdff 100644
--- a/packages/server/src/attestation/generateAttestationOptions.ts
+++ b/packages/server/src/attestation/generateAttestationOptions.ts
@@ -1,57 +1,74 @@
-import { PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/typescript-types';
+import {
+ PublicKeyCredentialCreationOptionsJSON,
+} from '@simplewebauthn/typescript-types';
+
+type Options = {
+ serviceName: string,
+ rpID: string,
+ challenge: string,
+ userID: string,
+ userName: string,
+ userDisplayName?: string,
+ timeout?: number,
+ attestationType?: AttestationConveyancePreference,
+ excludedBase64CredentialIDs?: string[],
+ suggestedTransports?: AuthenticatorTransport[],
+};
/**
* Prepare a value to pass into navigator.credentials.create(...) for authenticator "registration"
*
+ * **Options:**
+ *
* @param serviceName Friendly user-visible website name
* @param rpID Valid domain name (after `https://`)
* @param challenge Random string the authenticator needs to sign and pass back
* @param userID User's website-specific unique ID
- * @param username User's website-specific username
+ * @param userName User's website-specific username (email, etc...)
+ * @param userDisplayName User's actual name
* @param timeout How long (in ms) the user can take to complete attestation
- * @param attestationType Request a full ("direct") or anonymized ("indirect") attestation statement
+ * @param attestationType Specific attestation statement
* @param excludedBase64CredentialIDs Array of base64-encoded authenticator IDs registered by the
* user so the user can't register the same credential multiple times
* @param suggestedTransports Suggested types of authenticators for attestation
*/
-export default function generateAttestationOptions(
- serviceName: string,
- rpID: string,
- challenge: string,
- userID: string,
- username: string,
- timeout = 60000,
- attestationType: 'direct' | 'indirect' = 'direct',
- excludedBase64CredentialIDs: string[] = [],
- suggestedTransports: AuthenticatorTransport[] = ['usb', 'ble', 'nfc', 'internal'],
-): PublicKeyCredentialCreationOptionsJSON {
+export default function generateAttestationOptions(opts: Options): PublicKeyCredentialCreationOptionsJSON {
+ const {
+ serviceName,
+ rpID,
+ challenge,
+ userID,
+ userName,
+ userDisplayName = userName,
+ timeout = 60000,
+ attestationType = 'none',
+ excludedBase64CredentialIDs = [],
+ suggestedTransports = ['usb', 'ble', 'nfc', 'internal'],
+ } = opts;
+
return {
- publicKey: {
- // Cryptographically random bytes to prevent replay attacks
- challenge,
- // The organization registering and authenticating the user
- rp: {
- name: serviceName,
- id: rpID,
- },
- user: {
- id: userID,
- name: username,
- displayName: username,
- },
- pubKeyCredParams: [
- {
- alg: -7,
- type: 'public-key',
- },
- ],
- timeout,
- attestation: attestationType,
- excludeCredentials: excludedBase64CredentialIDs.map((id) => ({
- id,
- type: 'public-key',
- transports: suggestedTransports,
- })),
+ challenge,
+ rp: {
+ name: serviceName,
+ id: rpID,
+ },
+ user: {
+ id: userID,
+ name: userName,
+ displayName: userDisplayName,
},
+ pubKeyCredParams: [
+ {
+ alg: -7,
+ type: 'public-key',
+ },
+ ],
+ timeout,
+ attestation: attestationType,
+ excludeCredentials: excludedBase64CredentialIDs.map((id) => ({
+ id,
+ type: 'public-key',
+ transports: suggestedTransports,
+ })),
};
}