UNPKG

@simulacrum/auth0-simulator

Version:

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

199 lines 9.95 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAuth0Handlers = void 0; const login_redirect_ts_1 = require("./login-redirect.js"); const web_message_ts_1 = require("./web-message.js"); const login_ts_1 = require("../views/login.js"); const oauth_handlers_ts_1 = require("./oauth-handlers.js"); const assert_ts_1 = require("assert-ts"); const querystring_1 = require("querystring"); const base64_url_1 = require("base64-url"); const username_password_ts_1 = require("../views/username-password.js"); const jsonwebtoken_1 = require("jsonwebtoken"); const utils_ts_1 = require("./utils.js"); const createLogger = (debug) => ({ log: (...args) => { if (!debug) { return; } console.dir(...args); }, }); const createAuth0Handlers = (simulationStore, serviceURL, options, debug) => { let { audience, scope, clientID, rulesDirectory } = options; let personQuery = (0, utils_ts_1.createPersonQuery)(simulationStore); let authorizeHandlers = { query: (0, login_redirect_ts_1.createLoginRedirectHandler)(options), web_message: (0, web_message_ts_1.createWebMessageHandler)(), }; let logger = createLogger(debug); return { ["/heartbeat"]: function (_, res) { res.status(200).json({ ok: true }); }, ["/authorize"]: function (req, res, next) { var _a; logger.log({ "/authorize": { body: req.body, query: req.query, session: req.session, }, }); let currentUser = req.query.currentUser; (0, assert_ts_1.assert)(!!req.session, "no session"); if (currentUser) { // the request is a silent login. // We fake an existing login by // adding the user to the session req.session.username = currentUser; } let responseMode = ((_a = req.query.response_mode) !== null && _a !== void 0 ? _a : "query"); (0, assert_ts_1.assert)(["query", "web_message"].includes(responseMode), `unknown response_mode ${responseMode}`); let handler = authorizeHandlers[responseMode]; handler(req, res, next); }, ["/login"]: function (req, res) { var _a, _b; logger.log({ "/login": { body: req.body, query: req.query } }); let query = req.query; let responseClientId = (_a = query.client_id) !== null && _a !== void 0 ? _a : clientID; let responseAudience = (_b = query.audience) !== null && _b !== void 0 ? _b : audience; (0, assert_ts_1.assert)(!!responseClientId, `no clientID assigned`); let html = (0, login_ts_1.loginView)({ domain: new URL(serviceURL(req)).host, scope, redirectUri: query.redirect_uri, clientID: responseClientId, audience: responseAudience, loginFailed: false, }); res.set("Content-Type", "text/html"); res.status(200).send(Buffer.from(html)); }, ["/usernamepassword/login"]: function (req, res) { var _a, _b; logger.log({ "/usernamepassword/login": { body: req.body, query: req.query }, }); let { username, nonce, password } = req.body; (0, assert_ts_1.assert)(!!username, "no username in /usernamepassword/login"); (0, assert_ts_1.assert)(!!nonce, "no nonce in /usernamepassword/login"); (0, assert_ts_1.assert)(!!req.session, "no session"); let user = personQuery((person) => { var _a; return ((_a = person.email) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === username.toLowerCase() && person.password === password; }); if (!user) { let query = req.query; let responseClientId = (_a = query.client_id) !== null && _a !== void 0 ? _a : clientID; let responseAudience = (_b = query.audience) !== null && _b !== void 0 ? _b : audience; (0, assert_ts_1.assert)(!!clientID, `no clientID assigned`); let html = (0, login_ts_1.loginView)({ domain: new URL(serviceURL(req)).host, scope, redirectUri: query.redirect_uri, clientID: responseClientId, audience: responseAudience, loginFailed: true, }); res.set("Content-Type", "text/html"); res.status(400).send(html); return; } req.session.username = username; simulationStore.store.dispatch(simulationStore.actions.batchUpdater([ simulationStore.schema.sessions.patch({ [nonce]: { username, nonce }, }), ])); res.status(200).send((0, username_password_ts_1.userNamePasswordForm)(req.body)); }, ["/login/callback"]: function (req, res) { let wctx = JSON.parse(req.body.wctx); logger.log({ "/login/callback": { body: req.body, query: req.query, wctx }, }); let { redirect_uri, nonce } = wctx; const session = simulationStore.schema.sessions.selectById(simulationStore.store.getState(), { id: nonce }); const { username } = session !== null && session !== void 0 ? session : {}; let encodedNonce = (0, base64_url_1.encode)(`${nonce}:${username}`); let qs = (0, querystring_1.stringify)(Object.assign({ code: encodedNonce }, wctx)); let routerUrl = `${redirect_uri}?${qs}`; res.status(302).redirect(routerUrl); }, ["/oauth/token"]: function (req, res, next) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d; logger.log({ "/oauth/token": { body: req.body, query: req.query } }); try { let iss = serviceURL(req); let responseClientId = (_b = (_a = req === null || req === void 0 ? void 0 : req.body) === null || _a === void 0 ? void 0 : _a.client_id) !== null && _b !== void 0 ? _b : clientID; let responseAudience = (_d = (_c = req === null || req === void 0 ? void 0 : req.body) === null || _c === void 0 ? void 0 : _c.audience) !== null && _d !== void 0 ? _d : audience; (0, assert_ts_1.assert)(!!responseClientId, "500::no clientID in options or request body"); let tokens = yield (0, oauth_handlers_ts_1.createTokens)({ simulationStore, body: req.body, iss, clientID: responseClientId, audience: responseAudience, rulesDirectory, scope, }); res.status(200).json(Object.assign(Object.assign({}, tokens), { expires_in: 86400, token_type: "Bearer" })); } catch (error) { next(error); } }); }, ["/v2/logout"]: function (req, res) { var _a; req.session = null; let returnToUrl = (_a = req.query.returnTo) !== null && _a !== void 0 ? _a : req.headers.referer; (0, assert_ts_1.assert)(typeof returnToUrl === "string", `no logical returnTo url`); res.redirect(returnToUrl); }, ["/userinfo"]: function (req, res) { var _a, _b; let token = null; if (req.headers.authorization) { let authorizationHeader = req.headers.authorization; token = (_a = authorizationHeader === null || authorizationHeader === void 0 ? void 0 : authorizationHeader.split(" ")) === null || _a === void 0 ? void 0 : _a[1]; } else { token = (_b = req === null || req === void 0 ? void 0 : req.query) === null || _b === void 0 ? void 0 : _b.access_token; } (0, assert_ts_1.assert)(!!token, "no authorization header or access_token"); let { sub } = (0, jsonwebtoken_1.decode)(token, { json: true }); let user = personQuery((person) => { (0, assert_ts_1.assert)(!!person.id, `no email defined on person scenario`); return person.id === sub; }); (0, assert_ts_1.assert)(!!user, "no user in /userinfo"); let userinfo = { sub, name: user.name, given_name: user.name, family_name: user.name, email: user.email, email_verified: true, locale: "en", hd: "okta.com", }; res.status(200).json(userinfo); }, }; }; exports.createAuth0Handlers = createAuth0Handlers; //# sourceMappingURL=auth0-handlers.js.map