lbx-jwt
Version:
Provides JWT authentication for loopback applications. Includes storing roles inside tokens and handling refreshing. Built-in reuse detection.
173 lines (154 loc) • 9.84 kB
text/typescript
/* eslint-disable jsdoc/check-param-names */
import base64 from '@hexagon/base64';
import { GenerateAuthenticationOptionsOpts, GenerateRegistrationOptionsOpts, VerifiedAuthenticationResponse as SWAVerifiedAuthenticationResponse, VerifiedRegistrationResponse, VerifyAuthenticationResponseOpts, VerifyRegistrationResponseOpts, generateAuthenticationOptions, generateRegistrationOptions, verifyAuthenticationResponse, verifyRegistrationResponse } from '@simplewebauthn/server';
import { PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/types';
// eslint-disable-next-line jsdoc/require-jsdoc
type ConditionalType<InputType, ReturnType> =
InputType extends undefined
? undefined
: ReturnType;
/**
* The values for AuthenticatorTransport property definitions.
*/
export const authenticatorTransportFutureValues: string[] = ['ble', 'cable', 'hybrid', 'internal', 'nfc', 'smart-card', 'usb'];
/**
* The values for AuthenticatorAttachment property definitions.
*/
export const authenticatorAttachmentValues: string[] = ['cross-platform', 'platform'];
/**
* The values for Requirement property definitions.
*/
export const requirementValues: string[] = ['discouraged', 'preferred', 'required'];
/**
* The values for AttestationConveyancePreference property definitions.
*/
export const attestationConveyancePreferenceValues: string[] = ['none', 'direct', 'enterprise', 'indirect'];
/**
* The values for PublicKeyCredentialType property definitions.
*/
export const publicKeyCredentialTypeValues: string[] = ['public-key'];
/**
* The values for AttestationFormat property definitions.
*/
// eslint-disable-next-line cspell/spellchecker
export const attestationFormatValues: string[] = ['none', 'fido-u2f', 'packed', 'android-safetynet', 'android-key', 'tpm', 'apple'];
/**
* The possible AttestationFormats.
*/
export type AttestationFormat = typeof attestationFormatValues[number];
/**
* The values for CredentialDeviceType property definitions.
*/
export const credentialDeviceTypeValues: string[] = ['singleDevice', 'multiDevice'];
/**
* The type of the credential device used.
*/
export type CredentialDeviceType = typeof credentialDeviceTypeValues[number];
/**
* Verified authentication response. Comes from the frontend when biometric authentication was successful.
*/
export type VerifiedAuthenticationResponse = SWAVerifiedAuthenticationResponse;
/**
* Helper type for the base64 string.
*/
// eslint-disable-next-line jsdoc/require-jsdoc
type Opaque<T, K extends string> = T & { __typename: K };
/**
* Type for a base64 string. This does not apply any type checking and is just programmatic sugar.
*/
export type Base64UrlString = Opaque<string, 'base64'>;
/**
* Encapsulates functionality of the **@simplewebauthn/server** package.
*/
export abstract class WebauthnUtilities {
// eslint-disable-next-line jsdoc/require-param, jsdoc/require-returns
/**
* Prepare a value to pass into navigator.credentials.create(...) for authenticator registration.
*
* **Options:**.
* @param rpName - User-visible, "friendly" website/service name.
* @param rpID - Valid domain name (after `https://`).
* @param userName - User's website-specific username (email, etc...).
* @param userID - **(Optional)** - User's website-specific unique ID. Defaults to generating a random identifier.
* @param challenge - **(Optional)** - Random value the authenticator needs to sign and pass back. Defaults to generating a random value.
* @param userDisplayName - **(Optional)** - User's actual name. Defaults to `""`.
* @param timeout - **(Optional)** - How long (in ms) the user can take to complete attestation. Defaults to `60000`.
* @param attestationType - **(Optional)** - Specific attestation statement. Defaults to `"none"`.
* @param excludeCredentials - **(Optional)** - Authenticators registered by the user so the user can't register the same credential multiple times. Defaults to `[]`.
* @param authenticatorSelection - **(Optional)** - Advanced criteria for restricting the types of authenticators that may be used. Defaults to `{ residentKey: 'preferred', userVerification: 'preferred' }`.
* @param extensions - **(Optional)** - Additional plugins the authenticator or browser should use during attestation.
* @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 `[-8, -7, -257]`.
*/
static async generateRegistrationOptions(options: GenerateRegistrationOptionsOpts): Promise<PublicKeyCredentialCreationOptionsJSON> {
return generateRegistrationOptions(options);
}
// eslint-disable-next-line jsdoc/require-param, jsdoc/require-returns
/**
* Verify that the user has legitimately completed the registration process.
*
* **Options:**.
* @param response - Response returned by **@simplewebauthn/browser**'s `startAuthentication()`.
* @param expectedChallenge - The base64url-encoded `options.challenge` returned by `generateRegistrationOptions()`.
* @param expectedOrigin - Website URL (or array of URLs) that the registration should have occurred on.
* @param expectedRPID - RP ID (or array of IDs) that was specified in the registration options.
* @param expectedType - **(Optional)** - The response type expected ('webauthn.create').
* @param requireUserVerification - **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true`.
* @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.
*/
static async verifyRegistrationResponse(options: VerifyRegistrationResponseOpts): Promise<VerifiedRegistrationResponse> {
return verifyRegistrationResponse(options);
}
// eslint-disable-next-line jsdoc/require-param, jsdoc/require-returns
/**
* Prepare a value to pass into navigator.credentials.get(...) for authenticator authentication.
*
* **Options:**.
* @param rpID - Valid domain name (after `https://`).
* @param allowCredentials - **(Optional)** - Authenticators previously registered by the user, if any. If undefined the client will ask the user which credential they want to use.
* @param challenge - **(Optional)** - Random value the authenticator needs to sign and pass back user for authentication. Defaults to generating a random value.
* @param timeout - **(Optional)** - How long (in ms) the user can take to complete authentication. Defaults to `60000`.
* @param userVerification - **(Optional)** - Set to `'discouraged'` when asserting as part of a 2FA flow, otherwise set to `'preferred'` or `'required'` as desired. Defaults to `"preferred"`.
* @param extensions - **(Optional)** - Additional plugins the authenticator or browser should use during authentication.
*/
static async generateAuthenticationOptions(options: GenerateAuthenticationOptionsOpts): Promise<PublicKeyCredentialRequestOptionsJSON> {
return generateAuthenticationOptions(options);
}
// eslint-disable-next-line jsdoc/require-param, jsdoc/require-returns
/**
* Verify that the user has legitimately completed the authentication process.
*
* **Options:**.
* @param response - Response returned by **@simplewebauthn/browser**'s `startAssertion()`.
* @param expectedChallenge - The base64url-encoded `options.challenge` returned by `generateAuthenticationOptions()`.
* @param expectedOrigin - Website URL (or array of URLs) that the registration should have occurred on.
* @param expectedRPID - RP ID (or array of IDs) that was specified in the registration options.
* @param authenticator - An internal AuthenticatorDevice matching the credential's ID.
* @param expectedType - **(Optional)** - The response type expected ('webauthn.get').
* @param requireUserVerification - **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true`.
* @param advancedFIDOConfig - **(Optional)** - Options for satisfying more stringent FIDO RP feature requirements.
* @param advancedFIDOConfig.userVerification - **(Optional)** - Enable alternative rules for evaluating the User Presence and User Verified flags in authenticator data: UV (and UP) flags are optional unless this value is `"required"`.
*/
static async verifyAuthenticationResponse(options: VerifyAuthenticationResponseOpts): Promise<VerifiedAuthenticationResponse> {
return verifyAuthenticationResponse(options);
}
/**
* Converts the given Uint8Array to a base64 url string.
* @param value - The value to convert.
* @returns A Base64UrlString that forces you to assign the value with "as string".
*/
static uint8ToBase64UrlString<T extends Uint8Array | undefined>(value: T): ConditionalType<T, Base64UrlString> {
if (value == undefined) {
return undefined as ConditionalType<T, Base64UrlString>;
}
return base64.fromArrayBuffer(value, true) as ConditionalType<T, Base64UrlString>;
}
/**
* Converts the given Base64UrlString to a Uint8Array.
* @param value - The value to convert.
* @returns The respective Uint8Array.
*/
static base64UrlStringToUint8(value: Base64UrlString): Uint8Array {
const normalString: string = base64.toString(value, true);
return new TextEncoder().encode(normalString);
}
}