summaryrefslogtreecommitdiffhomepage
path: root/packages/server/src
diff options
context:
space:
mode:
authorMatthew Miller <matthew@millerti.me>2020-05-26 22:38:27 -0700
committerGitHub <noreply@github.com>2020-05-26 22:38:27 -0700
commit5a1acc9128be6dbce3d8d718defe93fb14a88e36 (patch)
tree7eea60332475794ba7fa02ea24374fc98b59baf4 /packages/server/src
parent2374c09f8444b8a80ce8429f2654ce1b3b92c346 (diff)
parent1c956b9c39f5c175d3841b1fafaeeb495d1eea6b (diff)
Merge pull request #16 from MasterKale/feature/support-more-credential-options
feature/support-more-credential-options
Diffstat (limited to 'packages/server/src')
-rw-r--r--packages/server/src/assertion/generateAssertionOptions.test.ts51
-rw-r--r--packages/server/src/assertion/generateAssertionOptions.ts35
-rw-r--r--packages/server/src/attestation/generateAttestationOptions.test.ts98
-rw-r--r--packages/server/src/attestation/generateAttestationOptions.ts95
4 files changed, 152 insertions, 127 deletions
diff --git a/packages/server/src/assertion/generateAssertionOptions.test.ts b/packages/server/src/assertion/generateAssertionOptions.test.ts
index 257657b..aa345af 100644
--- a/packages/server/src/assertion/generateAssertionOptions.test.ts
+++ b/packages/server/src/assertion/generateAssertionOptions.test.ts
@@ -3,40 +3,41 @@ import generateAssertionOptions from './generateAssertionOptions';
test('should generate credential request options suitable for sending via JSON', () => {
const challenge = 'totallyrandomvalue';
- const options = generateAssertionOptions(
+ const options = generateAssertionOptions({
challenge,
- 1,
- [
+ timeout: 1,
+ allowedBase64CredentialIDs: [
Buffer.from('1234', 'ascii').toString('base64'),
Buffer.from('5678', 'ascii').toString('base64'),
],
- );
+ });
expect(options).toEqual({
- publicKey: {
- challenge,
- allowCredentials: [
- {
- id: 'MTIzNA==',
- type: 'public-key',
- transports: ['usb', 'ble', 'nfc', 'internal'],
- },
- {
- id: 'NTY3OA==',
- type: 'public-key',
- transports: ['usb', 'ble', 'nfc', 'internal'],
- },
- ],
- timeout: 1,
- },
+ challenge,
+ allowCredentials: [
+ {
+ id: 'MTIzNA==',
+ type: 'public-key',
+ transports: ['usb', 'ble', 'nfc', 'internal'],
+ },
+ {
+ id: 'NTY3OA==',
+ type: 'public-key',
+ transports: ['usb', 'ble', 'nfc', 'internal'],
+ },
+ ],
+ timeout: 1,
});
});
test('defaults to 60 seconds if no timeout is specified', () => {
- const options = generateAssertionOptions('totallyrandomvalue', undefined, [
- Buffer.from('1234', 'ascii').toString('base64'),
- Buffer.from('5678', 'ascii').toString('base64'),
- ]);
+ const options = generateAssertionOptions({
+ challenge: 'totallyrandomvalue',
+ allowedBase64CredentialIDs: [
+ Buffer.from('1234', 'ascii').toString('base64'),
+ Buffer.from('5678', 'ascii').toString('base64'),
+ ],
+ });
- expect(options.publicKey.timeout).toEqual(60000);
+ expect(options.timeout).toEqual(60000);
});
diff --git a/packages/server/src/assertion/generateAssertionOptions.ts b/packages/server/src/assertion/generateAssertionOptions.ts
index b30344d..b31a34f 100644
--- a/packages/server/src/assertion/generateAssertionOptions.ts
+++ b/packages/server/src/assertion/generateAssertionOptions.ts
@@ -2,6 +2,13 @@ import type {
PublicKeyCredentialRequestOptionsJSON,
} from '@simplewebauthn/typescript-types';
+type Options = {
+ challenge: string,
+ allowedBase64CredentialIDs: string[],
+ suggestedTransports?: AuthenticatorTransport[],
+ timeout?: number,
+};
+
/**
* Prepare a value to pass into navigator.credentials.get(...) for authenticator "login"
*
@@ -12,20 +19,22 @@ import type {
* @param suggestedTransports Suggested types of authenticators for assertion
*/
export default function generateAssertionOptions(
- challenge: string,
- timeout = 60000,
- allowedBase64CredentialIDs: string[],
- suggestedTransports: AuthenticatorTransport[] = ['usb', 'ble', 'nfc', 'internal'],
+ options: Options,
): PublicKeyCredentialRequestOptionsJSON {
+ const {
+ challenge,
+ allowedBase64CredentialIDs,
+ suggestedTransports = ['usb', 'ble', 'nfc', 'internal'],
+ timeout = 60000,
+ } = options;
+
return {
- publicKey: {
- challenge,
- allowCredentials: allowedBase64CredentialIDs.map(id => ({
- id,
- type: 'public-key',
- transports: suggestedTransports,
- })),
- timeout,
- },
+ challenge,
+ allowCredentials: allowedBase64CredentialIDs.map(id => ({
+ id,
+ type: 'public-key',
+ transports: suggestedTransports,
+ })),
+ timeout,
};
}
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..e2a9926 100644
--- a/packages/server/src/attestation/generateAttestationOptions.ts
+++ b/packages/server/src/attestation/generateAttestationOptions.ts
@@ -1,57 +1,76 @@
-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'],
+ options: Options,
): PublicKeyCredentialCreationOptionsJSON {
+ const {
+ serviceName,
+ rpID,
+ challenge,
+ userID,
+ userName,
+ userDisplayName = userName,
+ timeout = 60000,
+ attestationType = 'none',
+ excludedBase64CredentialIDs = [],
+ suggestedTransports = ['usb', 'ble', 'nfc', 'internal'],
+ } = options;
+
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,
+ })),
};
}