UNPKG

lbx-jwt

Version:

Provides JWT authentication for loopback applications. Includes storing roles inside tokens and handling refreshing. Built-in reuse detection.

161 lines 7.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseBiometricCredentialsService = void 0; const rest_1 = require("@loopback/rest"); const webauthn_utilities_1 = require("../encapsulation/webauthn.utilities"); /** * The base service for handling biometric credentials. */ class BaseBiometricCredentialsService { constructor() { /** * Error message to throw when no registration was found with the provided challenge for verifying the registration response. */ // eslint-disable-next-line stylistic/max-len this.NO_REGISTRATION_WITH_PROVIDED_CHALLENGE_FOUND_ERROR_MESSAGE = 'No registration with provided challenge found.'; } // eslint-disable-next-line jsdoc/require-returns /** * The complete origin of your frontend. * By default this returns https://${this.RP_DOMAIN}. */ get RP_ORIGIN() { return `https://${this.RP_DOMAIN}`; } /** * Generate biometric registration options. * @param userEmail - The email of the user to generate the options for. * @param alreadyRegisteredCredentials - Any already registered credentials of the user to avoid duplication. * @returns The generated registration options. */ async generateRegistrationOptions(userEmail, alreadyRegisteredCredentials) { var _a; const res = await webauthn_utilities_1.WebauthnUtilities.generateRegistrationOptions({ rpName: this.RP_NAME, rpID: this.RP_DOMAIN, userName: userEmail, // Prompt users for additional information about the authenticator. attestationType: 'none', // Prevent users from re-registering existing authenticators excludeCredentials: alreadyRegisteredCredentials.map(c => { return { id: c.credentialId }; }), authenticatorSelection: { // Defaults residentKey: 'preferred', userVerification: 'preferred' } }); return { ...res, challenge: res.challenge, excludeCredentials: (_a = res.excludeCredentials) === null || _a === void 0 ? void 0 : _a.map(ec => { return { ...ec, id: ec.id }; }) }; } /** * Verifies a biometric registration. * @param body - The request body including the data to verify (challenge, etc.). * @param expectedChallenge - The expected challenge. * @returns The verified biometric registration response. */ async verifyRegistrationResponse(body, expectedChallenge) { if (!expectedChallenge) { throw new rest_1.HttpErrors.BadRequest(this.NO_REGISTRATION_WITH_PROVIDED_CHALLENGE_FOUND_ERROR_MESSAGE); } const res = await webauthn_utilities_1.WebauthnUtilities.verifyRegistrationResponse({ response: body, expectedChallenge: expectedChallenge, expectedOrigin: this.RP_ORIGIN, expectedRPID: this.RP_DOMAIN }); return { ...res, registrationInfo: res.registrationInfo == undefined ? undefined : { ...res.registrationInfo, credentialID: res.registrationInfo.credentialID, credentialPublicKey: webauthn_utilities_1.WebauthnUtilities.uint8ToBase64UrlString(res.registrationInfo.credentialPublicKey), attestationObject: webauthn_utilities_1.WebauthnUtilities.uint8ToBase64UrlString(res.registrationInfo.attestationObject), authenticatorExtensionResults: res.registrationInfo.authenticatorExtensionResults == undefined ? undefined : this.transformAuthenticatorExtensionResults(res.registrationInfo.authenticatorExtensionResults) } }; } /** * Transforms the given authenticatorExtensionResults to an easier to use structure that uses base64 url strings instead of Uint8Arrays. * @param authenticatorExtensionResults - The original extension results to transform. * @returns The transformed value. */ transformAuthenticatorExtensionResults(authenticatorExtensionResults) { var _a, _b, _c, _d; return { ...authenticatorExtensionResults, devicePubKey: { ...authenticatorExtensionResults.devicePubKey, dpk: webauthn_utilities_1.WebauthnUtilities.uint8ToBase64UrlString((_a = authenticatorExtensionResults.devicePubKey) === null || _a === void 0 ? void 0 : _a.dpk), nonce: webauthn_utilities_1.WebauthnUtilities.uint8ToBase64UrlString((_b = authenticatorExtensionResults.devicePubKey) === null || _b === void 0 ? void 0 : _b.nonce), scope: webauthn_utilities_1.WebauthnUtilities.uint8ToBase64UrlString((_c = authenticatorExtensionResults.devicePubKey) === null || _c === void 0 ? void 0 : _c.scope), aaguid: webauthn_utilities_1.WebauthnUtilities.uint8ToBase64UrlString((_d = authenticatorExtensionResults.devicePubKey) === null || _d === void 0 ? void 0 : _d.aaguid) }, uvm: authenticatorExtensionResults.uvm == undefined ? undefined : { uvm: authenticatorExtensionResults.uvm.uvm == undefined ? undefined : authenticatorExtensionResults.uvm.uvm.map(u => webauthn_utilities_1.WebauthnUtilities.uint8ToBase64UrlString(u)) } }; } /** * Generates authentication options from the provided biometric credentials. * @param credentialsOfUser - The credentials to generate the options for. * @returns The generated authentication options. */ async generateAuthenticationOptions(credentialsOfUser) { var _a; const res = await webauthn_utilities_1.WebauthnUtilities.generateAuthenticationOptions({ rpID: this.RP_DOMAIN, allowCredentials: credentialsOfUser }); return { ...res, challenge: res.challenge, allowCredentials: (_a = res.allowCredentials) === null || _a === void 0 ? void 0 : _a.map(c => { return { ...c, id: c.id }; }) }; } /** * Verify that the user has legitimately completed the authentication process. * @param body - The response from the frontend. * @param biometricCredential - The biometric credential that the user tries to login with. * @returns The verified authentication response. */ async verifyAuthenticationResponse(body, biometricCredential) { return webauthn_utilities_1.WebauthnUtilities.verifyAuthenticationResponse({ response: body, expectedChallenge: biometricCredential.challenge, expectedOrigin: `https://${this.RP_DOMAIN}`, expectedRPID: this.RP_DOMAIN, authenticator: { credentialID: biometricCredential.credentialId, credentialPublicKey: webauthn_utilities_1.WebauthnUtilities.base64UrlStringToUint8(biometricCredential.publicKey), counter: biometricCredential.counter } }); } } exports.BaseBiometricCredentialsService = BaseBiometricCredentialsService; //# sourceMappingURL=base-biometric-credentials.service.js.map