@thunderid/express 0.0.4 → 0.1.0
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/README.md +1 -1
- package/dist/ThunderIDExpressClient.d.ts +11 -9
- package/dist/ThunderIDExpressClient.d.ts.map +1 -1
- package/dist/cjs/index.cjs +306 -172
- package/dist/{__legacy__/constants/logger-config.d.ts → constants/CookieConfig.d.ts} +11 -11
- package/dist/constants/CookieConfig.d.ts.map +1 -0
- package/dist/edge/index.js +300 -172
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +300 -172
- package/dist/middleware/authentication.d.ts +66 -0
- package/dist/middleware/authentication.d.ts.map +1 -0
- package/dist/middleware/flow.d.ts +50 -0
- package/dist/middleware/flow.d.ts.map +1 -0
- package/dist/{__legacy__/middleware/protect-route.d.ts → middleware/protect.d.ts} +12 -5
- package/dist/middleware/protect.d.ts.map +1 -0
- package/dist/models/config.d.ts +28 -9
- package/dist/models/config.d.ts.map +1 -1
- package/dist/{__legacy__/models/protect-route.d.ts → models/protectRoute.d.ts} +6 -3
- package/dist/models/protectRoute.d.ts.map +1 -0
- package/dist/{__legacy__/constants/index.d.ts → utils/expressUtils.d.ts} +9 -4
- package/dist/utils/expressUtils.d.ts.map +1 -0
- package/package.json +7 -5
- package/dist/__legacy__/client.d.ts +0 -46
- package/dist/__legacy__/client.d.ts.map +0 -1
- package/dist/__legacy__/constants/default-options.d.ts +0 -26
- package/dist/__legacy__/constants/default-options.d.ts.map +0 -1
- package/dist/__legacy__/constants/index.d.ts.map +0 -1
- package/dist/__legacy__/constants/logger-config.d.ts.map +0 -1
- package/dist/__legacy__/middleware/authentication.d.ts +0 -23
- package/dist/__legacy__/middleware/authentication.d.ts.map +0 -1
- package/dist/__legacy__/middleware/index.d.ts +0 -20
- package/dist/__legacy__/middleware/index.d.ts.map +0 -1
- package/dist/__legacy__/middleware/protect-route.d.ts.map +0 -1
- package/dist/__legacy__/models/client-config.d.ts +0 -33
- package/dist/__legacy__/models/client-config.d.ts.map +0 -1
- package/dist/__legacy__/models/data.d.ts +0 -21
- package/dist/__legacy__/models/data.d.ts.map +0 -1
- package/dist/__legacy__/models/index.d.ts +0 -21
- package/dist/__legacy__/models/index.d.ts.map +0 -1
- package/dist/__legacy__/models/protect-route.d.ts.map +0 -1
- package/dist/__legacy__/utils/express-utils.d.ts +0 -22
- package/dist/__legacy__/utils/express-utils.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
3
|
Express.js SDK for ThunderID. Provides authentication middleware for Express applications.
|
|
4
4
|
|
|
@@ -15,15 +15,17 @@
|
|
|
15
15
|
* specific language governing permissions and limitations
|
|
16
16
|
* under the License.
|
|
17
17
|
*/
|
|
18
|
-
import {
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
import { ThunderIDNodeClient, Storage, TokenResponse, User } from '@thunderid/node';
|
|
19
|
+
import express from 'express';
|
|
20
|
+
import { ExpressClientConfig } from './models/config';
|
|
21
|
+
declare class ThunderIDExpressClient<T extends ExpressClientConfig = ExpressClientConfig> extends ThunderIDNodeClient<T> {
|
|
22
|
+
private _expressConfig;
|
|
23
|
+
constructor();
|
|
24
|
+
initialize(config: T, storage?: Storage): Promise<boolean>;
|
|
25
|
+
get expressConfig(): ExpressClientConfig | undefined;
|
|
26
|
+
getUserFromRequest(req: express.Request): Promise<User | undefined>;
|
|
27
|
+
signIn(req: express.Request, res: express.Response, next: express.NextFunction, signInConfig?: Record<string, string | boolean>): Promise<TokenResponse>;
|
|
28
|
+
signOut(userId?: string): Promise<string>;
|
|
27
29
|
}
|
|
28
30
|
export default ThunderIDExpressClient;
|
|
29
31
|
//# sourceMappingURL=ThunderIDExpressClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThunderIDExpressClient.d.ts","sourceRoot":"","sources":["../src/ThunderIDExpressClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"ThunderIDExpressClient.d.ts","sourceRoot":"","sources":["../src/ThunderIDExpressClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAC,mBAAmB,EAA0B,OAAO,EAAE,aAAa,EAAE,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAC1G,OAAO,OAAO,MAAM,SAAS,CAAC;AAG9B,OAAO,EAAC,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AAGpD,cAAM,sBAAsB,CAAC,CAAC,SAAS,mBAAmB,GAAG,mBAAmB,CAAE,SAAQ,mBAAmB,CAAC,CAAC,CAAC;IAC9G,OAAO,CAAC,cAAc,CAAkC;;IAMlC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAKhF,IAAW,aAAa,IAAI,mBAAmB,GAAG,SAAS,CAE1D;IAEY,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAK1D,MAAM,CAC1B,GAAG,EAAE,OAAO,CAAC,OAAO,EACpB,GAAG,EAAE,OAAO,CAAC,QAAQ,EACrB,IAAI,EAAE,OAAO,CAAC,YAAY,EAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAC9C,OAAO,CAAC,aAAa,CAAC;IAuDH,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAGhE;AAED,eAAe,sBAAsB,CAAC"}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -25,12 +25,10 @@ let __thunderid_node = require("@thunderid/node");
|
|
|
25
25
|
__thunderid_node = __toESM(__thunderid_node);
|
|
26
26
|
let uuid = require("uuid");
|
|
27
27
|
uuid = __toESM(uuid);
|
|
28
|
-
let express = require("express");
|
|
29
|
-
express = __toESM(express);
|
|
30
28
|
|
|
31
|
-
//#region src/
|
|
29
|
+
//#region src/constants/CookieConfig.ts
|
|
32
30
|
/**
|
|
33
|
-
* Copyright (c)
|
|
31
|
+
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
|
|
34
32
|
*
|
|
35
33
|
* WSO2 LLC. licenses this file to you under the Apache License,
|
|
36
34
|
* Version 2.0 (the "License"); you may not use this file except
|
|
@@ -46,209 +44,345 @@ express = __toESM(express);
|
|
|
46
44
|
* specific language governing permissions and limitations
|
|
47
45
|
* under the License.
|
|
48
46
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
/** Session cookie name used across the Express SDK. */
|
|
48
|
+
const SESSION_COOKIE_NAME = "THUNDERID_SESSION_ID";
|
|
49
|
+
/** Default cookie configuration values. */
|
|
50
|
+
const CookieConfig = {
|
|
51
|
+
defaultExpirySeconds: 86400,
|
|
52
|
+
defaultHttpOnly: true,
|
|
53
|
+
defaultSameSite: "lax",
|
|
54
|
+
defaultSecure: false
|
|
55
|
+
};
|
|
56
|
+
var CookieConfig_default = CookieConfig;
|
|
58
57
|
|
|
59
58
|
//#endregion
|
|
60
|
-
//#region src/
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
59
|
+
//#region src/utils/expressUtils.ts
|
|
60
|
+
/**
|
|
61
|
+
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
|
|
62
|
+
*
|
|
63
|
+
* WSO2 LLC. licenses this file to you under the Apache License,
|
|
64
|
+
* Version 2.0 (the "License"); you may not use this file except
|
|
65
|
+
* in compliance with the License.
|
|
66
|
+
* You may obtain a copy of the License at
|
|
67
|
+
*
|
|
68
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
69
|
+
*
|
|
70
|
+
* Unless required by applicable law or agreed to in writing,
|
|
71
|
+
* software distributed under the License is distributed on an
|
|
72
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
73
|
+
* KIND, either express or implied. See the License for the
|
|
74
|
+
* specific language governing permissions and limitations
|
|
75
|
+
* under the License.
|
|
76
|
+
*/
|
|
77
|
+
const AUTH_ERROR_REGEXP = /[?&]error=[^&]+/;
|
|
78
|
+
/**
|
|
79
|
+
* Returns `true` if the given URL contains an OAuth error query parameter.
|
|
80
|
+
*
|
|
81
|
+
* @param url - The URL to inspect.
|
|
82
|
+
*/
|
|
83
|
+
const hasErrorInURL = (url) => AUTH_ERROR_REGEXP.test(url);
|
|
84
|
+
var expressUtils_default = hasErrorInURL;
|
|
85
|
+
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/ThunderIDExpressClient.ts
|
|
88
|
+
var ThunderIDExpressClient = class extends __thunderid_node.ThunderIDNodeClient {
|
|
89
|
+
_expressConfig;
|
|
90
|
+
constructor() {
|
|
91
|
+
super();
|
|
92
|
+
}
|
|
93
|
+
async initialize(config, storage) {
|
|
94
|
+
this._expressConfig = config;
|
|
95
|
+
return super.initialize(config, storage);
|
|
96
|
+
}
|
|
97
|
+
get expressConfig() {
|
|
98
|
+
return this._expressConfig;
|
|
99
|
+
}
|
|
100
|
+
async getUserFromRequest(req) {
|
|
101
|
+
const sessionId = req.cookies?.[SESSION_COOKIE_NAME];
|
|
102
|
+
return this.getUser(sessionId);
|
|
103
|
+
}
|
|
104
|
+
async signIn(req, res, next, signInConfig) {
|
|
105
|
+
if (expressUtils_default(req.originalUrl)) return Promise.reject(new __thunderid_node.ThunderIDAuthException("EXPRESS-CLIENT-SI-IV01", "Invalid login request URL", "Login request contains an error query parameter in the URL"));
|
|
106
|
+
let userId = req.cookies?.[SESSION_COOKIE_NAME];
|
|
107
|
+
if (!userId) userId = (0, uuid.v4)();
|
|
108
|
+
const sc = this._expressConfig?.sessionCookie;
|
|
109
|
+
const authRedirectCallback = (url) => {
|
|
110
|
+
if (!url) return;
|
|
111
|
+
res.cookie(SESSION_COOKIE_NAME, userId, {
|
|
112
|
+
httpOnly: sc?.httpOnly ?? CookieConfig_default.defaultHttpOnly,
|
|
113
|
+
maxAge: (sc?.expiryTime ?? CookieConfig_default.defaultExpirySeconds) * 1e3,
|
|
114
|
+
sameSite: sc?.sameSite ?? CookieConfig_default.defaultSameSite,
|
|
115
|
+
secure: sc?.secure ?? CookieConfig_default.defaultSecure
|
|
116
|
+
});
|
|
117
|
+
res.redirect(url);
|
|
118
|
+
if (typeof next === "function") next();
|
|
119
|
+
};
|
|
120
|
+
const authResponse = await super.signIn(authRedirectCallback, userId, req.query.code, req.query.session_state, req.query.state, signInConfig);
|
|
121
|
+
if (authResponse.accessToken || authResponse.idToken) return authResponse;
|
|
122
|
+
return {
|
|
123
|
+
accessToken: "",
|
|
124
|
+
createdAt: 0,
|
|
125
|
+
expiresIn: "",
|
|
126
|
+
idToken: "",
|
|
127
|
+
refreshToken: "",
|
|
128
|
+
scope: "",
|
|
129
|
+
tokenType: ""
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
async signOut(userId) {
|
|
133
|
+
return super.signOut(userId);
|
|
134
|
+
}
|
|
74
135
|
};
|
|
136
|
+
var ThunderIDExpressClient_default = ThunderIDExpressClient;
|
|
75
137
|
|
|
76
138
|
//#endregion
|
|
77
|
-
//#region src/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
139
|
+
//#region src/middleware/authentication.ts
|
|
140
|
+
/**
|
|
141
|
+
* Returns Express middleware that initialises the ThunderID client and attaches
|
|
142
|
+
* it to `req.thunderIDAuth` for use in route handlers and `protect()`.
|
|
143
|
+
*
|
|
144
|
+
* Unlike the old `thunderID()` router, this function does **not** mount any
|
|
145
|
+
* routes automatically. Register sign-in and sign-out handlers explicitly:
|
|
146
|
+
*
|
|
147
|
+
* ```ts
|
|
148
|
+
* app.use(thunderID(config));
|
|
149
|
+
* app.get('/login', handleSignIn());
|
|
150
|
+
* app.get('/logout', handleSignOut());
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* @param config - ThunderID Express configuration.
|
|
154
|
+
*/
|
|
155
|
+
const thunderID = (config) => {
|
|
156
|
+
const client = new ThunderIDExpressClient_default();
|
|
157
|
+
let initPromise;
|
|
158
|
+
const getInitPromise = (req) => {
|
|
159
|
+
if (initPromise === void 0) {
|
|
160
|
+
const origin = `${req.protocol}://${req.get("host")}`;
|
|
161
|
+
initPromise = client.initialize({
|
|
162
|
+
...config,
|
|
163
|
+
afterSignInUrl: config.afterSignInUrl ?? `${origin}/login`,
|
|
164
|
+
afterSignOutUrl: config.afterSignOutUrl ?? `${origin}/logout`
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return initPromise;
|
|
168
|
+
};
|
|
169
|
+
return async (req, res, next) => {
|
|
170
|
+
await getInitPromise(req);
|
|
171
|
+
req.thunderIDAuth = client;
|
|
172
|
+
res.thunderIDAuth = client;
|
|
83
173
|
next();
|
|
84
|
-
}
|
|
85
|
-
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Returns an Express route handler for the sign-in path.
|
|
178
|
+
*
|
|
179
|
+
* - If the request has no `?code` query param, initiates the OAuth 2.0 redirect.
|
|
180
|
+
* - If the request has `?code`, exchanges the authorization code for tokens,
|
|
181
|
+
* sets the session cookie, and calls `onSignIn`.
|
|
182
|
+
*
|
|
183
|
+
* Must be used after `thunderID()` middleware so that `req.thunderIDAuth` is set.
|
|
184
|
+
*
|
|
185
|
+
* ```ts
|
|
186
|
+
* app.get('/login', handleSignIn());
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
const handleSignIn = () => {
|
|
190
|
+
return async (req, res, next) => {
|
|
191
|
+
const client = req.thunderIDAuth;
|
|
192
|
+
if (!client) {
|
|
193
|
+
__thunderid_node.logger.error("thunderID() middleware must be mounted before handleSignIn()");
|
|
194
|
+
res.status(500).end();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const config = client.expressConfig;
|
|
198
|
+
const onSignIn = config?.onSignIn ?? ((r) => r.end());
|
|
199
|
+
const onError = config?.onError ?? ((r, e) => {
|
|
200
|
+
__thunderid_node.logger.error(e.message);
|
|
201
|
+
r.status(500).end();
|
|
202
|
+
});
|
|
86
203
|
try {
|
|
87
|
-
const response = await
|
|
204
|
+
const response = await client.signIn(req, res, next, config?.signInOptions);
|
|
88
205
|
if (response.accessToken || response.idToken) onSignIn(res, response);
|
|
89
206
|
} catch (e) {
|
|
90
|
-
__thunderid_node.
|
|
207
|
+
__thunderid_node.logger.error(e.message);
|
|
91
208
|
onError(res, e);
|
|
92
209
|
}
|
|
93
|
-
}
|
|
94
|
-
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Returns an Express route handler for the sign-out path.
|
|
214
|
+
*
|
|
215
|
+
* - Clears the session cookie and redirects to the identity provider's
|
|
216
|
+
* end-session endpoint.
|
|
217
|
+
* - When the identity provider redirects back with `?state=sign_out_success`,
|
|
218
|
+
* calls `onSignOut`.
|
|
219
|
+
*
|
|
220
|
+
* Must be used after `thunderID()` middleware so that `req.thunderIDAuth` is set.
|
|
221
|
+
*
|
|
222
|
+
* ```ts
|
|
223
|
+
* app.get('/logout', handleSignOut());
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
const handleSignOut = () => {
|
|
227
|
+
return async (req, res) => {
|
|
228
|
+
const client = req.thunderIDAuth;
|
|
229
|
+
if (!client) {
|
|
230
|
+
__thunderid_node.logger.error("thunderID() middleware must be mounted before handleSignOut()");
|
|
231
|
+
res.status(500).end();
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const config = client.expressConfig;
|
|
235
|
+
const onSignOut = config?.onSignOut ?? ((r) => r.end());
|
|
236
|
+
const onError = config?.onError ?? ((r, e) => {
|
|
237
|
+
__thunderid_node.logger.error(e.message);
|
|
238
|
+
r.status(500).end();
|
|
239
|
+
});
|
|
95
240
|
if (req.query.state === "sign_out_success") {
|
|
96
241
|
onSignOut(res);
|
|
97
242
|
return;
|
|
98
243
|
}
|
|
99
|
-
|
|
100
|
-
|
|
244
|
+
const sessionId = req.cookies?.[SESSION_COOKIE_NAME];
|
|
245
|
+
if (!sessionId) {
|
|
246
|
+
onError(res, new __thunderid_node.ThunderIDRuntimeError("No cookie found in the request", "EXPRESS-AUTH_MW-LOGOUT-NF01", "express"));
|
|
101
247
|
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
const signOutURL = await client.signOut(sessionId);
|
|
104
251
|
if (signOutURL) {
|
|
105
|
-
res.cookie(
|
|
252
|
+
res.cookie(SESSION_COOKIE_NAME, null, { maxAge: 0 });
|
|
106
253
|
res.redirect(signOutURL);
|
|
107
|
-
return;
|
|
108
254
|
}
|
|
109
255
|
} catch (e) {
|
|
110
256
|
onError(res, e);
|
|
111
|
-
return;
|
|
112
257
|
}
|
|
113
|
-
}
|
|
114
|
-
return router;
|
|
258
|
+
};
|
|
115
259
|
};
|
|
116
260
|
|
|
117
261
|
//#endregion
|
|
118
|
-
//#region src/
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
262
|
+
//#region src/middleware/protect.ts
|
|
263
|
+
/**
|
|
264
|
+
* Returns Express middleware that blocks unauthenticated requests.
|
|
265
|
+
* Requires `thunderID()` to be mounted before this middleware so that
|
|
266
|
+
* `req.thunderIDAuth` is populated.
|
|
267
|
+
*
|
|
268
|
+
* @param onUnauthenticated - Called when the session is missing or invalid.
|
|
269
|
+
* Defaults to sending a 401 response.
|
|
270
|
+
*/
|
|
271
|
+
const protect = (onUnauthenticated) => {
|
|
272
|
+
return async (req, res, next) => {
|
|
273
|
+
const client = req.thunderIDAuth;
|
|
274
|
+
const sessionId = req.cookies?.[SESSION_COOKIE_NAME];
|
|
275
|
+
const reject = () => {
|
|
276
|
+
if (onUnauthenticated) onUnauthenticated(res);
|
|
277
|
+
else res.status(401).end();
|
|
278
|
+
};
|
|
279
|
+
if (!client || !sessionId) {
|
|
280
|
+
__thunderid_node.logger.error("No session ID found in the request cookies");
|
|
281
|
+
reject();
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (await client.isSignedIn(sessionId)) return next();
|
|
285
|
+
__thunderid_node.logger.error("Invalid session ID found in the request cookies");
|
|
286
|
+
reject();
|
|
287
|
+
};
|
|
141
288
|
};
|
|
289
|
+
var protect_default = protect;
|
|
142
290
|
|
|
143
291
|
//#endregion
|
|
144
|
-
//#region src/
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
292
|
+
//#region src/middleware/flow.ts
|
|
293
|
+
/**
|
|
294
|
+
* Returns an Express route handler that drives the embedded sign-in flow loop.
|
|
295
|
+
*
|
|
296
|
+
* Requires `thunderID()` middleware with `mode: 'embedded'` to be mounted first.
|
|
297
|
+
* On each POST, the handler advances the flow one step and returns JSON.
|
|
298
|
+
*
|
|
299
|
+
* **First call** — no `executionId`:
|
|
300
|
+
* ```json
|
|
301
|
+
* { "applicationId": "app-id", "flowType": "SIGN_IN" }
|
|
302
|
+
* ```
|
|
303
|
+
* Response includes `executionId`, `challengeToken`, `authId`, and `components`
|
|
304
|
+
* (the UI elements to render).
|
|
305
|
+
*
|
|
306
|
+
* **Subsequent calls** — continue the flow:
|
|
307
|
+
* ```json
|
|
308
|
+
* { "executionId": "...", "challengeToken": "...", "authId": "...", "inputs": { ... } }
|
|
309
|
+
* ```
|
|
310
|
+
*
|
|
311
|
+
* **On completion** — flow returns `{ "done": true, "redirectUrl": "/login?code=..." }`.
|
|
312
|
+
* The client navigates to `redirectUrl`, which is handled by `handleSignIn()` to
|
|
313
|
+
* exchange the code and set the session cookie.
|
|
314
|
+
*
|
|
315
|
+
* ```ts
|
|
316
|
+
* app.use(thunderID({ ..., mode: 'embedded' }));
|
|
317
|
+
* app.get('/login', handleSignIn());
|
|
318
|
+
* app.post('/flow/sign-in', handleFlow());
|
|
319
|
+
* app.get('/logout', handleSignOut());
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
322
|
+
const handleFlow = () => {
|
|
323
|
+
return async (req, res) => {
|
|
324
|
+
const client = req.thunderIDAuth;
|
|
325
|
+
if (!client) {
|
|
326
|
+
__thunderid_node.logger.error("thunderID() middleware must be mounted before handleFlow()");
|
|
327
|
+
res.status(500).json({ error: "SDK not initialised" });
|
|
328
|
+
return;
|
|
160
329
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (!ThunderIDExpressClient._instance && config) {
|
|
166
|
-
ThunderIDExpressClient._instance = new ThunderIDExpressClient(config, storage);
|
|
167
|
-
__thunderid_node.Logger.debug("Initialized ThunderIDExpressClient successfully");
|
|
330
|
+
const baseUrl = client.expressConfig?.baseUrl;
|
|
331
|
+
if (!baseUrl) {
|
|
332
|
+
res.status(500).json({ error: "baseUrl is not configured" });
|
|
333
|
+
return;
|
|
168
334
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
335
|
+
const { applicationId, flowType, executionId, challengeToken, authId, inputs } = req.body ?? {};
|
|
336
|
+
try {
|
|
337
|
+
let resolvedAuthId = authId;
|
|
338
|
+
if (!executionId && !resolvedAuthId) {
|
|
339
|
+
const authUrl = await client.getSignInUrl();
|
|
340
|
+
resolvedAuthId = new URL(authUrl).searchParams.get("authId") ?? void 0;
|
|
341
|
+
}
|
|
342
|
+
const flowResponse = await (0, __thunderid_node.executeEmbeddedSignInFlowV2)({
|
|
343
|
+
authId: resolvedAuthId,
|
|
344
|
+
baseUrl,
|
|
345
|
+
payload: executionId ? {
|
|
346
|
+
action: "submit",
|
|
347
|
+
challengeToken,
|
|
348
|
+
executionId,
|
|
349
|
+
inputs
|
|
350
|
+
} : {
|
|
351
|
+
applicationId,
|
|
352
|
+
flowType: flowType ?? "SIGN_IN"
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
if (flowResponse.redirectUrl) {
|
|
356
|
+
res.json({
|
|
357
|
+
done: true,
|
|
358
|
+
redirectUrl: flowResponse.redirectUrl
|
|
184
359
|
});
|
|
185
|
-
|
|
186
|
-
next && typeof next === "function" && next();
|
|
360
|
+
return;
|
|
187
361
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
async signOut(userId) {
|
|
202
|
-
return this._authClient.signOut(userId);
|
|
203
|
-
}
|
|
204
|
-
async isSignedIn(userId) {
|
|
205
|
-
return this._authClient.isSignedIn(userId);
|
|
206
|
-
}
|
|
207
|
-
async getIdToken(userId) {
|
|
208
|
-
return this._authClient.getIdToken(userId);
|
|
209
|
-
}
|
|
210
|
-
async getUser(userId) {
|
|
211
|
-
return this._authClient.getUser(userId);
|
|
212
|
-
}
|
|
213
|
-
async getOpenIDProviderEndpoints() {
|
|
214
|
-
return this._authClient.getOpenIDProviderEndpoints();
|
|
215
|
-
}
|
|
216
|
-
async getDecodedIdToken(userId) {
|
|
217
|
-
return this._authClient.getDecodedIdToken(userId);
|
|
218
|
-
}
|
|
219
|
-
async getAccessToken(userId) {
|
|
220
|
-
return this._authClient.getAccessToken(userId);
|
|
221
|
-
}
|
|
222
|
-
async exchangeToken(config, userId) {
|
|
223
|
-
return this._authClient.exchangeToken(config, userId);
|
|
224
|
-
}
|
|
225
|
-
async reInitialize(config) {
|
|
226
|
-
return this._authClient.reInitialize(config);
|
|
227
|
-
}
|
|
228
|
-
async revokeAccessToken(userId) {
|
|
229
|
-
return this._authClient.revokeAccessToken(userId);
|
|
230
|
-
}
|
|
231
|
-
static didSignOutFail(afterSignOutUrl) {
|
|
232
|
-
return __thunderid_node.LegacyThunderIDNodeClient.didSignOutFail(afterSignOutUrl);
|
|
233
|
-
}
|
|
234
|
-
static isSignOutSuccessful(afterSignOutUrl) {
|
|
235
|
-
return __thunderid_node.LegacyThunderIDNodeClient.isSignOutSuccessful(afterSignOutUrl);
|
|
236
|
-
}
|
|
237
|
-
static protectRoute(callback) {
|
|
238
|
-
if (!this._instance) throw new __thunderid_node.ThunderIDAuthException("EXPRESS-CLIENT-PR-NF01", "ThunderIDExpressClient is not instantiated", "Create an instance of ThunderIDExpressClient before using calling this method.");
|
|
239
|
-
return protectRoute(this._instance, callback);
|
|
240
|
-
}
|
|
241
|
-
static thunderIDExpressAuth(onSignIn, onSignOut, onError) {
|
|
242
|
-
if (!this._instance) throw new __thunderid_node.ThunderIDAuthException("EXPRESS-CLIENT-AEA-NF01", "ThunderIDExpressClient is not instantiated", "Create an instance of ThunderIDExpressClient before using calling this method.");
|
|
243
|
-
return thunderIDExpressAuth(this._instance, ThunderIDExpressClient._clientConfig, onSignIn, onSignOut, onError);
|
|
244
|
-
}
|
|
245
|
-
async getStorageManager() {
|
|
246
|
-
return this._authClient.getStorageManager();
|
|
247
|
-
}
|
|
362
|
+
res.json({
|
|
363
|
+
authId: resolvedAuthId,
|
|
364
|
+
challengeToken: flowResponse.challengeToken,
|
|
365
|
+
components: flowResponse.data?.meta?.components ?? [],
|
|
366
|
+
executionId: flowResponse.executionId,
|
|
367
|
+
flowStatus: flowResponse.flowStatus
|
|
368
|
+
});
|
|
369
|
+
} catch (e) {
|
|
370
|
+
__thunderid_node.logger.error(e.message);
|
|
371
|
+
res.status(500).json({ error: e.message ?? "Flow execution failed" });
|
|
372
|
+
}
|
|
373
|
+
};
|
|
248
374
|
};
|
|
375
|
+
var flow_default = handleFlow;
|
|
249
376
|
|
|
250
377
|
//#endregion
|
|
251
|
-
exports.
|
|
378
|
+
exports.CookieConfig = CookieConfig_default;
|
|
379
|
+
exports.SESSION_COOKIE_NAME = SESSION_COOKIE_NAME;
|
|
380
|
+
exports.ThunderIDExpressClient = ThunderIDExpressClient_default;
|
|
381
|
+
exports.handleFlow = flow_default;
|
|
382
|
+
exports.handleSignIn = handleSignIn;
|
|
383
|
+
exports.handleSignOut = handleSignOut;
|
|
384
|
+
exports.protect = protect_default;
|
|
385
|
+
exports.thunderID = thunderID;
|
|
252
386
|
Object.keys(__thunderid_node).forEach(function (k) {
|
|
253
387
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
254
388
|
enumerable: true,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
|
|
3
3
|
*
|
|
4
4
|
* WSO2 LLC. licenses this file to you under the Apache License,
|
|
5
5
|
* Version 2.0 (the "License"); you may not use this file except
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
* specific language governing permissions and limitations
|
|
16
16
|
* under the License.
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
reset: string;
|
|
18
|
+
/** Session cookie name used across the Express SDK. */
|
|
19
|
+
export declare const SESSION_COOKIE_NAME = "THUNDERID_SESSION_ID";
|
|
20
|
+
/** Default cookie configuration values. */
|
|
21
|
+
declare const CookieConfig: {
|
|
22
|
+
defaultExpirySeconds: number;
|
|
23
|
+
defaultHttpOnly: boolean;
|
|
24
|
+
defaultSameSite: "lax";
|
|
25
|
+
defaultSecure: boolean;
|
|
27
26
|
};
|
|
28
|
-
|
|
27
|
+
export default CookieConfig;
|
|
28
|
+
//# sourceMappingURL=CookieConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CookieConfig.d.ts","sourceRoot":"","sources":["../../src/constants/CookieConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,uDAAuD;AACvD,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,2CAA2C;AAC3C,QAAA,MAAM,YAAY;;;;;CAKjB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|