@simulacrum/auth0-simulator
Version:
Run local instance of Auth0 API for local development and integration testing
145 lines • 6.37 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.getBaseAccessToken = exports.getIdToken = exports.createTokens = void 0;
const assert_ts_1 = require("assert-ts");
const base64_url_1 = require("base64-url");
const date_ts_1 = require("../auth/date.js");
const jwt_ts_1 = require("../auth/jwt.js");
const rules_runner_ts_1 = require("../rules/rules-runner.js");
const utils_ts_1 = require("./utils.js");
const refresh_token_ts_1 = require("../auth/refresh-token.js");
const createTokens = (_a) => __awaiter(void 0, [_a], void 0, function* ({ body, iss, clientID, audience, rulesDirectory, scope: scopeConfig, simulationStore, }) {
let { grant_type } = body;
let scope = (0, utils_ts_1.deriveScope)({ scopeConfig, clientID, audience });
let accessToken = (0, exports.getBaseAccessToken)({ iss, grant_type, scope, audience });
let user;
let nonce;
if (grant_type === "client_credentials") {
return { access_token: (0, jwt_ts_1.createJsonWebToken)(accessToken) };
}
// TODO: check refresh_token expiry date
else if (grant_type === "refresh_token") {
let { refresh_token: refreshTokenValue } = body;
let refreshToken = JSON.parse((0, base64_url_1.decode)(refreshTokenValue));
let findUser = (0, utils_ts_1.createPersonQuery)(simulationStore);
user = findUser((person) => person.id === refreshToken.user.id);
nonce = refreshToken.nonce;
(0, assert_ts_1.assert)(!!nonce, `400::No nonce in request`);
}
else {
let result = verifyUserExistsInStore({
simulationStore,
body,
grant_type,
});
user = result.user;
nonce = result.nonce;
}
(0, assert_ts_1.assert)(!!user, "500::No user found");
let { idTokenData, userData } = (0, exports.getIdToken)({
body,
iss,
user,
clientID,
nonce,
});
let context = {
clientID,
accessToken: { scope, sub: idTokenData.sub },
idToken: idTokenData,
};
let rulesRunner = (0, rules_runner_ts_1.createRulesRunner)(rulesDirectory);
// the rules mutate the values
yield rulesRunner(userData, context);
return {
access_token: (0, jwt_ts_1.createJsonWebToken)(Object.assign(Object.assign(Object.assign({}, accessToken), context.accessToken), (scope.split(" ").includes("email") ? { email: user.email } : {}))),
id_token: (0, jwt_ts_1.createJsonWebToken)(Object.assign(Object.assign({}, userData), context.idToken)),
refresh_token: (0, refresh_token_ts_1.issueRefreshToken)(scope, grant_type)
? (0, refresh_token_ts_1.createRefreshToken)({
exp: idTokenData.exp,
rotations: 0,
scope,
user,
nonce,
})
: undefined,
};
});
exports.createTokens = createTokens;
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,
};
(0, assert_ts_1.assert)(!!user.email, "500::User in store requires an email");
let idTokenData = {
alg: "RS256",
typ: "JWT",
iss,
exp: (0, date_ts_1.expiresAt)(),
iat: (0, date_ts_1.epochTime)(),
email: user.email,
aud: clientID,
sub: user.id,
};
if (typeof nonce !== "undefined") {
idTokenData.nonce = nonce;
}
return { userData, idTokenData };
};
exports.getIdToken = getIdToken;
const getBaseAccessToken = ({ iss, grant_type, scope, audience, }) => ({
iss,
exp: (0, date_ts_1.expiresAt)(),
iat: (0, date_ts_1.epochTime)(),
aud: audience,
gty: grant_type,
scope,
});
exports.getBaseAccessToken = getBaseAccessToken;
const verifyUserExistsInStore = ({ simulationStore, body, grant_type, }) => {
let { code } = body;
let personQuery = (0, utils_ts_1.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
(0, assert_ts_1.assert)(typeof code !== "undefined", "400::no code in /oauth/token");
[nonce, username] = (0, base64_url_1.decode)(code).split(":");
}
(0, assert_ts_1.assert)(!!username, `400::no nonce in store for ${code}`);
let user = personQuery((person) => {
(0, assert_ts_1.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;
}
});
(0, assert_ts_1.assert)(!!user, "401::Unauthorized");
return { user, nonce };
};
//# sourceMappingURL=oauth-handlers.js.map