@simulacrum/auth0-simulator 0.11.1 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/rolldown_runtime.cjs +29 -0
- package/dist/_virtual/rolldown_runtime.mjs +7 -0
- package/dist/auth/constants.cjs +15 -0
- package/dist/auth/constants.mjs +14 -0
- package/dist/auth/constants.mjs.map +1 -0
- package/dist/auth/date.cjs +8 -0
- package/dist/auth/date.mjs +7 -0
- package/dist/auth/date.mjs.map +1 -0
- package/dist/auth/jwt.cjs +16 -0
- package/dist/auth/jwt.mjs +15 -0
- package/dist/auth/jwt.mjs.map +1 -0
- package/dist/auth/refresh-token.cjs +24 -0
- package/dist/auth/refresh-token.mjs +23 -0
- package/dist/auth/refresh-token.mjs.map +1 -0
- package/dist/config/get-config.cjs +39 -0
- package/dist/config/get-config.mjs +39 -0
- package/dist/config/get-config.mjs.map +1 -0
- package/dist/handlers/auth0-handlers.cjs +207 -0
- package/dist/handlers/auth0-handlers.mjs +207 -0
- package/dist/handlers/auth0-handlers.mjs.map +1 -0
- package/dist/handlers/index.cjs +29 -0
- package/dist/handlers/index.mjs +27 -0
- package/dist/handlers/index.mjs.map +1 -0
- package/dist/handlers/login-redirect.cjs +24 -0
- package/dist/handlers/login-redirect.mjs +24 -0
- package/dist/handlers/login-redirect.mjs.map +1 -0
- package/dist/handlers/oauth-handlers.cjs +144 -0
- package/dist/handlers/oauth-handlers.mjs +144 -0
- package/dist/handlers/oauth-handlers.mjs.map +1 -0
- package/dist/handlers/openid-handlers.cjs +32 -0
- package/dist/handlers/openid-handlers.mjs +33 -0
- package/dist/handlers/openid-handlers.mjs.map +1 -0
- package/dist/handlers/url.cjs +6 -0
- package/dist/handlers/url.mjs +6 -0
- package/dist/handlers/url.mjs.map +1 -0
- package/dist/handlers/utils.cjs +25 -0
- package/dist/handlers/utils.mjs +24 -0
- package/dist/handlers/utils.mjs.map +1 -0
- package/dist/handlers/web-message.cjs +23 -0
- package/dist/handlers/web-message.mjs +23 -0
- package/dist/handlers/web-message.mjs.map +1 -0
- package/dist/index.cjs +15 -38751
- package/dist/index.d.cts +7 -175
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +21 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +22 -0
- package/dist/index.mjs.map +1 -0
- package/dist/middleware/create-cors.cjs +15 -0
- package/dist/middleware/create-cors.mjs +14 -0
- package/dist/middleware/create-cors.mjs.map +1 -0
- package/dist/middleware/error-handling.cjs +25 -0
- package/dist/middleware/error-handling.mjs +25 -0
- package/dist/middleware/error-handling.mjs.map +1 -0
- package/dist/middleware/no-cache.cjs +10 -0
- package/dist/middleware/no-cache.mjs +10 -0
- package/dist/middleware/no-cache.mjs.map +1 -0
- package/dist/middleware/session.cjs +19 -0
- package/dist/middleware/session.mjs +18 -0
- package/dist/middleware/session.mjs.map +1 -0
- package/dist/rules/extensionless-file-name.cjs +6 -0
- package/dist/rules/extensionless-file-name.mjs +6 -0
- package/dist/rules/extensionless-file-name.mjs.map +1 -0
- package/dist/rules/parse-rules-files.cjs +28 -0
- package/dist/rules/parse-rules-files.mjs +26 -0
- package/dist/rules/parse-rules-files.mjs.map +1 -0
- package/dist/rules/rules-runner.cjs +67 -0
- package/dist/rules/rules-runner.mjs +65 -0
- package/dist/rules/rules-runner.mjs.map +1 -0
- package/dist/store/entities.cjs +37 -0
- package/dist/store/entities.d.cts +99 -0
- package/dist/store/entities.d.cts.map +1 -0
- package/dist/store/entities.d.mts +100 -0
- package/dist/store/entities.d.mts.map +1 -0
- package/dist/store/entities.mjs +34 -0
- package/dist/store/entities.mjs.map +1 -0
- package/dist/store/index.cjs +44 -0
- package/dist/store/index.d.cts +22 -0
- package/dist/store/index.d.cts.map +1 -0
- package/dist/store/index.d.mts +22 -0
- package/dist/store/index.d.mts.map +1 -0
- package/dist/store/index.mjs +45 -0
- package/dist/store/index.mjs.map +1 -0
- package/dist/types.cjs +24 -0
- package/dist/types.d.cts +66 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +66 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +24 -0
- package/dist/types.mjs.map +1 -0
- package/dist/views/login.cjs +145 -0
- package/dist/views/login.mjs +146 -0
- package/dist/views/login.mjs.map +1 -0
- package/dist/views/username-password.cjs +39 -0
- package/dist/views/username-password.mjs +39 -0
- package/dist/views/username-password.mjs.map +1 -0
- package/dist/views/web-message.cjs +66 -0
- package/dist/views/web-message.mjs +65 -0
- package/dist/views/web-message.mjs.map +1 -0
- package/package.json +9 -9
- package/dist/index.d.ts +0 -189
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -38747
- package/dist/index.js.map +0 -1
- /package/dist/{public → views/public}/img/frontside-logo.png +0 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { createLoginRedirectHandler } from "./login-redirect.mjs";
|
|
2
|
+
import { createWebMessageHandler } from "./web-message.mjs";
|
|
3
|
+
import { createPersonQuery } from "./utils.mjs";
|
|
4
|
+
import { loginView } from "../views/login.mjs";
|
|
5
|
+
import { createTokens } from "./oauth-handlers.mjs";
|
|
6
|
+
import { userNamePasswordForm } from "../views/username-password.mjs";
|
|
7
|
+
import { stringify } from "querystring";
|
|
8
|
+
import { assert } from "assert-ts";
|
|
9
|
+
import { encode } from "base64-url";
|
|
10
|
+
import { decode as decode$1 } from "jsonwebtoken";
|
|
11
|
+
|
|
12
|
+
//#region src/handlers/auth0-handlers.ts
|
|
13
|
+
const createLogger = (debug) => ({ log: (...args) => {
|
|
14
|
+
if (!debug) return;
|
|
15
|
+
console.dir(...args);
|
|
16
|
+
} });
|
|
17
|
+
const createAuth0Handlers = (simulationStore, serviceURL, options, debug) => {
|
|
18
|
+
let { audience, scope, clientID, rulesDirectory } = options;
|
|
19
|
+
let personQuery = createPersonQuery(simulationStore);
|
|
20
|
+
let authorizeHandlers = {
|
|
21
|
+
query: createLoginRedirectHandler(options),
|
|
22
|
+
web_message: createWebMessageHandler()
|
|
23
|
+
};
|
|
24
|
+
let logger = createLogger(debug);
|
|
25
|
+
return {
|
|
26
|
+
["/heartbeat"]: function(_, res) {
|
|
27
|
+
res.status(200).json({ ok: true });
|
|
28
|
+
},
|
|
29
|
+
["/authorize"]: function(req, res, next) {
|
|
30
|
+
logger.log({ "/authorize": {
|
|
31
|
+
body: req.body,
|
|
32
|
+
query: req.query,
|
|
33
|
+
session: req.session
|
|
34
|
+
} });
|
|
35
|
+
let currentUser = req.query.currentUser;
|
|
36
|
+
assert(!!req.session, "no session");
|
|
37
|
+
if (currentUser) req.session.username = currentUser;
|
|
38
|
+
let responseMode = req.query.response_mode ?? "query";
|
|
39
|
+
assert(["query", "web_message"].includes(responseMode), `unknown response_mode ${responseMode}`);
|
|
40
|
+
let handler = authorizeHandlers[responseMode];
|
|
41
|
+
handler(req, res, next);
|
|
42
|
+
},
|
|
43
|
+
["/login"]: function(req, res) {
|
|
44
|
+
logger.log({ "/login": {
|
|
45
|
+
body: req.body,
|
|
46
|
+
query: req.query
|
|
47
|
+
} });
|
|
48
|
+
let query = req.query;
|
|
49
|
+
let responseClientId = query.client_id ?? clientID;
|
|
50
|
+
let responseAudience = query.audience ?? audience;
|
|
51
|
+
assert(!!responseClientId, `no clientID assigned`);
|
|
52
|
+
let html = loginView({
|
|
53
|
+
domain: new URL(serviceURL(req)).host,
|
|
54
|
+
scope,
|
|
55
|
+
redirectUri: query.redirect_uri,
|
|
56
|
+
clientID: responseClientId,
|
|
57
|
+
audience: responseAudience,
|
|
58
|
+
loginFailed: false
|
|
59
|
+
});
|
|
60
|
+
res.set("Content-Type", "text/html");
|
|
61
|
+
res.status(200).send(Buffer.from(html));
|
|
62
|
+
},
|
|
63
|
+
["/usernamepassword/login"]: function(req, res) {
|
|
64
|
+
logger.log({ "/usernamepassword/login": {
|
|
65
|
+
body: req.body,
|
|
66
|
+
query: req.query
|
|
67
|
+
} });
|
|
68
|
+
let { username, nonce, password } = req.body;
|
|
69
|
+
assert(!!username, "no username in /usernamepassword/login");
|
|
70
|
+
assert(!!nonce, "no nonce in /usernamepassword/login");
|
|
71
|
+
assert(!!req.session, "no session");
|
|
72
|
+
if (!personQuery((person) => person.email?.toLowerCase() === username.toLowerCase() && person.password === password)) {
|
|
73
|
+
let query = req.query;
|
|
74
|
+
let responseClientId = query.client_id ?? clientID;
|
|
75
|
+
let responseAudience = query.audience ?? audience;
|
|
76
|
+
assert(!!clientID, `no clientID assigned`);
|
|
77
|
+
let html = loginView({
|
|
78
|
+
domain: new URL(serviceURL(req)).host,
|
|
79
|
+
scope,
|
|
80
|
+
redirectUri: query.redirect_uri,
|
|
81
|
+
clientID: responseClientId,
|
|
82
|
+
audience: responseAudience,
|
|
83
|
+
loginFailed: true
|
|
84
|
+
});
|
|
85
|
+
res.set("Content-Type", "text/html");
|
|
86
|
+
res.status(400).send(html);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
req.session.username = username;
|
|
90
|
+
simulationStore.store.dispatch(simulationStore.actions.batchUpdater([simulationStore.schema.sessions.patch({ [nonce]: {
|
|
91
|
+
username,
|
|
92
|
+
nonce
|
|
93
|
+
} })]));
|
|
94
|
+
res.status(200).send(userNamePasswordForm(req.body));
|
|
95
|
+
},
|
|
96
|
+
["/login/callback"]: function(req, res) {
|
|
97
|
+
let wctx = JSON.parse(req.body.wctx);
|
|
98
|
+
logger.log({ "/login/callback": {
|
|
99
|
+
body: req.body,
|
|
100
|
+
query: req.query,
|
|
101
|
+
wctx
|
|
102
|
+
} });
|
|
103
|
+
let { redirect_uri, nonce } = wctx;
|
|
104
|
+
const { username } = simulationStore.schema.sessions.selectById(simulationStore.store.getState(), { id: nonce }) ?? {};
|
|
105
|
+
let routerUrl = `${redirect_uri}?${stringify({
|
|
106
|
+
code: encode(`${nonce}:${username}`),
|
|
107
|
+
...wctx
|
|
108
|
+
})}`;
|
|
109
|
+
res.redirect(302, routerUrl);
|
|
110
|
+
},
|
|
111
|
+
["/oauth/token"]: async function(req, res, next) {
|
|
112
|
+
logger.log({ "/oauth/token": {
|
|
113
|
+
body: req.body,
|
|
114
|
+
query: req.query
|
|
115
|
+
} });
|
|
116
|
+
try {
|
|
117
|
+
let iss = serviceURL(req);
|
|
118
|
+
let responseClientId = req?.body?.client_id ?? clientID;
|
|
119
|
+
let responseAudience = req?.body?.audience ?? audience;
|
|
120
|
+
assert(!!responseClientId, "500::no clientID in options or request body");
|
|
121
|
+
let tokens = await createTokens({
|
|
122
|
+
simulationStore,
|
|
123
|
+
body: req.body,
|
|
124
|
+
iss,
|
|
125
|
+
clientID: responseClientId,
|
|
126
|
+
audience: responseAudience,
|
|
127
|
+
rulesDirectory,
|
|
128
|
+
scope
|
|
129
|
+
});
|
|
130
|
+
res.status(200).json({
|
|
131
|
+
...tokens,
|
|
132
|
+
expires_in: 86400,
|
|
133
|
+
token_type: "Bearer"
|
|
134
|
+
});
|
|
135
|
+
} catch (error) {
|
|
136
|
+
next(error);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
["/v2/logout"]: function(req, res) {
|
|
140
|
+
req.session = null;
|
|
141
|
+
let returnToUrl = req.query.returnTo ?? req.headers.referer;
|
|
142
|
+
assert(typeof returnToUrl === "string", `no logical returnTo url`);
|
|
143
|
+
res.redirect(returnToUrl);
|
|
144
|
+
},
|
|
145
|
+
["/userinfo"]: function(req, res) {
|
|
146
|
+
let token = null;
|
|
147
|
+
if (req.headers.authorization) token = req.headers.authorization?.split(" ")?.[1];
|
|
148
|
+
else token = req?.query?.access_token;
|
|
149
|
+
assert(!!token, "no authorization header or access_token");
|
|
150
|
+
let { sub } = decode$1(token, { json: true });
|
|
151
|
+
let user = personQuery((person) => {
|
|
152
|
+
assert(!!person.id, `no email defined on person scenario`);
|
|
153
|
+
return person.id === sub;
|
|
154
|
+
});
|
|
155
|
+
assert(!!user, "no user in /userinfo");
|
|
156
|
+
let userinfo = {
|
|
157
|
+
sub,
|
|
158
|
+
name: user.name,
|
|
159
|
+
given_name: user.name,
|
|
160
|
+
family_name: user.name,
|
|
161
|
+
email: user.email,
|
|
162
|
+
email_verified: true,
|
|
163
|
+
locale: "en",
|
|
164
|
+
hd: "okta.com"
|
|
165
|
+
};
|
|
166
|
+
res.status(200).json(userinfo);
|
|
167
|
+
},
|
|
168
|
+
["/passwordless/start"]: function(req, res, next) {
|
|
169
|
+
logger.log({ "/passwordless/start": { body: req.body } });
|
|
170
|
+
try {
|
|
171
|
+
const { client_id, connection, email, phone_number } = req.body;
|
|
172
|
+
if (!client_id) {
|
|
173
|
+
res.status(400).json({ error: "client_id is required" });
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (!connection || connection !== "email" && connection !== "sms") {
|
|
177
|
+
res.status(400).json({ error: "connection must be 'email' or 'sms'" });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (connection === "email" && !email) {
|
|
181
|
+
res.status(400).json({ error: "email is required when connection is 'email'" });
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (connection === "sms" && !phone_number) {
|
|
185
|
+
res.status(400).json({ error: "phone_number is required when connection is 'sms'" });
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (connection === "email") res.status(200).json({
|
|
189
|
+
_id: "000000000000000000000000",
|
|
190
|
+
email,
|
|
191
|
+
email_verified: false
|
|
192
|
+
});
|
|
193
|
+
else res.status(200).json({
|
|
194
|
+
_id: "000000000000000000000000",
|
|
195
|
+
phone_number,
|
|
196
|
+
phone_verified: false
|
|
197
|
+
});
|
|
198
|
+
} catch (error) {
|
|
199
|
+
next(error);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
//#endregion
|
|
206
|
+
export { createAuth0Handlers };
|
|
207
|
+
//# sourceMappingURL=auth0-handlers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth0-handlers.mjs","names":["authorizeHandlers: Record<ResponseModes, RequestHandler>","responseClientId: string","responseAudience: string","token: string | null","decodeToken"],"sources":["../../src/handlers/auth0-handlers.ts"],"sourcesContent":["import type { ExtendedSimulationStore } from \"../store/index.ts\";\nimport type { Request, RequestHandler } from \"express\";\nimport type {\n Auth0Configuration,\n QueryParams,\n ResponseModes,\n} from \"../types.ts\";\nimport { createLoginRedirectHandler } from \"./login-redirect.ts\";\nimport { createWebMessageHandler } from \"./web-message.ts\";\nimport { loginView } from \"../views/login.ts\";\nimport { createTokens } from \"./oauth-handlers.ts\";\nimport { assert } from \"assert-ts\";\nimport { stringify } from \"querystring\";\nimport { encode } from \"base64-url\";\nimport { userNamePasswordForm } from \"../views/username-password.ts\";\nimport { decode as decodeToken } from \"jsonwebtoken\";\nimport { createPersonQuery } from \"./utils.ts\";\n\nexport type Routes =\n | \"/heartbeat\"\n | \"/authorize\"\n | \"/login\"\n | \"/usernamepassword/login\"\n | \"/login/callback\"\n | \"/oauth/token\"\n | \"/v2/logout\"\n | \"/userinfo\"\n | \"/passwordless/start\";\n\nexport type AuthSession = { username: string; nonce: string };\n\ntype LoggerArgs = Parameters<typeof console.dir>;\n\nconst createLogger = (debug: boolean) => ({\n log: (...args: LoggerArgs): void => {\n if (!debug) {\n return;\n }\n\n console.dir(...args);\n },\n});\n\nexport const createAuth0Handlers = (\n simulationStore: ExtendedSimulationStore,\n serviceURL: (request: Request) => string,\n options: Auth0Configuration,\n debug: boolean\n): Record<Routes, RequestHandler> => {\n let { audience, scope, clientID, rulesDirectory } = options;\n let personQuery = createPersonQuery(simulationStore);\n\n let authorizeHandlers: Record<ResponseModes, RequestHandler> = {\n query: createLoginRedirectHandler(options),\n web_message: createWebMessageHandler(),\n };\n\n let logger = createLogger(debug);\n\n return {\n [\"/heartbeat\"]: function (_, res) {\n res.status(200).json({ ok: true });\n },\n\n [\"/authorize\"]: function (req, res, next) {\n logger.log({\n \"/authorize\": {\n body: req.body,\n query: req.query,\n session: req.session,\n },\n });\n let currentUser = req.query.currentUser as string | undefined;\n\n assert(!!req.session, \"no session\");\n\n if (currentUser) {\n // the request is a silent login.\n // We fake an existing login by\n // adding the user to the session\n req.session.username = currentUser;\n }\n\n let responseMode = (req.query.response_mode ?? \"query\") as ResponseModes;\n\n assert(\n [\"query\", \"web_message\"].includes(responseMode),\n `unknown response_mode ${responseMode}`\n );\n\n let handler = authorizeHandlers[responseMode];\n\n handler(req, res, next);\n },\n\n [\"/login\"]: function (req, res) {\n logger.log({ \"/login\": { body: req.body, query: req.query } });\n let query = req.query as QueryParams;\n let responseClientId = query.client_id ?? clientID;\n let responseAudience = query.audience ?? audience;\n assert(!!responseClientId, `no clientID assigned`);\n\n let html = loginView({\n domain: new URL(serviceURL(req)).host,\n scope,\n redirectUri: query.redirect_uri,\n clientID: responseClientId,\n audience: responseAudience,\n loginFailed: false,\n });\n\n res.set(\"Content-Type\", \"text/html\");\n\n res.status(200).send(Buffer.from(html));\n },\n\n [\"/usernamepassword/login\"]: function (req, res) {\n logger.log({\n \"/usernamepassword/login\": { body: req.body, query: req.query },\n });\n let { username, nonce, password } = req.body;\n\n assert(!!username, \"no username in /usernamepassword/login\");\n assert(!!nonce, \"no nonce in /usernamepassword/login\");\n assert(!!req.session, \"no session\");\n\n let user = personQuery(\n (person) =>\n person.email?.toLowerCase() === username.toLowerCase() &&\n person.password === password\n );\n\n if (!user) {\n let query = req.query as QueryParams;\n let responseClientId = query.client_id ?? clientID;\n let responseAudience = query.audience ?? audience;\n\n assert(!!clientID, `no clientID assigned`);\n\n let html = loginView({\n domain: new URL(serviceURL(req)).host,\n scope,\n redirectUri: query.redirect_uri,\n clientID: responseClientId,\n audience: responseAudience,\n loginFailed: true,\n });\n\n res.set(\"Content-Type\", \"text/html\");\n\n res.status(400).send(html);\n return;\n }\n\n req.session.username = username;\n\n simulationStore.store.dispatch(\n simulationStore.actions.batchUpdater([\n simulationStore.schema.sessions.patch({\n [nonce]: { username, nonce },\n }),\n ])\n );\n\n res.status(200).send(userNamePasswordForm(req.body));\n },\n\n [\"/login/callback\"]: function (req, res) {\n let wctx = JSON.parse(req.body.wctx);\n logger.log({\n \"/login/callback\": { body: req.body, query: req.query, wctx },\n });\n\n let { redirect_uri, nonce } = wctx;\n\n const session = simulationStore.schema.sessions.selectById(\n simulationStore.store.getState(),\n { id: nonce }\n );\n\n const { username } = session ?? {};\n\n let encodedNonce = encode(`${nonce}:${username}`);\n\n let qs = stringify({ code: encodedNonce, ...wctx });\n\n let routerUrl = `${redirect_uri}?${qs}`;\n\n res.redirect(302, routerUrl);\n },\n\n [\"/oauth/token\"]: async function (req, res, next) {\n logger.log({ \"/oauth/token\": { body: req.body, query: req.query } });\n try {\n let iss = serviceURL(req);\n\n let responseClientId: string =\n (req?.body?.client_id as string) ?? clientID;\n let responseAudience: string =\n (req?.body?.audience as string) ?? audience;\n\n assert(\n !!responseClientId,\n \"500::no clientID in options or request body\"\n );\n\n let tokens = await createTokens({\n simulationStore,\n body: req.body,\n iss,\n clientID: responseClientId,\n audience: responseAudience,\n rulesDirectory,\n scope,\n });\n\n res.status(200).json({\n ...tokens,\n expires_in: 86400,\n token_type: \"Bearer\",\n });\n } catch (error) {\n next(error);\n }\n },\n\n [\"/v2/logout\"]: function (req, res) {\n req.session = null;\n\n let returnToUrl = req.query.returnTo ?? req.headers.referer;\n\n assert(typeof returnToUrl === \"string\", `no logical returnTo url`);\n\n res.redirect(returnToUrl);\n },\n\n [\"/userinfo\"]: function (req, res) {\n let token: string | null = null;\n if (req.headers.authorization) {\n let authorizationHeader = req.headers.authorization;\n token = authorizationHeader?.split(\" \")?.[1];\n } else {\n token = req?.query?.access_token as string;\n }\n\n assert(!!token, \"no authorization header or access_token\");\n let { sub } = decodeToken(token, { json: true }) as { sub: string };\n\n let user = personQuery((person) => {\n assert(!!person.id, `no email defined on person scenario`);\n\n return person.id === sub;\n });\n\n assert(!!user, \"no user in /userinfo\");\n\n let userinfo = {\n sub,\n name: user.name,\n given_name: user.name,\n family_name: user.name,\n email: user.email,\n email_verified: true,\n locale: \"en\",\n hd: \"okta.com\",\n };\n\n res.status(200).json(userinfo);\n },\n\n [\"/passwordless/start\"]: function (req, res, next) {\n logger.log({ \"/passwordless/start\": { body: req.body } });\n\n try {\n const { client_id, connection, email, phone_number } = req.body;\n\n // Validate required fields\n if (!client_id) {\n res.status(400).json({ error: \"client_id is required\" });\n return;\n }\n\n if (!connection || (connection !== \"email\" && connection !== \"sms\")) {\n res.status(400).json({\n error: \"connection must be 'email' or 'sms'\",\n });\n return;\n }\n\n if (connection === \"email\" && !email) {\n res.status(400).json({\n error: \"email is required when connection is 'email'\",\n });\n return;\n }\n\n if (connection === \"sms\" && !phone_number) {\n res.status(400).json({\n error: \"phone_number is required when connection is 'sms'\",\n });\n return;\n }\n\n // Return appropriate response based on connection type\n if (connection === \"email\") {\n res.status(200).json({\n _id: \"000000000000000000000000\",\n email: email,\n email_verified: false,\n });\n } else {\n res.status(200).json({\n _id: \"000000000000000000000000\",\n phone_number: phone_number,\n phone_verified: false,\n });\n }\n } catch (error) {\n next(error);\n }\n },\n };\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_create_cors = require('../middleware/create-cors.cjs');
|
|
3
|
+
const require_no_cache = require('../middleware/no-cache.cjs');
|
|
4
|
+
const require_session = require('../middleware/session.cjs');
|
|
5
|
+
const require_error_handling = require('../middleware/error-handling.cjs');
|
|
6
|
+
const require_auth0_handlers = require('./auth0-handlers.cjs');
|
|
7
|
+
const require_openid_handlers = require('./openid-handlers.cjs');
|
|
8
|
+
require('../types.cjs');
|
|
9
|
+
let express = require("express");
|
|
10
|
+
express = require_rolldown_runtime.__toESM(express);
|
|
11
|
+
let path = require("path");
|
|
12
|
+
path = require_rolldown_runtime.__toESM(path);
|
|
13
|
+
|
|
14
|
+
//#region src/handlers/index.ts
|
|
15
|
+
const publicDir = path.default.join(__dirname, "..", "views", "public");
|
|
16
|
+
const extendRouter = (config, extend, debug = false) => (router, simulationStore) => {
|
|
17
|
+
const serviceURL = (request) => `${request.protocol}://${request.get("Host")}/`;
|
|
18
|
+
const auth0 = require_auth0_handlers.createAuth0Handlers(simulationStore, serviceURL, config, debug);
|
|
19
|
+
const openid = require_openid_handlers.createOpenIdHandlers(serviceURL);
|
|
20
|
+
router.use(express.default.static(publicDir)).use(require_session.createSession()).use(require_create_cors.createCors()).use(require_no_cache.noCache());
|
|
21
|
+
if (extend) extend(router, simulationStore);
|
|
22
|
+
router.get("/health", (_, response) => {
|
|
23
|
+
response.send({ status: "ok" });
|
|
24
|
+
}).get("/heartbeat", auth0["/heartbeat"]).get("/authorize", auth0["/authorize"]).get("/login", auth0["/login"]).get("/u/login", auth0["/usernamepassword/login"]).post("/usernamepassword/login", auth0["/usernamepassword/login"]).post("/login/callback", auth0["/login/callback"]).post("/oauth/token", auth0["/oauth/token"]).post("/passwordless/start", auth0["/passwordless/start"]).get("/userinfo", auth0["/userinfo"]).get("/v2/logout", auth0["/v2/logout"]).get("/.well-known/jwks.json", openid["/.well-known/jwks.json"]).get("/.well-known/openid-configuration", openid["/.well-known/openid-configuration"]);
|
|
25
|
+
router.use(require_error_handling.defaultErrorHandler);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
exports.extendRouter = extendRouter;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createCors } from "../middleware/create-cors.mjs";
|
|
2
|
+
import { noCache } from "../middleware/no-cache.mjs";
|
|
3
|
+
import { createSession } from "../middleware/session.mjs";
|
|
4
|
+
import { defaultErrorHandler } from "../middleware/error-handling.mjs";
|
|
5
|
+
import { createAuth0Handlers } from "./auth0-handlers.mjs";
|
|
6
|
+
import { createOpenIdHandlers } from "./openid-handlers.mjs";
|
|
7
|
+
import "../types.mjs";
|
|
8
|
+
import express, { Router } from "express";
|
|
9
|
+
import path from "path";
|
|
10
|
+
|
|
11
|
+
//#region src/handlers/index.ts
|
|
12
|
+
const publicDir = path.join(import.meta.dirname, "..", "views", "public");
|
|
13
|
+
const extendRouter = (config, extend, debug = false) => (router, simulationStore) => {
|
|
14
|
+
const serviceURL = (request) => `${request.protocol}://${request.get("Host")}/`;
|
|
15
|
+
const auth0 = createAuth0Handlers(simulationStore, serviceURL, config, debug);
|
|
16
|
+
const openid = createOpenIdHandlers(serviceURL);
|
|
17
|
+
router.use(express.static(publicDir)).use(createSession()).use(createCors()).use(noCache());
|
|
18
|
+
if (extend) extend(router, simulationStore);
|
|
19
|
+
router.get("/health", (_, response) => {
|
|
20
|
+
response.send({ status: "ok" });
|
|
21
|
+
}).get("/heartbeat", auth0["/heartbeat"]).get("/authorize", auth0["/authorize"]).get("/login", auth0["/login"]).get("/u/login", auth0["/usernamepassword/login"]).post("/usernamepassword/login", auth0["/usernamepassword/login"]).post("/login/callback", auth0["/login/callback"]).post("/oauth/token", auth0["/oauth/token"]).post("/passwordless/start", auth0["/passwordless/start"]).get("/userinfo", auth0["/userinfo"]).get("/v2/logout", auth0["/v2/logout"]).get("/.well-known/jwks.json", openid["/.well-known/jwks.json"]).get("/.well-known/openid-configuration", openid["/.well-known/openid-configuration"]);
|
|
22
|
+
router.use(defaultErrorHandler);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { extendRouter };
|
|
27
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/handlers/index.ts"],"sourcesContent":["import express, { type Request, type Express, Router } from \"express\";\nimport type { ExtendedSimulationStore } from \"../store/index.ts\";\nimport { createCors } from \"../middleware/create-cors.ts\";\nimport { noCache } from \"../middleware/no-cache.ts\";\nimport { createSession } from \"../middleware/session.ts\";\nimport { defaultErrorHandler } from \"../middleware/error-handling.ts\";\nimport { createAuth0Handlers } from \"./auth0-handlers.ts\";\nimport { createOpenIdHandlers } from \"./openid-handlers.ts\";\nimport path from \"path\";\nimport { type Auth0Configuration } from \"../types.ts\";\n\nconst publicDir = path.join(import.meta.dirname, \"..\", \"views\", \"public\");\nexport const extendRouter =\n (\n config: Auth0Configuration,\n extend:\n | ((router: Router, simulationStore: ExtendedSimulationStore) => void)\n | undefined,\n debug = false\n ) =>\n (router: Express, simulationStore: ExtendedSimulationStore) => {\n const serviceURL = (request: Request) =>\n `${request.protocol}://${request.get(\"Host\")}/`;\n const auth0 = createAuth0Handlers(\n simulationStore,\n serviceURL,\n config,\n debug\n );\n const openid = createOpenIdHandlers(serviceURL);\n\n router\n .use(express.static(publicDir))\n .use(createSession())\n .use(createCors())\n .use(noCache());\n\n if (extend) {\n extend(router, simulationStore);\n }\n\n router\n .get(\"/health\", (_, response) => {\n response.send({ status: \"ok\" });\n })\n .get(\"/heartbeat\", auth0[\"/heartbeat\"])\n .get(\"/authorize\", auth0[\"/authorize\"])\n .get(\"/login\", auth0[\"/login\"])\n .get(\"/u/login\", auth0[\"/usernamepassword/login\"])\n .post(\"/usernamepassword/login\", auth0[\"/usernamepassword/login\"])\n .post(\"/login/callback\", auth0[\"/login/callback\"])\n .post(\"/oauth/token\", auth0[\"/oauth/token\"])\n .post(\"/passwordless/start\", auth0[\"/passwordless/start\"])\n .get(\"/userinfo\", auth0[\"/userinfo\"])\n .get(\"/v2/logout\", auth0[\"/v2/logout\"])\n .get(\"/.well-known/jwks.json\", openid[\"/.well-known/jwks.json\"])\n .get(\n \"/.well-known/openid-configuration\",\n openid[\"/.well-known/openid-configuration\"]\n );\n\n // needs to be the last middleware added\n router.use(defaultErrorHandler);\n };\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,YAAY,KAAK,KAAK,OAAO,KAAK,SAAS,MAAM,SAAS,SAAS;AACzE,MAAa,gBAET,QACA,QAGA,QAAQ,WAET,QAAiB,oBAA6C;CAC7D,MAAM,cAAc,YAClB,GAAG,QAAQ,SAAS,KAAK,QAAQ,IAAI,OAAO,CAAC;CAC/C,MAAM,QAAQ,oBACZ,iBACA,YACA,QACA,MACD;CACD,MAAM,SAAS,qBAAqB,WAAW;AAE/C,QACG,IAAI,QAAQ,OAAO,UAAU,CAAC,CAC9B,IAAI,eAAe,CAAC,CACpB,IAAI,YAAY,CAAC,CACjB,IAAI,SAAS,CAAC;AAEjB,KAAI,OACF,QAAO,QAAQ,gBAAgB;AAGjC,QACG,IAAI,YAAY,GAAG,aAAa;AAC/B,WAAS,KAAK,EAAE,QAAQ,MAAM,CAAC;GAC/B,CACD,IAAI,cAAc,MAAM,cAAc,CACtC,IAAI,cAAc,MAAM,cAAc,CACtC,IAAI,UAAU,MAAM,UAAU,CAC9B,IAAI,YAAY,MAAM,2BAA2B,CACjD,KAAK,2BAA2B,MAAM,2BAA2B,CACjE,KAAK,mBAAmB,MAAM,mBAAmB,CACjD,KAAK,gBAAgB,MAAM,gBAAgB,CAC3C,KAAK,uBAAuB,MAAM,uBAAuB,CACzD,IAAI,aAAa,MAAM,aAAa,CACpC,IAAI,cAAc,MAAM,cAAc,CACtC,IAAI,0BAA0B,OAAO,0BAA0B,CAC/D,IACC,qCACA,OAAO,qCACR;AAGH,QAAO,IAAI,oBAAoB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let querystring = require("querystring");
|
|
3
|
+
|
|
4
|
+
//#region src/handlers/login-redirect.ts
|
|
5
|
+
const createLoginRedirectHandler = (options) => function loginRedirect(req, res) {
|
|
6
|
+
let { client_id, audience, redirect_uri, scope, state, nonce, response_mode, code_challenge, code_challenge_method, auth0Client, response_type } = req.query;
|
|
7
|
+
res.status(302).redirect(`/login?${(0, querystring.stringify)({
|
|
8
|
+
state,
|
|
9
|
+
redirect_uri,
|
|
10
|
+
client: client_id || options.clientID,
|
|
11
|
+
protocol: "oauth2",
|
|
12
|
+
scope,
|
|
13
|
+
response_type,
|
|
14
|
+
response_mode,
|
|
15
|
+
nonce,
|
|
16
|
+
code_challenge,
|
|
17
|
+
code_challenge_method,
|
|
18
|
+
auth0Client,
|
|
19
|
+
audience: audience || options.audience
|
|
20
|
+
})}`);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
exports.createLoginRedirectHandler = createLoginRedirectHandler;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { stringify } from "querystring";
|
|
2
|
+
|
|
3
|
+
//#region src/handlers/login-redirect.ts
|
|
4
|
+
const createLoginRedirectHandler = (options) => function loginRedirect(req, res) {
|
|
5
|
+
let { client_id, audience, redirect_uri, scope, state, nonce, response_mode, code_challenge, code_challenge_method, auth0Client, response_type } = req.query;
|
|
6
|
+
res.status(302).redirect(`/login?${stringify({
|
|
7
|
+
state,
|
|
8
|
+
redirect_uri,
|
|
9
|
+
client: client_id || options.clientID,
|
|
10
|
+
protocol: "oauth2",
|
|
11
|
+
scope,
|
|
12
|
+
response_type,
|
|
13
|
+
response_mode,
|
|
14
|
+
nonce,
|
|
15
|
+
code_challenge,
|
|
16
|
+
code_challenge_method,
|
|
17
|
+
auth0Client,
|
|
18
|
+
audience: audience || options.audience
|
|
19
|
+
})}`);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { createLoginRedirectHandler };
|
|
24
|
+
//# sourceMappingURL=login-redirect.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-redirect.mjs","names":[],"sources":["../../src/handlers/login-redirect.ts"],"sourcesContent":["import type { Request, Response, RequestHandler } from \"express\";\nimport type { Auth0Configuration, QueryParams } from \"../types.ts\";\nimport { stringify } from \"querystring\";\n\nexport const createLoginRedirectHandler = (\n options: Auth0Configuration\n): RequestHandler =>\n function loginRedirect(req: Request, res: Response) {\n let {\n client_id,\n audience,\n redirect_uri,\n scope,\n state,\n nonce,\n response_mode,\n code_challenge,\n code_challenge_method,\n auth0Client,\n response_type,\n } = req.query as QueryParams;\n\n res.status(302).redirect(\n `/login?${stringify({\n state,\n redirect_uri,\n client: client_id || options.clientID,\n protocol: \"oauth2\",\n scope,\n response_type,\n response_mode,\n nonce,\n code_challenge,\n code_challenge_method,\n auth0Client,\n audience: audience || options.audience,\n })}`\n );\n };\n"],"mappings":";;;AAIA,MAAa,8BACX,YAEA,SAAS,cAAc,KAAc,KAAe;CAClD,IAAI,EACF,WACA,UACA,cACA,OACA,OACA,OACA,eACA,gBACA,uBACA,aACA,kBACE,IAAI;AAER,KAAI,OAAO,IAAI,CAAC,SACd,UAAU,UAAU;EAClB;EACA;EACA,QAAQ,aAAa,QAAQ;EAC7B,UAAU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU,YAAY,QAAQ;EAC/B,CAAC,GACH"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
require('../store/entities.cjs');
|
|
3
|
+
require('../store/index.cjs');
|
|
4
|
+
const require_utils = require('./utils.cjs');
|
|
5
|
+
const require_date = require('../auth/date.cjs');
|
|
6
|
+
const require_jwt = require('../auth/jwt.cjs');
|
|
7
|
+
const require_rules_runner = require('../rules/rules-runner.cjs');
|
|
8
|
+
const require_refresh_token = require('../auth/refresh-token.cjs');
|
|
9
|
+
let assert_ts = require("assert-ts");
|
|
10
|
+
let base64_url = require("base64-url");
|
|
11
|
+
|
|
12
|
+
//#region src/handlers/oauth-handlers.ts
|
|
13
|
+
const createTokens = async ({ body, iss, clientID, audience, rulesDirectory, scope: scopeConfig, simulationStore }) => {
|
|
14
|
+
let { grant_type } = body;
|
|
15
|
+
let scope = require_utils.deriveScope({
|
|
16
|
+
scopeConfig,
|
|
17
|
+
clientID,
|
|
18
|
+
audience
|
|
19
|
+
});
|
|
20
|
+
let accessToken = getBaseAccessToken({
|
|
21
|
+
iss,
|
|
22
|
+
grant_type,
|
|
23
|
+
scope,
|
|
24
|
+
audience
|
|
25
|
+
});
|
|
26
|
+
let user;
|
|
27
|
+
let nonce;
|
|
28
|
+
if (grant_type === "client_credentials") return { access_token: require_jwt.createJsonWebToken(accessToken) };
|
|
29
|
+
else if (grant_type === "refresh_token") {
|
|
30
|
+
let { refresh_token: refreshTokenValue } = body;
|
|
31
|
+
let refreshToken = JSON.parse((0, base64_url.decode)(refreshTokenValue));
|
|
32
|
+
user = require_utils.createPersonQuery(simulationStore)((person) => person.id === refreshToken.user.id);
|
|
33
|
+
nonce = refreshToken.nonce;
|
|
34
|
+
(0, assert_ts.assert)(!!nonce, `400::No nonce in request`);
|
|
35
|
+
} else {
|
|
36
|
+
let result = verifyUserExistsInStore({
|
|
37
|
+
simulationStore,
|
|
38
|
+
body,
|
|
39
|
+
grant_type
|
|
40
|
+
});
|
|
41
|
+
user = result.user;
|
|
42
|
+
nonce = result.nonce;
|
|
43
|
+
}
|
|
44
|
+
(0, assert_ts.assert)(!!user, "500::No user found");
|
|
45
|
+
let { idTokenData, userData } = getIdToken({
|
|
46
|
+
body,
|
|
47
|
+
iss,
|
|
48
|
+
user,
|
|
49
|
+
clientID,
|
|
50
|
+
nonce
|
|
51
|
+
});
|
|
52
|
+
let context = {
|
|
53
|
+
clientID,
|
|
54
|
+
accessToken: {
|
|
55
|
+
scope,
|
|
56
|
+
sub: idTokenData.sub
|
|
57
|
+
},
|
|
58
|
+
idToken: idTokenData
|
|
59
|
+
};
|
|
60
|
+
await require_rules_runner.createRulesRunner(rulesDirectory)(userData, context);
|
|
61
|
+
return {
|
|
62
|
+
access_token: require_jwt.createJsonWebToken({
|
|
63
|
+
...accessToken,
|
|
64
|
+
...context.accessToken,
|
|
65
|
+
...scope.split(" ").includes("email") ? { email: user.email } : {}
|
|
66
|
+
}),
|
|
67
|
+
id_token: require_jwt.createJsonWebToken({
|
|
68
|
+
...userData,
|
|
69
|
+
...context.idToken
|
|
70
|
+
}),
|
|
71
|
+
refresh_token: require_refresh_token.issueRefreshToken(scope, grant_type) ? require_refresh_token.createRefreshToken({
|
|
72
|
+
exp: idTokenData.exp,
|
|
73
|
+
rotations: 0,
|
|
74
|
+
scope,
|
|
75
|
+
user,
|
|
76
|
+
nonce
|
|
77
|
+
}) : void 0
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
const getIdToken = ({ body, iss, user, clientID, nonce }) => {
|
|
81
|
+
let userData = {
|
|
82
|
+
name: body?.name ?? user.name,
|
|
83
|
+
email: body?.email ?? user.email,
|
|
84
|
+
email_verified: true,
|
|
85
|
+
user_id: body?.id ?? user.id,
|
|
86
|
+
nickname: body?.nickname,
|
|
87
|
+
picture: body?.picture ?? user.picture,
|
|
88
|
+
identities: body?.identities
|
|
89
|
+
};
|
|
90
|
+
(0, assert_ts.assert)(!!user.email, "500::User in store requires an email");
|
|
91
|
+
let idTokenData = {
|
|
92
|
+
alg: "RS256",
|
|
93
|
+
typ: "JWT",
|
|
94
|
+
iss,
|
|
95
|
+
exp: require_date.expiresAt(),
|
|
96
|
+
iat: require_date.epochTime(),
|
|
97
|
+
email: user.email,
|
|
98
|
+
aud: clientID,
|
|
99
|
+
sub: user.id
|
|
100
|
+
};
|
|
101
|
+
if (typeof nonce !== "undefined") idTokenData.nonce = nonce;
|
|
102
|
+
return {
|
|
103
|
+
userData,
|
|
104
|
+
idTokenData
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
const getBaseAccessToken = ({ iss, grant_type, scope, audience }) => ({
|
|
108
|
+
iss,
|
|
109
|
+
exp: require_date.expiresAt(),
|
|
110
|
+
iat: require_date.epochTime(),
|
|
111
|
+
aud: audience,
|
|
112
|
+
gty: grant_type,
|
|
113
|
+
scope
|
|
114
|
+
});
|
|
115
|
+
const verifyUserExistsInStore = ({ simulationStore, body, grant_type }) => {
|
|
116
|
+
let { code } = body;
|
|
117
|
+
let personQuery = require_utils.createPersonQuery(simulationStore);
|
|
118
|
+
let nonce;
|
|
119
|
+
let username;
|
|
120
|
+
let password;
|
|
121
|
+
if (grant_type === "http://auth0.com/oauth/grant-type/passwordless/otp") username = body.username;
|
|
122
|
+
else if (grant_type === "password") {
|
|
123
|
+
username = body.username;
|
|
124
|
+
password = body.password;
|
|
125
|
+
} else {
|
|
126
|
+
(0, assert_ts.assert)(typeof code !== "undefined", "400::no code in /oauth/token");
|
|
127
|
+
[nonce, username] = (0, base64_url.decode)(code).split(":");
|
|
128
|
+
(0, assert_ts.assert)(!!username, `400::no nonce in store for ${code}`);
|
|
129
|
+
}
|
|
130
|
+
let user = personQuery((person) => {
|
|
131
|
+
(0, assert_ts.assert)(!!person.email, `500::no email defined on person scenario`);
|
|
132
|
+
let valid = person.email.toLowerCase() === username.toLowerCase();
|
|
133
|
+
if (typeof password === "undefined") return valid;
|
|
134
|
+
else return valid && password === person.password;
|
|
135
|
+
});
|
|
136
|
+
(0, assert_ts.assert)(!!user, "401::Unauthorized");
|
|
137
|
+
return {
|
|
138
|
+
user,
|
|
139
|
+
nonce
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
//#endregion
|
|
144
|
+
exports.createTokens = createTokens;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import "../store/entities.mjs";
|
|
2
|
+
import "../store/index.mjs";
|
|
3
|
+
import { createPersonQuery, deriveScope } from "./utils.mjs";
|
|
4
|
+
import { epochTime, expiresAt } from "../auth/date.mjs";
|
|
5
|
+
import { createJsonWebToken } from "../auth/jwt.mjs";
|
|
6
|
+
import { createRulesRunner } from "../rules/rules-runner.mjs";
|
|
7
|
+
import { createRefreshToken, issueRefreshToken } from "../auth/refresh-token.mjs";
|
|
8
|
+
import { assert } from "assert-ts";
|
|
9
|
+
import { decode } from "base64-url";
|
|
10
|
+
|
|
11
|
+
//#region src/handlers/oauth-handlers.ts
|
|
12
|
+
const createTokens = async ({ body, iss, clientID, audience, rulesDirectory, scope: scopeConfig, simulationStore }) => {
|
|
13
|
+
let { grant_type } = body;
|
|
14
|
+
let scope = deriveScope({
|
|
15
|
+
scopeConfig,
|
|
16
|
+
clientID,
|
|
17
|
+
audience
|
|
18
|
+
});
|
|
19
|
+
let accessToken = getBaseAccessToken({
|
|
20
|
+
iss,
|
|
21
|
+
grant_type,
|
|
22
|
+
scope,
|
|
23
|
+
audience
|
|
24
|
+
});
|
|
25
|
+
let user;
|
|
26
|
+
let nonce;
|
|
27
|
+
if (grant_type === "client_credentials") return { access_token: createJsonWebToken(accessToken) };
|
|
28
|
+
else if (grant_type === "refresh_token") {
|
|
29
|
+
let { refresh_token: refreshTokenValue } = body;
|
|
30
|
+
let refreshToken = JSON.parse(decode(refreshTokenValue));
|
|
31
|
+
user = createPersonQuery(simulationStore)((person) => person.id === refreshToken.user.id);
|
|
32
|
+
nonce = refreshToken.nonce;
|
|
33
|
+
assert(!!nonce, `400::No nonce in request`);
|
|
34
|
+
} else {
|
|
35
|
+
let result = verifyUserExistsInStore({
|
|
36
|
+
simulationStore,
|
|
37
|
+
body,
|
|
38
|
+
grant_type
|
|
39
|
+
});
|
|
40
|
+
user = result.user;
|
|
41
|
+
nonce = result.nonce;
|
|
42
|
+
}
|
|
43
|
+
assert(!!user, "500::No user found");
|
|
44
|
+
let { idTokenData, userData } = getIdToken({
|
|
45
|
+
body,
|
|
46
|
+
iss,
|
|
47
|
+
user,
|
|
48
|
+
clientID,
|
|
49
|
+
nonce
|
|
50
|
+
});
|
|
51
|
+
let context = {
|
|
52
|
+
clientID,
|
|
53
|
+
accessToken: {
|
|
54
|
+
scope,
|
|
55
|
+
sub: idTokenData.sub
|
|
56
|
+
},
|
|
57
|
+
idToken: idTokenData
|
|
58
|
+
};
|
|
59
|
+
await createRulesRunner(rulesDirectory)(userData, context);
|
|
60
|
+
return {
|
|
61
|
+
access_token: createJsonWebToken({
|
|
62
|
+
...accessToken,
|
|
63
|
+
...context.accessToken,
|
|
64
|
+
...scope.split(" ").includes("email") ? { email: user.email } : {}
|
|
65
|
+
}),
|
|
66
|
+
id_token: createJsonWebToken({
|
|
67
|
+
...userData,
|
|
68
|
+
...context.idToken
|
|
69
|
+
}),
|
|
70
|
+
refresh_token: issueRefreshToken(scope, grant_type) ? createRefreshToken({
|
|
71
|
+
exp: idTokenData.exp,
|
|
72
|
+
rotations: 0,
|
|
73
|
+
scope,
|
|
74
|
+
user,
|
|
75
|
+
nonce
|
|
76
|
+
}) : void 0
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
const getIdToken = ({ body, iss, user, clientID, nonce }) => {
|
|
80
|
+
let userData = {
|
|
81
|
+
name: body?.name ?? user.name,
|
|
82
|
+
email: body?.email ?? user.email,
|
|
83
|
+
email_verified: true,
|
|
84
|
+
user_id: body?.id ?? user.id,
|
|
85
|
+
nickname: body?.nickname,
|
|
86
|
+
picture: body?.picture ?? user.picture,
|
|
87
|
+
identities: body?.identities
|
|
88
|
+
};
|
|
89
|
+
assert(!!user.email, "500::User in store requires an email");
|
|
90
|
+
let idTokenData = {
|
|
91
|
+
alg: "RS256",
|
|
92
|
+
typ: "JWT",
|
|
93
|
+
iss,
|
|
94
|
+
exp: expiresAt(),
|
|
95
|
+
iat: epochTime(),
|
|
96
|
+
email: user.email,
|
|
97
|
+
aud: clientID,
|
|
98
|
+
sub: user.id
|
|
99
|
+
};
|
|
100
|
+
if (typeof nonce !== "undefined") idTokenData.nonce = nonce;
|
|
101
|
+
return {
|
|
102
|
+
userData,
|
|
103
|
+
idTokenData
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
const getBaseAccessToken = ({ iss, grant_type, scope, audience }) => ({
|
|
107
|
+
iss,
|
|
108
|
+
exp: expiresAt(),
|
|
109
|
+
iat: epochTime(),
|
|
110
|
+
aud: audience,
|
|
111
|
+
gty: grant_type,
|
|
112
|
+
scope
|
|
113
|
+
});
|
|
114
|
+
const verifyUserExistsInStore = ({ simulationStore, body, grant_type }) => {
|
|
115
|
+
let { code } = body;
|
|
116
|
+
let personQuery = createPersonQuery(simulationStore);
|
|
117
|
+
let nonce;
|
|
118
|
+
let username;
|
|
119
|
+
let password;
|
|
120
|
+
if (grant_type === "http://auth0.com/oauth/grant-type/passwordless/otp") username = body.username;
|
|
121
|
+
else if (grant_type === "password") {
|
|
122
|
+
username = body.username;
|
|
123
|
+
password = body.password;
|
|
124
|
+
} else {
|
|
125
|
+
assert(typeof code !== "undefined", "400::no code in /oauth/token");
|
|
126
|
+
[nonce, username] = decode(code).split(":");
|
|
127
|
+
assert(!!username, `400::no nonce in store for ${code}`);
|
|
128
|
+
}
|
|
129
|
+
let user = personQuery((person) => {
|
|
130
|
+
assert(!!person.email, `500::no email defined on person scenario`);
|
|
131
|
+
let valid = person.email.toLowerCase() === username.toLowerCase();
|
|
132
|
+
if (typeof password === "undefined") return valid;
|
|
133
|
+
else return valid && password === person.password;
|
|
134
|
+
});
|
|
135
|
+
assert(!!user, "401::Unauthorized");
|
|
136
|
+
return {
|
|
137
|
+
user,
|
|
138
|
+
nonce
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
export { createTokens };
|
|
144
|
+
//# sourceMappingURL=oauth-handlers.mjs.map
|