DockerERTFF/lib/modules/passkeys.js

86 lines
6.2 KiB
JavaScript

module.exports = {
// rpName: User-visible, "friendly" website/service name
// rpID: Valid domain name (after `https://`)
// userID: User's website-specific unique ID (must be a string, do not use integer, user GUID instead)
// userName: User's website-specific username (email, etc...)
// userDisplayName: User's actual name
// timeout: How long (in ms) the user can take to complete attestation
// attestationType: Specific attestation statement
// excludeCredentials: Authenticators registered by the user so the user can't register the same credential multiple times
// supportedAlgorithmIDs Array of numeric COSE algorithm identifiers supported for attestation by this RP. See https://www.iana.org/assignments/cose/cose.xhtml#algorithms
async generateRegistrationOptions (options) {
const { generateRegistrationOptions } = require('@simplewebauthn/server');
const rpName = this.parseRequired(options.rpName, 'string', 'passkeys.generateRegistrationOptions: rpName is required.');
const rpID = this.parseRequired(options.rpID, 'string', 'passkeys.generateRegistrationOptions: rpID is required.');
const userID = this.parseRequired(options.userID, 'string', 'passkeys.generateRegistrationOptions: userID is required.');
const userName = this.parseRequired(options.userName, 'string', 'passkeys.generateRegistrationOptions: userName is required.');
const userDisplayName = this.parseOptional(options.userDisplayName, 'string', '');
const timeout = this.parseOptional(options.timeout, 'number', 60000);
const attestationType = this.parseOptional(options.attestationType, 'string', 'none'); // "direct" | "enterprise" | "indirect" | "none"
const excludeCredentials = this.parseOptional(options.excludeCredentials, 'object', []); // array[{id, transports}]
const supportedAlgorithmIDs = this.parseOptional(options.supportedAlgorithmIDs, 'object', [-8, -7, -257]) // array[number] (-8 requires Node 18 LTS)
// authenticator selection criteria (https://simplewebauthn.dev/docs/packages/server#1-generate-registration-options)
const residentKey = 'preferred'; // "discouraged" | "preferred" | "required"
const userVerification = 'preferred'; // "discouraged" | "preferred" | "required"
return await generateRegistrationOptions({
rpName, rpID, userID, userName, userDisplayName,
timeout, attestationType, excludeCredentials,
supportedAlgorithmIDs, authenticatorSelection: {
residentKey, userVerification,
},
});
},
// response: Response returned by **@simplewebauthn/browser**'s `startAuthentication()`
// expectedChallenge: The base64url-encoded `options.challenge` returned by `generateRegistrationOptions()`
// expectedOrigin: Website URL (or array of URLs) that the registration should have occurred on
// expectedRPID: RP ID (or array of IDs) that was specified in the registration options
async verifyRegistrationResponse (options) {
const { verifyRegistrationResponse } = require('@simplewebauthn/server');
const response = this.parseRequired(options.response, 'object', 'passkeys.verifyRegistrationResponse: response is required.');
const expectedChallenge = this.parseRequired(options.expectedChallenge, 'string', 'passkeys.verifyRegistrationResponse: expectedChallenge is required.');
const expectedOrigin = this.parseRequired(options.expectedOrigin, 'string', 'passkeys.verifyRegistrationResponse: expectedOrigin is required.');
const expectedRPID = this.parseRequired(options.expectedRPID, 'string', 'passkeys.verifyRegistrationResponse: expectedRPID is required.');
return await verifyRegistrationResponse({
response, expectedChallenge, expectedOrigin, expectedRPID,
});
},
// allowCredentials: Authenticators previously registered by the user, if any. If undefined the client will ask the user which credential they want to use
// timeout: How long (in ms) the user can take to complete authentication
// userVerification: Set to `'discouraged'` when asserting as part of a 2FA flow, otherwise set to `'preferred'` or `'required'` as desired.
// rpID: Valid domain name (after `https://`)
async generateAuthenticationOptions (options) {
const { generateAuthenticationOptions } = require('@simplewebauthn/server');
const allowCredentials = this.parseOptional(options.allowCredentials, 'object', undefined);
const timeout = this.parseOptional(options.timeout, 'number', 60000);
const userVerification = this.parseOptional(options.userVerification, 'string', 'preferred'); // "discouraged" | "preferred" | "required"
const rpID = this.parseOptional(options.rpID, 'string', undefined);
return await generateAuthenticationOptions({
allowCredentials, timeout, userVerification, rpID,
});
},
// response: Response returned by **@simplewebauthn/browser**'s `startAssertion()`
// expectedChallenge: The base64url-encoded `options.challenge` returned by `generateAuthenticationOptions()`
// expectedOrigin: Website URL (or array of URLs) that the registration should have occurred on
// expectedRPID: RP ID (or array of IDs) that was specified in the registration options
// authenticator: An internal {@link AuthenticatorDevice} matching the credential's ID
async verifyAuthenticationResponse (options) {
const { verifyAuthenticationResponse } = require('@simplewebauthn/server');
const response = this.parseRequired(options.response, 'object', 'passkeys.verifyAuthenticationResponse: response is required.');
const expectedChallenge = this.parseRequired(options.expectedChallenge, 'string', 'passkeys.verifyAuthenticationResponse: expectedChallenge is required.');
const expectedOrigin = this.parseRequired(options.expectedOrigin, 'string', 'passkeys.verifyAuthenticationResponse: expectedOrigin is required.');
const expectedRPID = this.parseRequired(options.expectedRPID, 'string', 'passkeys.verifyAuthenticationResponse: expectedRPID is required.');
const authenticator = this.parseRequired(options.authenticator, 'object', 'passkeys.verifyAuthenticationResponse: authenticator is required.')
return await verifyAuthenticationResponse({
response, expectedChallenge, expectedOrigin, expectedRPID, authenticator,
});
},
};