@simulacrum/auth0-simulator
Version:
Run local instance of Auth0 API for local development and integration testing
199 lines • 9.95 kB
JavaScript
;
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