UNPKG

@simulacrum/auth0-simulator

Version:

Run local instance of Auth0 API for local development and integration testing

136 lines 4.98 kB
import { assert } from "assert-ts"; import { decode, decode as decodeBase64 } from "base64-url"; import { epochTime, expiresAt } from "../auth/date"; import { createJsonWebToken } from "../auth/jwt"; import { createRulesRunner } from "../rules/rules-runner"; import { deriveScope, createPersonQuery } from "./utils"; import { createRefreshToken, issueRefreshToken } from "../auth/refresh-token"; export const createTokens = async ({ body, iss, clientID, audience, rulesDirectory, scope: scopeConfig, simulationStore, }) => { let { grant_type } = body; let scope = deriveScope({ scopeConfig, clientID, audience }); let accessToken = getBaseAccessToken({ iss, grant_type, scope, audience }); let user; let nonce; if (grant_type === "client_credentials") { return { access_token: createJsonWebToken(accessToken) }; } // TODO: check refresh_token expiry date else if (grant_type === "refresh_token") { let { refresh_token: refreshTokenValue } = body; let refreshToken = JSON.parse(decode(refreshTokenValue)); let findUser = createPersonQuery(simulationStore); user = findUser((person) => person.id === refreshToken.user.id); nonce = refreshToken.nonce; assert(!!nonce, `400::No nonce in request`); } else { let result = verifyUserExistsInStore({ simulationStore, body, grant_type, }); user = result.user; nonce = result.nonce; } assert(!!user, "500::No user found"); let { idTokenData, userData } = getIdToken({ body, iss, user, clientID, nonce, }); let context = { clientID, accessToken: { scope, sub: idTokenData.sub }, idToken: idTokenData, }; let rulesRunner = createRulesRunner(rulesDirectory); // the rules mutate the values await rulesRunner(userData, context); return { access_token: createJsonWebToken({ ...accessToken, ...context.accessToken, }), id_token: createJsonWebToken({ ...userData, ...context.idToken, }), refresh_token: issueRefreshToken(scope, grant_type) ? createRefreshToken({ exp: idTokenData.exp, rotations: 0, scope, user, nonce, }) : undefined, }; }; export const getIdToken = ({ body, iss, user, clientID, nonce, }) => { var _a, _b, _c, _d; let userData = { name: (_a = body === null || body === void 0 ? void 0 : body.name) !== null && _a !== void 0 ? _a : user.name, email: (_b = body === null || body === void 0 ? void 0 : body.email) !== null && _b !== void 0 ? _b : user.email, email_verified: true, user_id: (_c = body === null || body === void 0 ? void 0 : body.id) !== null && _c !== void 0 ? _c : user.id, nickname: body === null || body === void 0 ? void 0 : body.nickname, picture: (_d = body === null || body === void 0 ? void 0 : body.picture) !== null && _d !== void 0 ? _d : user.picture, identities: body === null || body === void 0 ? void 0 : body.identities, }; assert(!!user.email, "500::User in store requires an email"); let idTokenData = { alg: "RS256", typ: "JWT", iss, exp: expiresAt(), iat: epochTime(), email: user.email, aud: clientID, sub: user.id, }; if (typeof nonce !== "undefined") { idTokenData.nonce = nonce; } return { userData, idTokenData }; }; export const getBaseAccessToken = ({ iss, grant_type, scope, audience, }) => ({ iss, exp: expiresAt(), iat: epochTime(), aud: audience, gty: grant_type, scope, }); const verifyUserExistsInStore = ({ simulationStore, body, grant_type, }) => { let { code } = body; let personQuery = createPersonQuery(simulationStore); let nonce; let username; let password; if (grant_type === "password") { username = body.username; password = body.password; } else { // specifically grant_type === 'authorization_code' // but naively using it to handle other cases at the moment assert(typeof code !== "undefined", "400::no code in /oauth/token"); [nonce, username] = decodeBase64(code).split(":"); } assert(!!username, `400::no nonce in store for ${code}`); let user = personQuery((person) => { assert(!!person.email, `500::no email defined on person scenario`); let valid = person.email.toLowerCase() === username.toLowerCase(); if (typeof password === "undefined") { return valid; } else { return valid && password === person.password; } }); assert(!!user, "401::Unauthorized"); return { user, nonce }; }; //# sourceMappingURL=oauth-handlers.js.map