@civic/auth 0.1.6-beta.0 → 0.1.6-beta.2
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/CHANGELOG.md +2 -0
- package/dist/cjs/lib/cookies.d.ts +12 -1
- package/dist/cjs/lib/cookies.d.ts.map +1 -1
- package/dist/cjs/lib/cookies.js +28 -1
- package/dist/cjs/lib/cookies.js.map +1 -1
- package/dist/cjs/nextjs/NextClientAuthenticationRefresher.d.ts +9 -0
- package/dist/cjs/nextjs/NextClientAuthenticationRefresher.d.ts.map +1 -0
- package/dist/cjs/nextjs/NextClientAuthenticationRefresher.js +27 -0
- package/dist/cjs/nextjs/NextClientAuthenticationRefresher.js.map +1 -0
- package/dist/cjs/nextjs/config.d.ts +1 -0
- package/dist/cjs/nextjs/config.d.ts.map +1 -1
- package/dist/cjs/nextjs/config.js +4 -3
- package/dist/cjs/nextjs/config.js.map +1 -1
- package/dist/cjs/nextjs/hooks/useRefresh.d.ts +4 -0
- package/dist/cjs/nextjs/hooks/useRefresh.d.ts.map +1 -0
- package/dist/cjs/nextjs/hooks/useRefresh.js +45 -0
- package/dist/cjs/nextjs/hooks/useRefresh.js.map +1 -0
- package/dist/cjs/nextjs/hooks/useUserCookie.d.ts.map +1 -1
- package/dist/cjs/nextjs/hooks/useUserCookie.js +10 -9
- package/dist/cjs/nextjs/hooks/useUserCookie.js.map +1 -1
- package/dist/cjs/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
- package/dist/cjs/nextjs/providers/NextAuthProvider.js +5 -3
- package/dist/cjs/nextjs/providers/NextAuthProvider.js.map +1 -1
- package/dist/cjs/nextjs/routeHandler.d.ts +2 -2
- package/dist/cjs/nextjs/routeHandler.d.ts.map +1 -1
- package/dist/cjs/nextjs/routeHandler.js +35 -25
- package/dist/cjs/nextjs/routeHandler.js.map +1 -1
- package/dist/cjs/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -1
- package/dist/cjs/reactjs/providers/ClientTokenExchangeSessionProvider.js +7 -24
- package/dist/cjs/reactjs/providers/ClientTokenExchangeSessionProvider.js.map +1 -1
- package/dist/cjs/server/config.d.ts +1 -0
- package/dist/cjs/server/config.d.ts.map +1 -1
- package/dist/cjs/server/config.js.map +1 -1
- package/dist/cjs/server/refresh.d.ts.map +1 -1
- package/dist/cjs/server/refresh.js +2 -2
- package/dist/cjs/server/refresh.js.map +1 -1
- package/dist/cjs/services/AuthenticationService.d.ts +17 -22
- package/dist/cjs/services/AuthenticationService.d.ts.map +1 -1
- package/dist/cjs/services/AuthenticationService.js.map +1 -1
- package/dist/cjs/shared/hooks/useRefresh.d.ts.map +1 -1
- package/dist/cjs/shared/hooks/useRefresh.js +3 -3
- package/dist/cjs/shared/hooks/useRefresh.js.map +1 -1
- package/dist/cjs/shared/lib/AuthenticationRefresherImpl.d.ts +13 -0
- package/dist/cjs/shared/lib/AuthenticationRefresherImpl.d.ts.map +1 -0
- package/dist/cjs/shared/lib/AuthenticationRefresherImpl.js +44 -0
- package/dist/cjs/shared/lib/AuthenticationRefresherImpl.js.map +1 -0
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.d.ts +7 -11
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.d.ts.map +1 -1
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.js +15 -31
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.js.map +1 -1
- package/dist/cjs/shared/lib/storage.d.ts +8 -0
- package/dist/cjs/shared/lib/storage.d.ts.map +1 -1
- package/dist/cjs/shared/lib/storage.js.map +1 -1
- package/dist/cjs/shared/lib/types.d.ts +1 -0
- package/dist/cjs/shared/lib/types.d.ts.map +1 -1
- package/dist/cjs/shared/lib/types.js.map +1 -1
- package/dist/cjs/shared/providers/CivicAuthConfigContext.d.ts +2 -1
- package/dist/cjs/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
- package/dist/cjs/shared/providers/CivicAuthConfigContext.js +3 -1
- package/dist/cjs/shared/providers/CivicAuthConfigContext.js.map +1 -1
- package/dist/cjs/shared/version.d.ts +1 -1
- package/dist/cjs/shared/version.js +1 -1
- package/dist/cjs/shared/version.js.map +1 -1
- package/dist/esm/lib/cookies.d.ts +12 -1
- package/dist/esm/lib/cookies.d.ts.map +1 -1
- package/dist/esm/lib/cookies.js +27 -1
- package/dist/esm/lib/cookies.js.map +1 -1
- package/dist/esm/nextjs/NextClientAuthenticationRefresher.d.ts +9 -0
- package/dist/esm/nextjs/NextClientAuthenticationRefresher.d.ts.map +1 -0
- package/dist/esm/nextjs/NextClientAuthenticationRefresher.js +23 -0
- package/dist/esm/nextjs/NextClientAuthenticationRefresher.js.map +1 -0
- package/dist/esm/nextjs/config.d.ts +1 -0
- package/dist/esm/nextjs/config.d.ts.map +1 -1
- package/dist/esm/nextjs/config.js +4 -3
- package/dist/esm/nextjs/config.js.map +1 -1
- package/dist/esm/nextjs/hooks/useRefresh.d.ts +4 -0
- package/dist/esm/nextjs/hooks/useRefresh.d.ts.map +1 -0
- package/dist/esm/nextjs/hooks/useRefresh.js +42 -0
- package/dist/esm/nextjs/hooks/useRefresh.js.map +1 -0
- package/dist/esm/nextjs/hooks/useUserCookie.d.ts.map +1 -1
- package/dist/esm/nextjs/hooks/useUserCookie.js +10 -9
- package/dist/esm/nextjs/hooks/useUserCookie.js.map +1 -1
- package/dist/esm/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
- package/dist/esm/nextjs/providers/NextAuthProvider.js +5 -3
- package/dist/esm/nextjs/providers/NextAuthProvider.js.map +1 -1
- package/dist/esm/nextjs/routeHandler.d.ts +2 -2
- package/dist/esm/nextjs/routeHandler.d.ts.map +1 -1
- package/dist/esm/nextjs/routeHandler.js +35 -25
- package/dist/esm/nextjs/routeHandler.js.map +1 -1
- package/dist/esm/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -1
- package/dist/esm/reactjs/providers/ClientTokenExchangeSessionProvider.js +5 -22
- package/dist/esm/reactjs/providers/ClientTokenExchangeSessionProvider.js.map +1 -1
- package/dist/esm/server/config.d.ts +1 -0
- package/dist/esm/server/config.d.ts.map +1 -1
- package/dist/esm/server/config.js.map +1 -1
- package/dist/esm/server/refresh.d.ts.map +1 -1
- package/dist/esm/server/refresh.js +2 -2
- package/dist/esm/server/refresh.js.map +1 -1
- package/dist/esm/services/AuthenticationService.d.ts +17 -22
- package/dist/esm/services/AuthenticationService.d.ts.map +1 -1
- package/dist/esm/services/AuthenticationService.js.map +1 -1
- package/dist/esm/shared/hooks/useRefresh.d.ts.map +1 -1
- package/dist/esm/shared/hooks/useRefresh.js +3 -3
- package/dist/esm/shared/hooks/useRefresh.js.map +1 -1
- package/dist/esm/shared/lib/AuthenticationRefresherImpl.d.ts +13 -0
- package/dist/esm/shared/lib/AuthenticationRefresherImpl.d.ts.map +1 -0
- package/dist/esm/shared/lib/AuthenticationRefresherImpl.js +40 -0
- package/dist/esm/shared/lib/AuthenticationRefresherImpl.js.map +1 -0
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.d.ts +7 -11
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.d.ts.map +1 -1
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.js +15 -31
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.js.map +1 -1
- package/dist/esm/shared/lib/storage.d.ts +8 -0
- package/dist/esm/shared/lib/storage.d.ts.map +1 -1
- package/dist/esm/shared/lib/storage.js.map +1 -1
- package/dist/esm/shared/lib/types.d.ts +1 -0
- package/dist/esm/shared/lib/types.d.ts.map +1 -1
- package/dist/esm/shared/lib/types.js.map +1 -1
- package/dist/esm/shared/providers/CivicAuthConfigContext.d.ts +2 -1
- package/dist/esm/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
- package/dist/esm/shared/providers/CivicAuthConfigContext.js +3 -1
- package/dist/esm/shared/providers/CivicAuthConfigContext.js.map +1 -1
- package/dist/esm/shared/version.d.ts +1 -1
- package/dist/esm/shared/version.js +1 -1
- package/dist/esm/shared/version.js.map +1 -1
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +8 -7
|
@@ -3,21 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.handler = void 0;
|
|
4
4
|
exports.handleLogout = handleLogout;
|
|
5
5
|
exports.handleLogoutCallback = handleLogoutCallback;
|
|
6
|
-
const
|
|
7
|
-
const cache_js_1 = require("next/cache.js");
|
|
8
|
-
const config_js_1 = require("../nextjs/config.js");
|
|
6
|
+
const constants_js_1 = require("../constants.js");
|
|
9
7
|
const logger_js_1 = require("../lib/logger.js");
|
|
8
|
+
const oauth_js_1 = require("../lib/oauth.js");
|
|
9
|
+
const config_js_1 = require("../nextjs/config.js");
|
|
10
10
|
const cookies_js_1 = require("../nextjs/cookies.js");
|
|
11
|
-
const PKCE_js_1 = require("../services/PKCE.js");
|
|
12
|
-
const login_js_1 = require("../server/login.js");
|
|
13
11
|
const GetUser_js_1 = require("../nextjs/GetUser.js");
|
|
14
12
|
const utils_js_1 = require("../nextjs/utils.js");
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
13
|
+
const login_js_1 = require("../server/login.js");
|
|
14
|
+
const PKCE_js_1 = require("../services/PKCE.js");
|
|
15
|
+
const AuthenticationRefresherImpl_js_1 = require("../shared/lib/AuthenticationRefresherImpl.js");
|
|
18
16
|
const types_js_1 = require("../shared/lib/types.js");
|
|
17
|
+
const UserSession_js_1 = require("../shared/lib/UserSession.js");
|
|
19
18
|
const util_js_1 = require("../shared/lib/util.js");
|
|
20
|
-
const
|
|
19
|
+
const cache_js_1 = require("next/cache.js");
|
|
20
|
+
const server_js_1 = require("next/server.js");
|
|
21
21
|
const logger = logger_js_1.loggers.nextjs.handlers.auth;
|
|
22
22
|
class AuthError extends Error {
|
|
23
23
|
status;
|
|
@@ -70,6 +70,21 @@ async function performTokenExchangeAndSetCookies(request, config, code, state, a
|
|
|
70
70
|
const userSession = new UserSession_js_1.GenericUserSession(clientStorage);
|
|
71
71
|
userSession.set(user);
|
|
72
72
|
}
|
|
73
|
+
async function handleRefresh(request, config) {
|
|
74
|
+
const resolvedConfigs = (0, config_js_1.resolveAuthConfig)(config);
|
|
75
|
+
const cookieStorage = new cookies_js_1.NextjsCookieStorage(config.cookies?.tokens ?? {});
|
|
76
|
+
const refresher = await AuthenticationRefresherImpl_js_1.AuthenticationRefresherImpl.build({
|
|
77
|
+
clientId: resolvedConfigs.clientId,
|
|
78
|
+
oauthServer: resolvedConfigs.oauthServer,
|
|
79
|
+
redirectUrl: resolvedConfigs.callbackUrl,
|
|
80
|
+
refreshUrl: resolvedConfigs.refreshUrl,
|
|
81
|
+
}, cookieStorage);
|
|
82
|
+
const tokens = await refresher.refreshAccessToken();
|
|
83
|
+
// this will use the refresh token to get new tokens and, if successful
|
|
84
|
+
// the idToken, accessToken and user cookies will be updated
|
|
85
|
+
// await newRefresher.refreshTokens();
|
|
86
|
+
return server_js_1.NextResponse.json({ status: "success", tokens });
|
|
87
|
+
}
|
|
73
88
|
const generateHtmlResponseWithCallback = (request, callbackUrl) => {
|
|
74
89
|
// we need to replace the URL with resolved config in case the server is hosted
|
|
75
90
|
// behind a reverse proxy or load balancer
|
|
@@ -213,25 +228,26 @@ async function handleLogout(request, config) {
|
|
|
213
228
|
redirectUrl: postLogoutUrl.href,
|
|
214
229
|
oauthServer: resolvedConfigs.oauthServer,
|
|
215
230
|
});
|
|
216
|
-
|
|
217
|
-
return logoutUrl.href;
|
|
231
|
+
return server_js_1.NextResponse.redirect(`${logoutUrl.href}`);
|
|
218
232
|
}
|
|
219
233
|
async function handleLogoutCallback(request, config) {
|
|
220
234
|
const resolvedConfigs = (0, config_js_1.resolveAuthConfig)(config);
|
|
221
235
|
const state = request.nextUrl.searchParams.get("state") || "";
|
|
222
236
|
if (!state)
|
|
223
237
|
throw new AuthError("Bad parameters", 400);
|
|
224
|
-
const displayMode = (0, oauth_js_1.displayModeFromState)(state, "
|
|
238
|
+
const displayMode = (0, oauth_js_1.displayModeFromState)(state, "iframe");
|
|
225
239
|
console.log("handleLogout: clear auth cookies", { state, displayMode });
|
|
226
|
-
|
|
240
|
+
const canAccessCookies = !!(await getIdToken(resolvedConfigs));
|
|
241
|
+
if (canAccessCookies) {
|
|
242
|
+
await (0, cookies_js_1.clearAuthCookies)(resolvedConfigs);
|
|
243
|
+
}
|
|
227
244
|
let response;
|
|
228
245
|
// handle logout for iframe display mode
|
|
229
246
|
if (displayMode === "iframe") {
|
|
230
247
|
// try to read the token from cookies. If cookies cant be read/written
|
|
231
248
|
// because the request cames from a cross-origin redirect,
|
|
232
249
|
// we need to show a page that will trigger the logout from the same domain
|
|
233
|
-
|
|
234
|
-
if (canReadCookies || request.url.includes("sameDomainCallback=true")) {
|
|
250
|
+
if (canAccessCookies || request.url.includes("sameDomainCallback=true")) {
|
|
235
251
|
// just return success
|
|
236
252
|
return server_js_1.NextResponse.json({ status: "success" });
|
|
237
253
|
}
|
|
@@ -242,7 +258,7 @@ async function handleLogoutCallback(request, config) {
|
|
|
242
258
|
}
|
|
243
259
|
// handle logout for non-iframe display mode
|
|
244
260
|
const redirectUrl = getPostLogoutRedirectUrl(request, resolvedConfigs);
|
|
245
|
-
if (redirectUrl) {
|
|
261
|
+
if (redirectUrl && canAccessCookies) {
|
|
246
262
|
console.log("handleLogout with redirect mode", { state, redirectUrl });
|
|
247
263
|
// this is comming from the fetch from the HTML page returned by this handler
|
|
248
264
|
if (request.url.includes("sameDomainCallback=true")) {
|
|
@@ -277,7 +293,6 @@ async function handleLogoutCallback(request, config) {
|
|
|
277
293
|
*/
|
|
278
294
|
const handler = (authConfig = {}) => async (request) => {
|
|
279
295
|
const config = (0, config_js_1.resolveAuthConfig)(authConfig);
|
|
280
|
-
let redirectUrl = null;
|
|
281
296
|
try {
|
|
282
297
|
const pathname = request.nextUrl.pathname;
|
|
283
298
|
const pathSegments = pathname.split("/");
|
|
@@ -287,9 +302,10 @@ const handler = (authConfig = {}) => async (request) => {
|
|
|
287
302
|
return await handleChallenge(request, config);
|
|
288
303
|
case "callback":
|
|
289
304
|
return await handleCallback(request, config);
|
|
305
|
+
case "refresh":
|
|
306
|
+
return await handleRefresh(request, config);
|
|
290
307
|
case "logout":
|
|
291
|
-
|
|
292
|
-
break;
|
|
308
|
+
return await handleLogout(request, config);
|
|
293
309
|
case "logoutcallback":
|
|
294
310
|
return await handleLogoutCallback(request, config);
|
|
295
311
|
default:
|
|
@@ -304,12 +320,6 @@ const handler = (authConfig = {}) => async (request) => {
|
|
|
304
320
|
(0, cookies_js_1.clearAuthCookies)(config);
|
|
305
321
|
return response;
|
|
306
322
|
}
|
|
307
|
-
// redirect on Nextjs must be called outside a try-catch block
|
|
308
|
-
// see https://nextjs.org/docs/app/api-reference/functions/redirect
|
|
309
|
-
if (redirectUrl)
|
|
310
|
-
(0, navigation_js_1.redirect)(redirectUrl);
|
|
311
|
-
// do nothing if no redirectUrl
|
|
312
|
-
return server_js_1.NextResponse.json({ status: "ok" });
|
|
313
323
|
};
|
|
314
324
|
exports.handler = handler;
|
|
315
325
|
//# sourceMappingURL=routeHandler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routeHandler.js","sourceRoot":"","sources":["../../../src/nextjs/routeHandler.ts"],"names":[],"mappings":";;;AAsRA,oCA6BC;AAED,oDAkEC;AAtXD,8CAA8C;AAC9C,4CAA+C;AAE/C,kDAAuD;AACvD,+CAA0C;AAC1C,oDAI6B;AAC7B,gDAAqE;AACrE,gDAA2D;AAC3D,oDAA8C;AAC9C,gDAAuD;AACvD,gEAAiE;AACjE,iDAGwB;AACxB,6CAGwB;AACxB,oDAAkE;AAClE,kDAA8D;AAC9D,sDAA8C;AAE9C,MAAM,MAAM,GAAG,mBAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;AAE5C,MAAM,SAAU,SAAQ,KAAK;IAGT;IAFlB,YACE,OAAe,EACC,SAAiB,GAAG;QAEpC,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,WAAM,GAAN,MAAM,CAAc;QAGpC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,SAAS,GAAG,CAAC,OAAoB,EAAiB,EAAE,CACxD,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAY,CAAC,OAAO,CAAC,EAAE,KAAK;IAChD,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAE7C,MAAM,UAAU,GAAG,KAAK,EAAE,MAAkB,EAA0B,EAAE;IACtE,MAAM,aAAa,GAAG,IAAI,gCAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;IAC5E,OAAO,aAAa,CAAC,GAAG,CAAC,sBAAW,CAAC,QAAQ,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAC5B,OAAoB,EACpB,MAAkB;IAElB,MAAM,aAAa,GAAG,IAAI,gCAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;IAC5E,MAAM,YAAY,GAAG,IAAI,yCAA+B,CAAC,aAAa,CAAC,CAAC;IAExE,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,gBAAgB,EAAE,CAAC;IACxD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1D,IAAI,MAAM,EAAE,CAAC;QACX,aAAa,CAAC,GAAG,CAAC,uBAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,wBAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,KAAK,UAAU,iCAAiC,CAC9C,OAAoB,EACpB,MAAkB,EAClB,IAAY,EACZ,KAAa,EACb,MAAc;IAEd,MAAM,eAAe,GAAG,IAAA,6BAAiB,EAAC,MAAM,CAAC,CAAC;IAClD,MAAM,aAAa,GAAG,IAAI,gCAAmB,CAAC,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE9E,MAAM,WAAW,GAAG,IAAA,6BAAkB,EAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAChE,IAAI,CAAC;QACH,MAAM,IAAA,iCAAsB,EAAC,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE;YACvD,GAAG,eAAe;YAClB,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;QAC9C,MAAM,IAAI,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,IAAA,oBAAO,GAAE,CAAC;IAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,SAAS,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,gCAAmB,EAAE,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,mCAAkB,CAAC,aAAa,CAAC,CAAC;IAC1D,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,gCAAgC,GAAG,CACvC,OAAoB,EACpB,WAAmB,EACnB,EAAE;IACF,+EAA+E;IAC/E,0CAA0C;IAC1C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,GAAG,WAAW,IAAI,UAAU,CAAC,YAAY,CAAC,QAAQ,EAAE,0BAA0B,CAAC;IAChG,OAAO,IAAI,wBAAY,CACrB;;;;;;kCAM8B,QAAQ;;;;;;;;;;;;KAYrC,CACF,CAAC;AACJ,CAAC,CAAC;AAEF,KAAK,UAAU,cAAc,CAC3B,OAAoB,EACpB,MAAkB;IAElB,MAAM,eAAe,GAAG,IAAA,6BAAiB,EAAC,MAAM,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACxD,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,SAAS,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAEhE,qEAAqE;IACrE,mGAAmG;IACnG,+FAA+F;IAC/F,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAElC,gFAAgF;IAChF,wCAAwC;IACxC,yHAAyH;IACzH,wHAAwH;IACxH,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE;QAC5B,IAAI;QACJ,KAAK;QACL,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAY,CAAC,WAAW,CAAC,CAAC;IAEnE,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,uCAAuC,EAAE;YACnD,KAAK;YACL,mBAAmB,EAAE,IAAA,uCAA4B,EAAC,GAAG,KAAK,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,IAAI,QAAQ,GAAG,IAAI,wBAAY,CAC7B,0CAA0C,0CAA2B,uBAAuB,CAC7F,CAAC;QAEF,mGAAmG;QACnG,uEAAuE;QACvE,wGAAwG;QACxG,sCAAsC;QACtC,IAAI,KAAK,IAAI,IAAA,uCAA4B,EAAC,KAAK,CAAC,EAAE,CAAC;YACjD,OAAO,CAAC,GAAG,CACT,yEAAyE,EACzE;gBACE,UAAU,EAAE,OAAO,CAAC,GAAG;gBACvB,iBAAiB,EAAE,eAAe,CAAC,WAAW;aAC/C,CACF,CAAC;YACF,yEAAyE;YACzE,sDAAsD;YACtD,QAAQ,GAAG,gCAAgC,CACzC,OAAO,EACP,eAAe,CAAC,WAAW,CAC5B,CAAC;QACJ,CAAC;QAED,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CACT,oDAAoD,0CAA2B,EAAE,CAClF,CAAC;QACF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,iCAAiC,CACrC,OAAO,EACP,eAAe,EACf,IAAI,EACJ,KAAK,EACL,MAAM,CACP,CAAC;IAEF,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC;QACpD,OAAO,CAAC,GAAG,CACT,mEAAmE,EACnE,MAAM,CACP,CAAC;QACF,OAAO,wBAAY,CAAC,IAAI,CAAC;YACvB,MAAM,EAAE,SAAS;YACjB,WAAW,EAAE,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;IAED,0DAA0D;IAC1D,IAAI,IAAA,uCAA4B,EAAC,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CACT,iEAAiE,EACjE,MAAM,CACP,CAAC;QACF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,wBAAY,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,wEAAwE;IACxE,iEAAiE;IACjE,oDAAoD;IACpD,MAAM,QAAQ,GAAG,IAAI,wBAAY,CAC/B,oCAAoC,0CAA2B,gBAAgB,CAChF,CAAC;IACF,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;IACjE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,uBAAuB,GAAG,CAC9B,YAAoB,EACpB,eAAuB,EACvB,EAAE,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC;AAEjD,MAAM,wBAAwB,GAAG,CAC/B,OAAoB,EACpB,MAAkB,EACH,EAAE;IACjB,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAA,6BAAiB,EAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,cAAc,GAAG,QAAQ,IAAI,GAAG,CAAC;IAEvC,kEAAkE;IAClE,gCAAgC;IAChC,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1E,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,iFAAiF;IACjF,gFAAgF;IAChF,+EAA+E;IAC/E,+DAA+D;IAC/D,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,MAAM;QAAE,OAAO,uBAAuB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAEnE,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,EAAE,GAAW,EAAE,EAAE;IAC9C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACnC,IAAA,yBAAc,EAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;IAChE,CAAC;AACH,CAAC,CAAC;AAEK,KAAK,UAAU,YAAY,CAChC,OAAoB,EACpB,MAAkB;IAElB,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACtE,MAAM,eAAe,GAAG,IAAA,6BAAiB,EAAC,MAAM,CAAC,CAAC;IAElD,qCAAqC;IACrC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,eAAe,CAAC,CAAC;IAElD,2CAA2C;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAExD,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,SAAS,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAEnE,MAAM,aAAa,GAAG,IAAI,GAAG,CAC3B,eAAe,CAAC,iBAAiB,EACjC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,CAClC,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,IAAA,gCAAsB,EAAC;QAC7C,QAAQ,EAAE,eAAe,CAAC,QAAQ;QAClC,OAAO;QACP,KAAK;QACL,WAAW,EAAE,aAAa,CAAC,IAAI;QAC/B,WAAW,EAAE,eAAe,CAAC,WAAW;KACzC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,SAAS,CAAC,CAAC;IAExD,OAAO,SAAS,CAAC,IAAI,CAAC;AACxB,CAAC;AAEM,KAAK,UAAU,oBAAoB,CACxC,OAAoB,EACpB,MAAkB;IAElB,MAAM,eAAe,GAAG,IAAA,6BAAiB,EAAC,MAAM,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC9D,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,SAAS,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAEvD,MAAM,WAAW,GAAG,IAAA,+BAAoB,EAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAE5D,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IACxE,MAAM,IAAA,6BAAgB,EAAC,eAAe,CAAC,CAAC;IAExC,IAAI,QAAQ,CAAC;IAEb,wCAAwC;IACxC,IAAI,WAAW,KAAK,QAAQ,EAAE,CAAC;QAC7B,sEAAsE;QACtE,0DAA0D;QAC1D,2EAA2E;QAC3E,MAAM,cAAc,GAAG,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC;QAC7D,IAAI,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC;YACtE,sBAAsB;YACtB,OAAO,wBAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAClD,CAAC;QAED,kEAAkE;QAClE,QAAQ,GAAG,gCAAgC,CACzC,OAAO,EACP,eAAe,CAAC,iBAAiB,CAClC,CAAC;QACF,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;QACjE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,4CAA4C;IAC5C,MAAM,WAAW,GAAG,wBAAwB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAEvE,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAEvE,6EAA6E;QAC7E,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC;YACpD,OAAO,CAAC,GAAG,CACT,mEAAmE,EACnE,WAAW,CACZ,CAAC;YACF,OAAO,wBAAY,CAAC,IAAI,CAAC;gBACvB,MAAM,EAAE,SAAS;gBACjB,WAAW,EAAE,WAAW;aACzB,CAAC,CAAC;QACL,CAAC;QAED,+BAA+B;QAC/B,QAAQ,GAAG,wBAAY,CAAC,QAAQ,CAAC,GAAG,WAAW,EAAE,CAAC,CAAC;QACnD,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,QAAQ,GAAG,gCAAgC,CACzC,OAAO,EACP,eAAe,CAAC,iBAAiB,CAClC,CAAC;QACF,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;GAWG;AACI,MAAM,OAAO,GAClB,CAAC,UAAU,GAAG,EAAE,EAAE,EAAE,CACpB,KAAK,EAAE,OAAoB,EAAyB,EAAE;IACpD,MAAM,MAAM,GAAG,IAAA,6BAAiB,EAAC,UAAU,CAAC,CAAC;IAE7C,IAAI,WAAW,GAAkB,IAAI,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC1C,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,WAAW,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAE1D,QAAQ,WAAW,EAAE,CAAC;YACpB,KAAK,WAAW;gBACd,OAAO,MAAM,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAChD,KAAK,UAAU;gBACb,OAAO,MAAM,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC/C,KAAK,QAAQ;gBACX,WAAW,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAClD,MAAM;YACR,KAAK,gBAAgB;gBACnB,OAAO,MAAM,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACrD;gBACE,MAAM,IAAI,SAAS,CAAC,uBAAuB,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;QAE3C,MAAM,MAAM,GAAG,KAAK,YAAY,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC;QAC/D,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;QAEnE,MAAM,QAAQ,GAAG,wBAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAEnE,IAAA,6BAAgB,EAAC,MAAM,CAAC,CAAC;QACzB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,8DAA8D;IAC9D,mEAAmE;IACnE,IAAI,WAAW;QAAE,IAAA,wBAAQ,EAAC,WAAW,CAAC,CAAC;IAEvC,+BAA+B;IAC/B,OAAO,wBAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC;AA5CS,QAAA,OAAO,WA4ChB","sourcesContent":["import type { NextRequest } from \"next/server.js\";\nimport { NextResponse } from \"next/server.js\";\nimport { revalidatePath } from \"next/cache.js\";\nimport type { AuthConfig } from \"@/nextjs/config.js\";\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport {\n clearAuthCookies,\n NextjsClientStorage,\n NextjsCookieStorage,\n} from \"@/nextjs/cookies.js\";\nimport { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { resolveOAuthAccessCode } from \"@/server/login.js\";\nimport { getUser } from \"@/nextjs/GetUser.js\";\nimport { resolveCallbackUrl } from \"@/nextjs/utils.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\nimport {\n TOKEN_EXCHANGE_SUCCESS_TEXT,\n TOKEN_EXCHANGE_TRIGGER_TEXT,\n} from \"@/constants.js\";\nimport {\n displayModeFromState,\n serverTokenExchangeFromState,\n} from \"@/lib/oauth.js\";\nimport { CodeVerifier, OAuthTokens } from \"@/shared/lib/types.js\";\nimport { generateOauthLogoutUrl } from \"@/shared/lib/util.js\";\nimport { redirect } from \"next/navigation.js\";\n\nconst logger = loggers.nextjs.handlers.auth;\n\nclass AuthError extends Error {\n constructor(\n message: string,\n public readonly status: number = 401,\n ) {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\nconst getAppUrl = (request: NextRequest): string | null =>\n request.cookies.get(CodeVerifier.APP_URL)?.value ||\n request.nextUrl.searchParams.get(\"appUrl\");\n\nconst getIdToken = async (config: AuthConfig): Promise<string | null> => {\n const cookieStorage = new NextjsCookieStorage(config.cookies?.tokens ?? {});\n return cookieStorage.get(OAuthTokens.ID_TOKEN);\n};\n\n/**\n * create a code verifier and challenge for PKCE\n * saving the verifier in a cookie for later use\n * @returns {Promise<NextResponse>}\n */\nasync function handleChallenge(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const cookieStorage = new NextjsCookieStorage(config.cookies?.tokens ?? {});\n const pkceProducer = new GenericPublicClientPKCEProducer(cookieStorage);\n\n const challenge = await pkceProducer.getCodeChallenge();\n const appUrl = request.nextUrl.searchParams.get(\"appUrl\");\n if (appUrl) {\n cookieStorage.set(CodeVerifier.APP_URL, appUrl);\n }\n return NextResponse.json({ status: \"success\", challenge });\n}\n\nasync function performTokenExchangeAndSetCookies(\n request: NextRequest,\n config: AuthConfig,\n code: string,\n state: string,\n appUrl: string,\n) {\n const resolvedConfigs = resolveAuthConfig(config);\n const cookieStorage = new NextjsCookieStorage(resolvedConfigs.cookies.tokens);\n\n const callbackUrl = resolveCallbackUrl(resolvedConfigs, appUrl);\n try {\n await resolveOAuthAccessCode(code, state, cookieStorage, {\n ...resolvedConfigs,\n redirectUrl: callbackUrl,\n });\n } catch (error) {\n logger.error(\"Token exchange failed:\", error);\n throw new AuthError(\"Failed to authenticate user\", 401);\n }\n\n const user = await getUser();\n if (!user) {\n throw new AuthError(\"Failed to get user info\", 401);\n }\n\n const clientStorage = new NextjsClientStorage();\n const userSession = new GenericUserSession(clientStorage);\n userSession.set(user);\n}\n\nconst generateHtmlResponseWithCallback = (\n request: NextRequest,\n callbackUrl: string,\n) => {\n // we need to replace the URL with resolved config in case the server is hosted\n // behind a reverse proxy or load balancer\n const requestUrl = new URL(request.url);\n const fetchUrl = `${callbackUrl}?${requestUrl.searchParams.toString()}&sameDomainCallback=true`;\n return new NextResponse(\n `<html>\n <body>\n <span style=\"display:none\">\n <script>\n window.onload = function () {\n const appUrl = globalThis.window?.location?.origin;\n fetch('${fetchUrl}&appUrl=' + appUrl).then((response) => {\n response.json().then((jsonResponse) => {\n if (jsonResponse.redirectUrl) {\n window.location.href = jsonResponse.redirectUrl;\n }\n });\n });\n };\n </script>\n </span>\n </body>\n </html>\n `,\n );\n};\n\nasync function handleCallback(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n console.log(\"handleCallback\", { request, resolvedConfigs });\n const code = request.nextUrl.searchParams.get(\"code\");\n const state = request.nextUrl.searchParams.get(\"state\");\n if (!code || !state) throw new AuthError(\"Bad parameters\", 400);\n\n // appUrl is passed from the client to the server in the query string\n // this is necessary because the server does not have access to the client's window.location.origin\n // and can not accurately determine the appUrl (specially if the app is behind a reverse proxy)\n const appUrl = getAppUrl(request);\n\n // If we have a code_verifier cookie and the appUrl, we can do a token exchange.\n // Otherwise, just render an empty page.\n // The initial redirect back from the auth server does not send cookies, because the redirect is from a 3rd-party domain.\n // The client will make an additional call to this route with cookies included, at which point we do the token exchange.\n console.log(\"handleCallback\", {\n code,\n state,\n appUrl,\n });\n\n const codeVerifier = request.cookies.get(CodeVerifier.COOKIE_NAME);\n\n if (!codeVerifier || !appUrl) {\n console.log(\"handleCallback no code_verifier found\", {\n state,\n serverTokenExchange: serverTokenExchangeFromState(`${state}`),\n });\n let response = new NextResponse(\n `<html><body><span style=\"display:none\">${TOKEN_EXCHANGE_TRIGGER_TEXT}</span></body></html>`,\n );\n\n // in server-side token exchange mode we need to launch a page that will trigger the token exchange\n // from the same domain, allowing it access to the code_verifier cookie\n // we only need to do this in redirect mode, as the iframe already triggers a client-side token exchange\n // if no code-verifier cookie is found\n if (state && serverTokenExchangeFromState(state)) {\n console.log(\n \"handleCallback serverTokenExchangeFromState, launching redirect page...\",\n {\n requestUrl: request.url,\n configCallbackUrl: resolvedConfigs.callbackUrl,\n },\n );\n // generate a page that will callback to the same domain, allowing access\n // to the code_verifier cookie and passing the appUrl.\n response = generateHtmlResponseWithCallback(\n request,\n resolvedConfigs.callbackUrl,\n );\n }\n\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n console.log(\n `handleCallback no code_verifier found, returning ${TOKEN_EXCHANGE_TRIGGER_TEXT}`,\n );\n return response;\n }\n\n await performTokenExchangeAndSetCookies(\n request,\n resolvedConfigs,\n code,\n state,\n appUrl,\n );\n\n if (request.url.includes(\"sameDomainCallback=true\")) {\n console.log(\n \"handleCallback sameDomainCallback = true, returnining redirectUrl\",\n appUrl,\n );\n return NextResponse.json({\n status: \"success\",\n redirectUrl: appUrl,\n });\n }\n\n // this is the case where a 'normal' redirect is happening\n if (serverTokenExchangeFromState(state)) {\n console.log(\n \"handleCallback serverTokenExchangeFromState, redirect to appUrl\",\n appUrl,\n );\n if (!appUrl) {\n throw new Error(\"appUrl undefined. Cannot redirect.\");\n }\n return NextResponse.redirect(`${appUrl}`);\n }\n // return an empty HTML response so the iframe doesn't show any response\n // in the short moment between the redirect and the parent window\n // acknowledging the redirect and closing the iframe\n const response = new NextResponse(\n `<html><span style=\"display:none\">${TOKEN_EXCHANGE_SUCCESS_TEXT}</span></html>`,\n );\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n return response;\n}\n\n/**\n * If redirectPath is an absolute path, return it as-is.\n * Otherwise for relative paths, append it to the current domain.\n * @param redirectPath\n * @returns\n */\nconst getAbsoluteRedirectPath = (\n redirectPath: string,\n currentBasePath: string,\n) => new URL(redirectPath, currentBasePath).href;\n\nconst getPostLogoutRedirectUrl = (\n request: NextRequest,\n config: AuthConfig,\n): string | null => {\n const { loginUrl } = resolveAuthConfig(config);\n const redirectTarget = loginUrl ?? \"/\";\n\n // if the optional loginUrl is provided and it is an absolute URL,\n // use it as the redirect target\n const isAbsoluteRedirect = /^(https?:\\/\\/|www\\.).+/i.test(redirectTarget);\n if (isAbsoluteRedirect) {\n return redirectTarget;\n }\n\n // if loginUrl is not defined, the appUrl is passed from the client to the server\n // in the query string or cookies. This is necessary because the server does not\n // have access to the client's window.location and can not accurately determine\n // the appUrl (specially if the app is behind a reverse proxy).\n const appUrl = getAppUrl(request);\n if (appUrl) return getAbsoluteRedirectPath(redirectTarget, appUrl);\n\n return null;\n};\n\nconst revalidateUrlPath = async (url: string) => {\n try {\n const path = new URL(url).pathname;\n revalidatePath(path);\n } catch (error) {\n logger.warn(\"Failed to revalidate path after logout:\", error);\n }\n};\n\nexport async function handleLogout(\n request: NextRequest,\n config: AuthConfig,\n): Promise<string> {\n console.log(\"handleLogout\", { params: request.nextUrl.searchParams });\n const resolvedConfigs = resolveAuthConfig(config);\n\n // read the id_token from the cookies\n const idToken = await getIdToken(resolvedConfigs);\n\n // read the state from the query parameters\n const state = request.nextUrl.searchParams.get(\"state\");\n\n if (!state || !idToken) throw new AuthError(\"Bad parameters\", 400);\n\n const postLogoutUrl = new URL(\n resolvedConfigs.logoutCallbackUrl,\n getAppUrl(request) || request.url,\n );\n const logoutUrl = await generateOauthLogoutUrl({\n clientId: resolvedConfigs.clientId,\n idToken,\n state,\n redirectUrl: postLogoutUrl.href,\n oauthServer: resolvedConfigs.oauthServer,\n });\n console.log(\"handleLogout: redirecting to \", logoutUrl);\n\n return logoutUrl.href;\n}\n\nexport async function handleLogoutCallback(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n const state = request.nextUrl.searchParams.get(\"state\") || \"\";\n if (!state) throw new AuthError(\"Bad parameters\", 400);\n\n const displayMode = displayModeFromState(state, \"redirect\");\n\n console.log(\"handleLogout: clear auth cookies\", { state, displayMode });\n await clearAuthCookies(resolvedConfigs);\n\n let response;\n\n // handle logout for iframe display mode\n if (displayMode === \"iframe\") {\n // try to read the token from cookies. If cookies cant be read/written\n // because the request cames from a cross-origin redirect,\n // we need to show a page that will trigger the logout from the same domain\n const canReadCookies = !!(await getIdToken(resolvedConfigs));\n if (canReadCookies || request.url.includes(\"sameDomainCallback=true\")) {\n // just return success\n return NextResponse.json({ status: \"success\" });\n }\n\n // return a page that will trigger the logout from the same domain\n response = generateHtmlResponseWithCallback(\n request,\n resolvedConfigs.logoutCallbackUrl,\n );\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n return response;\n }\n\n // handle logout for non-iframe display mode\n const redirectUrl = getPostLogoutRedirectUrl(request, resolvedConfigs);\n\n if (redirectUrl) {\n console.log(\"handleLogout with redirect mode\", { state, redirectUrl });\n\n // this is comming from the fetch from the HTML page returned by this handler\n if (request.url.includes(\"sameDomainCallback=true\")) {\n console.log(\n \"handleCallback sameDomainCallback = true, returnining redirectUrl\",\n redirectUrl,\n );\n return NextResponse.json({\n status: \"success\",\n redirectUrl: redirectUrl,\n });\n }\n\n // just redirect to the app url\n response = NextResponse.redirect(`${redirectUrl}`);\n revalidateUrlPath(redirectUrl);\n } else {\n console.log(\"handleLogout no redirectUrl found\", { state });\n response = generateHtmlResponseWithCallback(\n request,\n resolvedConfigs.logoutCallbackUrl,\n );\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n }\n\n return response;\n}\n\n/**\n * Creates an authentication handler for Next.js API routes\n *\n * Usage:\n * ```ts\n * // app/api/auth/[...civicauth]/route.ts\n * import { handler } from '@civic/auth/nextjs'\n * export const GET = handler({\n * // optional config overrides\n * })\n * ```\n */\nexport const handler =\n (authConfig = {}) =>\n async (request: NextRequest): Promise<NextResponse> => {\n const config = resolveAuthConfig(authConfig);\n\n let redirectUrl: string | null = null;\n\n try {\n const pathname = request.nextUrl.pathname;\n const pathSegments = pathname.split(\"/\");\n const lastSegment = pathSegments[pathSegments.length - 1];\n\n switch (lastSegment) {\n case \"challenge\":\n return await handleChallenge(request, config);\n case \"callback\":\n return await handleCallback(request, config);\n case \"logout\":\n redirectUrl = await handleLogout(request, config);\n break;\n case \"logoutcallback\":\n return await handleLogoutCallback(request, config);\n default:\n throw new AuthError(`Invalid auth route: ${pathname}`, 404);\n }\n } catch (error) {\n logger.error(\"Auth handler error:\", error);\n\n const status = error instanceof AuthError ? error.status : 500;\n const message =\n error instanceof Error ? error.message : \"Authentication failed\";\n\n const response = NextResponse.json({ error: message }, { status });\n\n clearAuthCookies(config);\n return response;\n }\n\n // redirect on Nextjs must be called outside a try-catch block\n // see https://nextjs.org/docs/app/api-reference/functions/redirect\n if (redirectUrl) redirect(redirectUrl);\n\n // do nothing if no redirectUrl\n return NextResponse.json({ status: \"ok\" });\n };\n"]}
|
|
1
|
+
{"version":3,"file":"routeHandler.js","sourceRoot":"","sources":["../../../src/nextjs/routeHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n TOKEN_EXCHANGE_SUCCESS_TEXT,\n TOKEN_EXCHANGE_TRIGGER_TEXT,\n} from \"@/constants.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport {\n displayModeFromState,\n serverTokenExchangeFromState,\n} from \"@/lib/oauth.js\";\nimport type { AuthConfig } from \"@/nextjs/config.js\";\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport {\n clearAuthCookies,\n NextjsClientStorage,\n NextjsCookieStorage,\n} from \"@/nextjs/cookies.js\";\nimport { getUser } from \"@/nextjs/GetUser.js\";\nimport { resolveCallbackUrl } from \"@/nextjs/utils.js\";\nimport { resolveOAuthAccessCode } from \"@/server/login.js\";\nimport { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { AuthenticationRefresherImpl } from \"@/shared/lib/AuthenticationRefresherImpl.js\";\nimport { CodeVerifier, OAuthTokens } from \"@/shared/lib/types.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\nimport { generateOauthLogoutUrl } from \"@/shared/lib/util.js\";\nimport { revalidatePath } from \"next/cache.js\";\nimport type { NextRequest } from \"next/server.js\";\nimport { NextResponse } from \"next/server.js\";\n\nconst logger = loggers.nextjs.handlers.auth;\n\nclass AuthError extends Error {\n constructor(\n message: string,\n public readonly status: number = 401,\n ) {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\nconst getAppUrl = (request: NextRequest): string | null =>\n request.cookies.get(CodeVerifier.APP_URL)?.value ||\n request.nextUrl.searchParams.get(\"appUrl\");\n\nconst getIdToken = async (config: AuthConfig): Promise<string | null> => {\n const cookieStorage = new NextjsCookieStorage(config.cookies?.tokens ?? {});\n return cookieStorage.get(OAuthTokens.ID_TOKEN);\n};\n\n/**\n * create a code verifier and challenge for PKCE\n * saving the verifier in a cookie for later use\n * @returns {Promise<NextResponse>}\n */\nasync function handleChallenge(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const cookieStorage = new NextjsCookieStorage(config.cookies?.tokens ?? {});\n const pkceProducer = new GenericPublicClientPKCEProducer(cookieStorage);\n\n const challenge = await pkceProducer.getCodeChallenge();\n const appUrl = request.nextUrl.searchParams.get(\"appUrl\");\n if (appUrl) {\n cookieStorage.set(CodeVerifier.APP_URL, appUrl);\n }\n return NextResponse.json({ status: \"success\", challenge });\n}\n\nasync function performTokenExchangeAndSetCookies(\n request: NextRequest,\n config: AuthConfig,\n code: string,\n state: string,\n appUrl: string,\n) {\n const resolvedConfigs = resolveAuthConfig(config);\n const cookieStorage = new NextjsCookieStorage(resolvedConfigs.cookies.tokens);\n\n const callbackUrl = resolveCallbackUrl(resolvedConfigs, appUrl);\n try {\n await resolveOAuthAccessCode(code, state, cookieStorage, {\n ...resolvedConfigs,\n redirectUrl: callbackUrl,\n });\n } catch (error) {\n logger.error(\"Token exchange failed:\", error);\n throw new AuthError(\"Failed to authenticate user\", 401);\n }\n\n const user = await getUser();\n if (!user) {\n throw new AuthError(\"Failed to get user info\", 401);\n }\n\n const clientStorage = new NextjsClientStorage();\n const userSession = new GenericUserSession(clientStorage);\n userSession.set(user);\n}\nasync function handleRefresh(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n const cookieStorage = new NextjsCookieStorage(config.cookies?.tokens ?? {});\n\n const refresher = await AuthenticationRefresherImpl.build(\n {\n clientId: resolvedConfigs.clientId,\n oauthServer: resolvedConfigs.oauthServer,\n redirectUrl: resolvedConfigs.callbackUrl,\n refreshUrl: resolvedConfigs.refreshUrl,\n },\n cookieStorage,\n );\n const tokens = await refresher.refreshAccessToken();\n\n // this will use the refresh token to get new tokens and, if successful\n // the idToken, accessToken and user cookies will be updated\n // await newRefresher.refreshTokens();\n return NextResponse.json({ status: \"success\", tokens });\n}\n\nconst generateHtmlResponseWithCallback = (\n request: NextRequest,\n callbackUrl: string,\n) => {\n // we need to replace the URL with resolved config in case the server is hosted\n // behind a reverse proxy or load balancer\n const requestUrl = new URL(request.url);\n const fetchUrl = `${callbackUrl}?${requestUrl.searchParams.toString()}&sameDomainCallback=true`;\n return new NextResponse(\n `<html>\n <body>\n <span style=\"display:none\">\n <script>\n window.onload = function () {\n const appUrl = globalThis.window?.location?.origin;\n fetch('${fetchUrl}&appUrl=' + appUrl).then((response) => {\n response.json().then((jsonResponse) => {\n if (jsonResponse.redirectUrl) {\n window.location.href = jsonResponse.redirectUrl;\n }\n });\n });\n };\n </script>\n </span>\n </body>\n </html>\n `,\n );\n};\n\nasync function handleCallback(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n console.log(\"handleCallback\", { request, resolvedConfigs });\n const code = request.nextUrl.searchParams.get(\"code\");\n const state = request.nextUrl.searchParams.get(\"state\");\n if (!code || !state) throw new AuthError(\"Bad parameters\", 400);\n\n // appUrl is passed from the client to the server in the query string\n // this is necessary because the server does not have access to the client's window.location.origin\n // and can not accurately determine the appUrl (specially if the app is behind a reverse proxy)\n const appUrl = getAppUrl(request);\n\n // If we have a code_verifier cookie and the appUrl, we can do a token exchange.\n // Otherwise, just render an empty page.\n // The initial redirect back from the auth server does not send cookies, because the redirect is from a 3rd-party domain.\n // The client will make an additional call to this route with cookies included, at which point we do the token exchange.\n console.log(\"handleCallback\", {\n code,\n state,\n appUrl,\n });\n\n const codeVerifier = request.cookies.get(CodeVerifier.COOKIE_NAME);\n\n if (!codeVerifier || !appUrl) {\n console.log(\"handleCallback no code_verifier found\", {\n state,\n serverTokenExchange: serverTokenExchangeFromState(`${state}`),\n });\n let response = new NextResponse(\n `<html><body><span style=\"display:none\">${TOKEN_EXCHANGE_TRIGGER_TEXT}</span></body></html>`,\n );\n\n // in server-side token exchange mode we need to launch a page that will trigger the token exchange\n // from the same domain, allowing it access to the code_verifier cookie\n // we only need to do this in redirect mode, as the iframe already triggers a client-side token exchange\n // if no code-verifier cookie is found\n if (state && serverTokenExchangeFromState(state)) {\n console.log(\n \"handleCallback serverTokenExchangeFromState, launching redirect page...\",\n {\n requestUrl: request.url,\n configCallbackUrl: resolvedConfigs.callbackUrl,\n },\n );\n // generate a page that will callback to the same domain, allowing access\n // to the code_verifier cookie and passing the appUrl.\n response = generateHtmlResponseWithCallback(\n request,\n resolvedConfigs.callbackUrl,\n );\n }\n\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n console.log(\n `handleCallback no code_verifier found, returning ${TOKEN_EXCHANGE_TRIGGER_TEXT}`,\n );\n return response;\n }\n\n await performTokenExchangeAndSetCookies(\n request,\n resolvedConfigs,\n code,\n state,\n appUrl,\n );\n\n if (request.url.includes(\"sameDomainCallback=true\")) {\n console.log(\n \"handleCallback sameDomainCallback = true, returnining redirectUrl\",\n appUrl,\n );\n return NextResponse.json({\n status: \"success\",\n redirectUrl: appUrl,\n });\n }\n\n // this is the case where a 'normal' redirect is happening\n if (serverTokenExchangeFromState(state)) {\n console.log(\n \"handleCallback serverTokenExchangeFromState, redirect to appUrl\",\n appUrl,\n );\n if (!appUrl) {\n throw new Error(\"appUrl undefined. Cannot redirect.\");\n }\n return NextResponse.redirect(`${appUrl}`);\n }\n // return an empty HTML response so the iframe doesn't show any response\n // in the short moment between the redirect and the parent window\n // acknowledging the redirect and closing the iframe\n const response = new NextResponse(\n `<html><span style=\"display:none\">${TOKEN_EXCHANGE_SUCCESS_TEXT}</span></html>`,\n );\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n return response;\n}\n\n/**\n * If redirectPath is an absolute path, return it as-is.\n * Otherwise for relative paths, append it to the current domain.\n * @param redirectPath\n * @returns\n */\nconst getAbsoluteRedirectPath = (\n redirectPath: string,\n currentBasePath: string,\n) => new URL(redirectPath, currentBasePath).href;\n\nconst getPostLogoutRedirectUrl = (\n request: NextRequest,\n config: AuthConfig,\n): string | null => {\n const { loginUrl } = resolveAuthConfig(config);\n const redirectTarget = loginUrl ?? \"/\";\n\n // if the optional loginUrl is provided and it is an absolute URL,\n // use it as the redirect target\n const isAbsoluteRedirect = /^(https?:\\/\\/|www\\.).+/i.test(redirectTarget);\n if (isAbsoluteRedirect) {\n return redirectTarget;\n }\n\n // if loginUrl is not defined, the appUrl is passed from the client to the server\n // in the query string or cookies. This is necessary because the server does not\n // have access to the client's window.location and can not accurately determine\n // the appUrl (specially if the app is behind a reverse proxy).\n const appUrl = getAppUrl(request);\n if (appUrl) return getAbsoluteRedirectPath(redirectTarget, appUrl);\n\n return null;\n};\n\nconst revalidateUrlPath = async (url: string) => {\n try {\n const path = new URL(url).pathname;\n revalidatePath(path);\n } catch (error) {\n logger.warn(\"Failed to revalidate path after logout:\", error);\n }\n};\n\nexport async function handleLogout(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n console.log(\"handleLogout\", { params: request.nextUrl.searchParams });\n const resolvedConfigs = resolveAuthConfig(config);\n\n // read the id_token from the cookies\n const idToken = await getIdToken(resolvedConfigs);\n\n // read the state from the query parameters\n const state = request.nextUrl.searchParams.get(\"state\");\n\n if (!state || !idToken) throw new AuthError(\"Bad parameters\", 400);\n\n const postLogoutUrl = new URL(\n resolvedConfigs.logoutCallbackUrl,\n getAppUrl(request) || request.url,\n );\n const logoutUrl = await generateOauthLogoutUrl({\n clientId: resolvedConfigs.clientId,\n idToken,\n state,\n redirectUrl: postLogoutUrl.href,\n oauthServer: resolvedConfigs.oauthServer,\n });\n\n return NextResponse.redirect(`${logoutUrl.href}`);\n}\n\nexport async function handleLogoutCallback(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n const state = request.nextUrl.searchParams.get(\"state\") || \"\";\n if (!state) throw new AuthError(\"Bad parameters\", 400);\n\n const displayMode = displayModeFromState(state, \"iframe\");\n\n console.log(\"handleLogout: clear auth cookies\", { state, displayMode });\n\n const canAccessCookies = !!(await getIdToken(resolvedConfigs));\n if (canAccessCookies) {\n await clearAuthCookies(resolvedConfigs);\n }\n\n let response;\n\n // handle logout for iframe display mode\n if (displayMode === \"iframe\") {\n // try to read the token from cookies. If cookies cant be read/written\n // because the request cames from a cross-origin redirect,\n // we need to show a page that will trigger the logout from the same domain\n if (canAccessCookies || request.url.includes(\"sameDomainCallback=true\")) {\n // just return success\n return NextResponse.json({ status: \"success\" });\n }\n\n // return a page that will trigger the logout from the same domain\n response = generateHtmlResponseWithCallback(\n request,\n resolvedConfigs.logoutCallbackUrl,\n );\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n return response;\n }\n\n // handle logout for non-iframe display mode\n const redirectUrl = getPostLogoutRedirectUrl(request, resolvedConfigs);\n\n if (redirectUrl && canAccessCookies) {\n console.log(\"handleLogout with redirect mode\", { state, redirectUrl });\n\n // this is comming from the fetch from the HTML page returned by this handler\n if (request.url.includes(\"sameDomainCallback=true\")) {\n console.log(\n \"handleCallback sameDomainCallback = true, returnining redirectUrl\",\n redirectUrl,\n );\n return NextResponse.json({\n status: \"success\",\n redirectUrl: redirectUrl,\n });\n }\n\n // just redirect to the app url\n response = NextResponse.redirect(`${redirectUrl}`);\n revalidateUrlPath(redirectUrl);\n } else {\n console.log(\"handleLogout no redirectUrl found\", { state });\n response = generateHtmlResponseWithCallback(\n request,\n resolvedConfigs.logoutCallbackUrl,\n );\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n }\n\n return response;\n}\n\n/**\n * Creates an authentication handler for Next.js API routes\n *\n * Usage:\n * ```ts\n * // app/api/auth/[...civicauth]/route.ts\n * import { handler } from '@civic/auth/nextjs'\n * export const GET = handler({\n * // optional config overrides\n * })\n * ```\n */\nexport const handler =\n (authConfig = {}) =>\n async (request: NextRequest): Promise<NextResponse> => {\n const config = resolveAuthConfig(authConfig);\n\n try {\n const pathname = request.nextUrl.pathname;\n const pathSegments = pathname.split(\"/\");\n const lastSegment = pathSegments[pathSegments.length - 1];\n\n switch (lastSegment) {\n case \"challenge\":\n return await handleChallenge(request, config);\n case \"callback\":\n return await handleCallback(request, config);\n case \"refresh\":\n return await handleRefresh(request, config);\n case \"logout\":\n return await handleLogout(request, config);\n case \"logoutcallback\":\n return await handleLogoutCallback(request, config);\n default:\n throw new AuthError(`Invalid auth route: ${pathname}`, 404);\n }\n } catch (error) {\n logger.error(\"Auth handler error:\", error);\n\n const status = error instanceof AuthError ? error.status : 500;\n const message =\n error instanceof Error ? error.message : \"Authentication failed\";\n\n const response = NextResponse.json({ error: message }, { status });\n\n clearAuthCookies(config);\n return response;\n }\n };\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientTokenExchangeSessionProvider.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/providers/ClientTokenExchangeSessionProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAMN,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ClientTokenExchangeSessionProvider.d.ts","sourceRoot":"","sources":["../../../../src/reactjs/providers/ClientTokenExchangeSessionProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAMN,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAS9C,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAC1D,CAAC;AAcF,QAAA,MAAM,iCAAiC,yDACkC,CAAC;AAE1E,KAAK,qCAAqC,GAAG;IAC3C,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,kCAAkC,kBAErC,qCAAqC,sBAsIvC,CAAC;AAEF,YAAY,EAAE,qCAAqC,IAAI,kBAAkB,EAAE,CAAC;AAC5E,OAAO,EACL,kCAAkC,EAClC,iCAAiC,GAClC,CAAC"}
|
|
@@ -38,10 +38,8 @@ exports.ClientTokenExchangeSessionContext = exports.ClientTokenExchangeSessionPr
|
|
|
38
38
|
const react_1 = __importStar(require("react"));
|
|
39
39
|
const AuthenticationService_js_1 = require("../../services/AuthenticationService.js");
|
|
40
40
|
const windowUtil_js_1 = require("../../lib/windowUtil.js");
|
|
41
|
-
const
|
|
42
|
-
const useCivicAuthConfig_js_1 = require("../../shared/hooks/useCivicAuthConfig.js");
|
|
41
|
+
const index_js_1 = require("../../shared/hooks/index.js");
|
|
43
42
|
const storage_js_1 = require("../../browser/storage.js");
|
|
44
|
-
const useRefresh_js_1 = require("../../shared/hooks/useRefresh.js");
|
|
45
43
|
const defaultSession = {
|
|
46
44
|
data: {
|
|
47
45
|
authenticated: false,
|
|
@@ -57,29 +55,14 @@ const defaultSession = {
|
|
|
57
55
|
const ClientTokenExchangeSessionContext = (0, react_1.createContext)(defaultSession);
|
|
58
56
|
exports.ClientTokenExchangeSessionContext = ClientTokenExchangeSessionContext;
|
|
59
57
|
const ClientTokenExchangeSessionProvider = ({ children, }) => {
|
|
60
|
-
const authConfig = (0,
|
|
58
|
+
const authConfig = (0, index_js_1.useCivicAuthConfig)();
|
|
61
59
|
const [authService, setAuthService] = (0, react_1.useState)();
|
|
62
60
|
const [error, setError] = (0, react_1.useState)(null);
|
|
63
61
|
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
64
62
|
const [session, setSession] = (0, react_1.useState)(null);
|
|
65
|
-
const
|
|
66
|
-
(0,
|
|
67
|
-
|
|
68
|
-
(0, react_1.useEffect)(() => {
|
|
69
|
-
const handleFocus = () => {
|
|
70
|
-
setIsWindowFocused(true);
|
|
71
|
-
};
|
|
72
|
-
const handleBlur = () => {
|
|
73
|
-
setIsWindowFocused(false);
|
|
74
|
-
};
|
|
75
|
-
window.addEventListener("focus", handleFocus);
|
|
76
|
-
window.addEventListener("blur", handleBlur);
|
|
77
|
-
return () => {
|
|
78
|
-
window.removeEventListener("focus", handleFocus);
|
|
79
|
-
window.removeEventListener("blur", handleBlur);
|
|
80
|
-
};
|
|
81
|
-
}, []);
|
|
82
|
-
const currentUrl = (0, useCurrentUrl_js_1.useCurrentUrl)();
|
|
63
|
+
const { isWindowFocused } = (0, index_js_1.useWindowFocused)();
|
|
64
|
+
const currentUrl = (0, index_js_1.useCurrentUrl)();
|
|
65
|
+
(0, index_js_1.useRefresh)(session);
|
|
83
66
|
(0, react_1.useEffect)(() => {
|
|
84
67
|
if (!currentUrl || !authConfig)
|
|
85
68
|
return;
|
|
@@ -177,8 +160,8 @@ const ClientTokenExchangeSessionProvider = ({ children, }) => {
|
|
|
177
160
|
data: session,
|
|
178
161
|
error,
|
|
179
162
|
isLoading,
|
|
180
|
-
doTokenExchange,
|
|
181
|
-
}), [session, error, isLoading, doTokenExchange]);
|
|
163
|
+
doTokenExchange: authService ? doTokenExchange : null,
|
|
164
|
+
}), [session, error, isLoading, authService, doTokenExchange]);
|
|
182
165
|
return (react_1.default.createElement(ClientTokenExchangeSessionContext.Provider, { value: value }, children));
|
|
183
166
|
};
|
|
184
167
|
exports.ClientTokenExchangeSessionProvider = ClientTokenExchangeSessionProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientTokenExchangeSessionProvider.js","sourceRoot":"","sources":["../../../../src/reactjs/providers/ClientTokenExchangeSessionProvider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport type { ReactNode } from \"react\";\nimport React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { BrowserAuthenticationService } from \"@/services/AuthenticationService.js\";\nimport type { AuthenticationResolver } from \"@/services/types.js\";\nimport { isWindowInIframe } from \"@/lib/windowUtil.js\";\nimport type { SessionData } from \"@/types.js\";\nimport { useCurrentUrl } from \"@/shared/hooks/useCurrentUrl.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/useCivicAuthConfig.js\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\nimport { useRefresh } from \"../../shared/hooks/useRefresh.js\";\n\nexport type ClientTokenExchangeSessionProviderOutput = {\n data: SessionData | null;\n error: Error | null;\n isLoading: boolean;\n doTokenExchange: null | ((url: string) => Promise<void>);\n};\nconst defaultSession: ClientTokenExchangeSessionProviderOutput = {\n data: {\n authenticated: false,\n idToken: undefined,\n accessToken: undefined,\n displayMode: \"iframe\",\n },\n error: null,\n isLoading: false,\n doTokenExchange: null,\n};\n\n// Context for exposing session specifically to the TokenProvider\nconst ClientTokenExchangeSessionContext =\n createContext<ClientTokenExchangeSessionProviderOutput>(defaultSession);\n\ntype ClientTokenExchangeSessionContextType = {\n children: ReactNode;\n};\n\nconst ClientTokenExchangeSessionProvider = ({\n children,\n}: ClientTokenExchangeSessionContextType) => {\n const authConfig = useCivicAuthConfig();\n const [authService, setAuthService] = useState<AuthenticationResolver>();\n const [error, setError] = useState<Error | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [session, setSession] = useState<SessionData | null>(null);\n const [isWindowFocused, setIsWindowFocused] = useState(true);\n\n useRefresh(session);\n // handle the window refocusing after redirect\n useEffect(() => {\n const handleFocus = () => {\n setIsWindowFocused(true);\n };\n\n const handleBlur = () => {\n setIsWindowFocused(false);\n };\n window.addEventListener(\"focus\", handleFocus);\n window.addEventListener(\"blur\", handleBlur);\n\n return () => {\n window.removeEventListener(\"focus\", handleFocus);\n window.removeEventListener(\"blur\", handleBlur);\n };\n }, []);\n\n const currentUrl = useCurrentUrl();\n\n useEffect(() => {\n if (!currentUrl || !authConfig) return;\n\n const {\n redirectUrl,\n clientId,\n oauthServer,\n scopes,\n logoutRedirectUrl,\n logoutUrl,\n } = authConfig;\n BrowserAuthenticationService.build({\n clientId,\n redirectUrl,\n logoutRedirectUrl,\n logoutUrl,\n oauthServer,\n scopes,\n displayMode: \"iframe\",\n }).then(setAuthService);\n }, [currentUrl, authConfig]);\n\n const isInIframe = isWindowInIframe(globalThis.window);\n\n const doTokenExchange = useCallback(\n async (inUrl: string) => {\n if (!authService) return;\n const url = new URL(inUrl);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n if (code && state) {\n try {\n setIsLoading(true);\n await authService.tokenExchange(code, state);\n } catch (error) {\n setError(error as Error);\n setSession({ authenticated: false });\n }\n setIsLoading(false);\n }\n },\n [authService],\n );\n\n const onSignIn = useCallback(async () => {\n if (!authService) return;\n const session = await authService.getSessionData();\n setSession(session);\n }, [authService]);\n\n const onSignOut = useCallback(() => {\n setSession({ authenticated: false });\n }, []);\n\n useEffect(() => {\n LocalStorageAdapter.emitter.on(\"signIn\", onSignIn);\n LocalStorageAdapter.emitter.on(\"signOut\", onSignOut);\n return () => {\n LocalStorageAdapter.emitter.off(\"signIn\", onSignIn);\n LocalStorageAdapter.emitter.off(\"signOut\", onSignOut);\n };\n }, [onSignIn, onSignOut]);\n\n useEffect(() => {\n if (!authConfig) {\n setIsLoading(true);\n } else {\n setIsLoading(false);\n }\n }, [authConfig]);\n // Handle page load or refocus\n useEffect(() => {\n if (!authConfig || !authService || !currentUrl || isInIframe || isLoading) {\n return;\n }\n const abortController = new AbortController();\n const onPageLoad = async () => {\n // if we have existing tokens, then validate them and return the session data\n // otherwise check if we have a code in the url and exchange it for tokens\n // if we have neither, return undefined\n const existingSessionData = await authService.validateExistingSession();\n if (existingSessionData.authenticated) {\n setSession(existingSessionData);\n return;\n }\n if (\n abortController.signal.aborted ||\n !new URL(currentUrl).searchParams.get(\"code\")\n ) {\n return;\n }\n await doTokenExchange(currentUrl);\n };\n onPageLoad();\n return () => {\n abortController.abort();\n };\n }, [\n authConfig,\n authService,\n currentUrl,\n doTokenExchange,\n isInIframe,\n isLoading,\n isWindowFocused,\n session?.authenticated,\n ]);\n\n const value = useMemo(\n () => ({\n data: session,\n error,\n isLoading,\n doTokenExchange,\n }),\n [session, error, isLoading, doTokenExchange],\n );\n\n return (\n <ClientTokenExchangeSessionContext.Provider value={value}>\n {children}\n </ClientTokenExchangeSessionContext.Provider>\n );\n};\n\nexport type { ClientTokenExchangeSessionContextType as SessionContextType };\nexport {\n ClientTokenExchangeSessionProvider,\n ClientTokenExchangeSessionContext,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"ClientTokenExchangeSessionProvider.js","sourceRoot":"","sources":["../../../../src/reactjs/providers/ClientTokenExchangeSessionProvider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport type { ReactNode } from \"react\";\nimport React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { BrowserAuthenticationService } from \"@/services/AuthenticationService.js\";\nimport type { AuthenticationResolver } from \"@/services/types.js\";\nimport { isWindowInIframe } from \"@/lib/windowUtil.js\";\nimport type { SessionData } from \"@/types.js\";\nimport {\n useCurrentUrl,\n useCivicAuthConfig,\n useWindowFocused,\n useRefresh,\n} from \"@/shared/hooks/index.js\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\n\nexport type ClientTokenExchangeSessionProviderOutput = {\n data: SessionData | null;\n error: Error | null;\n isLoading: boolean;\n doTokenExchange: null | ((url: string) => Promise<void>);\n};\nconst defaultSession: ClientTokenExchangeSessionProviderOutput = {\n data: {\n authenticated: false,\n idToken: undefined,\n accessToken: undefined,\n displayMode: \"iframe\",\n },\n error: null,\n isLoading: false,\n doTokenExchange: null,\n};\n\n// Context for exposing session specifically to the TokenProvider\nconst ClientTokenExchangeSessionContext =\n createContext<ClientTokenExchangeSessionProviderOutput>(defaultSession);\n\ntype ClientTokenExchangeSessionContextType = {\n children: ReactNode;\n};\n\nconst ClientTokenExchangeSessionProvider = ({\n children,\n}: ClientTokenExchangeSessionContextType) => {\n const authConfig = useCivicAuthConfig();\n const [authService, setAuthService] = useState<AuthenticationResolver>();\n const [error, setError] = useState<Error | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [session, setSession] = useState<SessionData | null>(null);\n const { isWindowFocused } = useWindowFocused();\n const currentUrl = useCurrentUrl();\n\n useRefresh(session);\n\n useEffect(() => {\n if (!currentUrl || !authConfig) return;\n\n const {\n redirectUrl,\n clientId,\n oauthServer,\n scopes,\n logoutRedirectUrl,\n logoutUrl,\n } = authConfig;\n BrowserAuthenticationService.build({\n clientId,\n redirectUrl,\n logoutRedirectUrl,\n logoutUrl,\n oauthServer,\n scopes,\n displayMode: \"iframe\",\n }).then(setAuthService);\n }, [currentUrl, authConfig]);\n\n const isInIframe = isWindowInIframe(globalThis.window);\n\n const doTokenExchange = useCallback(\n async (inUrl: string) => {\n if (!authService) return;\n const url = new URL(inUrl);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n if (code && state) {\n try {\n setIsLoading(true);\n await authService.tokenExchange(code, state);\n } catch (error) {\n setError(error as Error);\n setSession({ authenticated: false });\n }\n setIsLoading(false);\n }\n },\n [authService],\n );\n\n const onSignIn = useCallback(async () => {\n if (!authService) return;\n const session = await authService.getSessionData();\n setSession(session);\n }, [authService]);\n\n const onSignOut = useCallback(() => {\n setSession({ authenticated: false });\n }, []);\n\n useEffect(() => {\n LocalStorageAdapter.emitter.on(\"signIn\", onSignIn);\n LocalStorageAdapter.emitter.on(\"signOut\", onSignOut);\n return () => {\n LocalStorageAdapter.emitter.off(\"signIn\", onSignIn);\n LocalStorageAdapter.emitter.off(\"signOut\", onSignOut);\n };\n }, [onSignIn, onSignOut]);\n\n useEffect(() => {\n if (!authConfig) {\n setIsLoading(true);\n } else {\n setIsLoading(false);\n }\n }, [authConfig]);\n // Handle page load or refocus\n useEffect(() => {\n if (!authConfig || !authService || !currentUrl || isInIframe || isLoading) {\n return;\n }\n const abortController = new AbortController();\n const onPageLoad = async () => {\n // if we have existing tokens, then validate them and return the session data\n // otherwise check if we have a code in the url and exchange it for tokens\n // if we have neither, return undefined\n const existingSessionData = await authService.validateExistingSession();\n if (existingSessionData.authenticated) {\n setSession(existingSessionData);\n return;\n }\n if (\n abortController.signal.aborted ||\n !new URL(currentUrl).searchParams.get(\"code\")\n ) {\n return;\n }\n await doTokenExchange(currentUrl);\n };\n onPageLoad();\n return () => {\n abortController.abort();\n };\n }, [\n authConfig,\n authService,\n currentUrl,\n doTokenExchange,\n isInIframe,\n isLoading,\n isWindowFocused,\n session?.authenticated,\n ]);\n\n const value = useMemo(\n () => ({\n data: session,\n error,\n isLoading,\n doTokenExchange: authService ? doTokenExchange : null,\n }),\n [session, error, isLoading, authService, doTokenExchange],\n );\n\n return (\n <ClientTokenExchangeSessionContext.Provider value={value}>\n {children}\n </ClientTokenExchangeSessionContext.Provider>\n );\n};\n\nexport type { ClientTokenExchangeSessionContextType as SessionContextType };\nexport {\n ClientTokenExchangeSessionProvider,\n ClientTokenExchangeSessionContext,\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/server/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IACnD,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/server/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IACnD,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/server/config.ts"],"names":[],"mappings":"","sourcesContent":["import type { Endpoints } from \"@/types.ts\";\n\nexport type AuthConfig = {\n clientId: string;\n redirectUrl: string;\n oauthServer?: string;\n challengeUrl?: string;\n endpointOverrides?: Partial<Endpoints> | undefined;\n postLogoutRedirectUrl?: string;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/server/config.ts"],"names":[],"mappings":"","sourcesContent":["import type { Endpoints } from \"@/types.ts\";\n\nexport type AuthConfig = {\n clientId: string;\n redirectUrl: string;\n oauthServer?: string;\n challengeUrl?: string;\n refreshUrl?: string;\n endpointOverrides?: Partial<Endpoints> | undefined;\n postLogoutRedirectUrl?: string;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../src/server/refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../src/server/refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAErE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,qBAAqB,CAAC,CAWhC"}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.refreshTokens = refreshTokens;
|
|
4
4
|
const constants_js_1 = require("../constants.js");
|
|
5
|
-
const
|
|
5
|
+
const AuthenticationRefresherImpl_js_1 = require("../shared/lib/AuthenticationRefresherImpl.js");
|
|
6
6
|
/**
|
|
7
7
|
* Refresh the current set of OIDC tokens
|
|
8
8
|
*/
|
|
9
9
|
async function refreshTokens(storage, config) {
|
|
10
|
-
const refresher = await
|
|
10
|
+
const refresher = await AuthenticationRefresherImpl_js_1.AuthenticationRefresherImpl.build({
|
|
11
11
|
...config,
|
|
12
12
|
oauthServer: config.oauthServer ?? constants_js_1.DEFAULT_AUTH_SERVER,
|
|
13
13
|
}, storage, config.endpointOverrides);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../../src/server/refresh.ts"],"names":[],"mappings":";;AAQA,sCAcC;AArBD,iDAAqD;
|
|
1
|
+
{"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../../src/server/refresh.ts"],"names":[],"mappings":";;AAQA,sCAcC;AArBD,iDAAqD;AAErD,gGAA0F;AAE1F;;GAEG;AACI,KAAK,UAAU,aAAa,CACjC,OAAoB,EACpB,MAAkB;IAElB,MAAM,SAAS,GAAG,MAAM,4DAA2B,CAAC,KAAK,CACvD;QACE,GAAG,MAAM;QACT,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,kCAAmB;KACvD,EACD,OAAO,EACP,MAAM,CAAC,iBAAiB,CACzB,CAAC;IAEF,OAAO,SAAS,CAAC,aAAa,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import type { AuthStorage, OIDCTokenResponseBody } from \"@/types.js\";\nimport { DEFAULT_AUTH_SERVER } from \"@/constants.js\";\nimport type { AuthConfig } from \"@/server/config.ts\";\nimport { AuthenticationRefresherImpl } from \"@/shared/lib/AuthenticationRefresherImpl.js\";\n\n/**\n * Refresh the current set of OIDC tokens\n */\nexport async function refreshTokens(\n storage: AuthStorage,\n config: AuthConfig,\n): Promise<OIDCTokenResponseBody> {\n const refresher = await AuthenticationRefresherImpl.build(\n {\n ...config,\n oauthServer: config.oauthServer ?? DEFAULT_AUTH_SERVER,\n },\n storage,\n config.endpointOverrides,\n );\n\n return refresher.refreshTokens();\n}\n"]}
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import type { DisplayMode, Endpoints, OIDCTokenResponseBody, SessionData } from "../types.js";
|
|
2
2
|
import { BrowserPublicClientPKCEProducer } from "../services/PKCE.js";
|
|
3
3
|
import type { AuthenticationInitiator, AuthenticationResolver, PKCEConsumer } from "../services/types.js";
|
|
4
|
+
export type GenericAuthenticationInitiatorConfig = {
|
|
5
|
+
clientId: string;
|
|
6
|
+
redirectUrl: string;
|
|
7
|
+
state: string;
|
|
8
|
+
scopes: string[];
|
|
9
|
+
oauthServer: string;
|
|
10
|
+
nonce?: string;
|
|
11
|
+
endpointOverrides?: Partial<Endpoints>;
|
|
12
|
+
pkceConsumer: PKCEConsumer;
|
|
13
|
+
};
|
|
14
|
+
export type BrowserAuthenticationInitiatorConfig = Omit<GenericAuthenticationInitiatorConfig, "state"> & {
|
|
15
|
+
logoutUrl?: string;
|
|
16
|
+
logoutRedirectUrl: string;
|
|
17
|
+
displayMode: DisplayMode;
|
|
18
|
+
};
|
|
4
19
|
/**
|
|
5
20
|
* An authentication initiator that works on a browser. Since this is just triggering
|
|
6
21
|
* login and logout, session data is not stored here.
|
|
@@ -24,18 +39,7 @@ import type { AuthenticationInitiator, AuthenticationResolver, PKCEConsumer } fr
|
|
|
24
39
|
*/
|
|
25
40
|
export declare class BrowserAuthenticationInitiator implements AuthenticationInitiator {
|
|
26
41
|
private postMessageHandler;
|
|
27
|
-
protected config:
|
|
28
|
-
clientId: string;
|
|
29
|
-
redirectUrl: string;
|
|
30
|
-
logoutUrl?: string;
|
|
31
|
-
logoutRedirectUrl: string;
|
|
32
|
-
scopes: string[];
|
|
33
|
-
displayMode: DisplayMode;
|
|
34
|
-
oauthServer: string;
|
|
35
|
-
endpointOverrides?: Partial<Endpoints>;
|
|
36
|
-
pkceConsumer: PKCEConsumer;
|
|
37
|
-
nonce?: string;
|
|
38
|
-
};
|
|
42
|
+
protected config: BrowserAuthenticationInitiatorConfig;
|
|
39
43
|
setDisplayMode(displayMode: DisplayMode): void;
|
|
40
44
|
get displayMode(): DisplayMode;
|
|
41
45
|
get isServerTokenExchange(): boolean;
|
|
@@ -52,16 +56,7 @@ export declare class BrowserAuthenticationInitiator implements AuthenticationIni
|
|
|
52
56
|
* that may serve this URL to their front-ends or just call them directly
|
|
53
57
|
*/
|
|
54
58
|
export declare class GenericAuthenticationInitiator implements AuthenticationInitiator {
|
|
55
|
-
protected config:
|
|
56
|
-
clientId: string;
|
|
57
|
-
redirectUrl: string;
|
|
58
|
-
state: string;
|
|
59
|
-
scopes: string[];
|
|
60
|
-
oauthServer: string;
|
|
61
|
-
nonce?: string;
|
|
62
|
-
endpointOverrides?: Partial<Endpoints>;
|
|
63
|
-
pkceConsumer: PKCEConsumer;
|
|
64
|
-
};
|
|
59
|
+
protected config: GenericAuthenticationInitiatorConfig;
|
|
65
60
|
constructor(config: typeof this.config);
|
|
66
61
|
signIn(): Promise<URL>;
|
|
67
62
|
signOut(idToken: string): Promise<URL>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationService.d.ts","sourceRoot":"","sources":["../../../src/services/AuthenticationService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAET,qBAAqB,EACrB,WAAW,EACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,+BAA+B,EAEhC,MAAM,oBAAoB,CAAC;AAe5B,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,YAAY,EACb,MAAM,qBAAqB,CAAC;AAQ7B
|
|
1
|
+
{"version":3,"file":"AuthenticationService.d.ts","sourceRoot":"","sources":["../../../src/services/AuthenticationService.ts"],"names":[],"mappings":"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"}
|