UNPKG

@simulacrum/auth0-simulator

Version:

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

144 lines (142 loc) 3.94 kB
import "../store/entities.mjs"; import "../store/index.mjs"; import { createPersonQuery, deriveScope } from "./utils.mjs"; import { epochTime, expiresAt } from "../auth/date.mjs"; import { createJsonWebToken } from "../auth/jwt.mjs"; import { createRulesRunner } from "../rules/rules-runner.mjs"; import { createRefreshToken, issueRefreshToken } from "../auth/refresh-token.mjs"; import { assert } from "assert-ts"; import { decode } from "base64-url"; //#region src/handlers/oauth-handlers.ts 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) }; else if (grant_type === "refresh_token") { let { refresh_token: refreshTokenValue } = body; let refreshToken = JSON.parse(decode(refreshTokenValue)); user = createPersonQuery(simulationStore)((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 }; await createRulesRunner(rulesDirectory)(userData, context); return { access_token: createJsonWebToken({ ...accessToken, ...context.accessToken, ...scope.split(" ").includes("email") ? { email: user.email } : {} }), id_token: createJsonWebToken({ ...userData, ...context.idToken }), refresh_token: issueRefreshToken(scope, grant_type) ? createRefreshToken({ exp: idTokenData.exp, rotations: 0, scope, user, nonce }) : void 0 }; }; const getIdToken = ({ body, iss, user, clientID, nonce }) => { let userData = { name: body?.name ?? user.name, email: body?.email ?? user.email, email_verified: true, user_id: body?.id ?? user.id, nickname: body?.nickname, picture: body?.picture ?? user.picture, identities: 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 }; }; 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 === "http://auth0.com/oauth/grant-type/passwordless/otp") username = body.username; else if (grant_type === "password") { username = body.username; password = body.password; } else { assert(typeof code !== "undefined", "400::no code in /oauth/token"); [nonce, username] = decode(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 }; }; //#endregion export { createTokens }; //# sourceMappingURL=oauth-handlers.mjs.map