@civic/auth 0.0.1-beta.0 → 0.0.1-beta.1
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 +10 -10
- package/dist/index-DFVNodC9.d.mts +66 -0
- package/dist/index-DFVNodC9.d.ts +66 -0
- package/dist/index.css +5 -5
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/nextjs.d.mts +235 -4
- package/dist/nextjs.d.ts +235 -4
- package/dist/nextjs.js +848 -42
- package/dist/nextjs.js.map +1 -1
- package/dist/nextjs.mjs +832 -43
- package/dist/nextjs.mjs.map +1 -1
- package/dist/react.d.mts +71 -19
- package/dist/react.d.ts +71 -19
- package/dist/react.js +599 -300
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +588 -293
- package/dist/react.mjs.map +1 -1
- package/package.json +22 -18
- package/dist/index-yT0eVchS.d.mts +0 -52
- package/dist/index-yT0eVchS.d.ts +0 -52
package/dist/nextjs.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
"use server";
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defProps = Object.defineProperties;
|
|
4
4
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
@@ -39,61 +39,850 @@ var __async = (__this, __arguments, generator) => {
|
|
|
39
39
|
});
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
// src/
|
|
43
|
-
import
|
|
44
|
-
|
|
45
|
-
var
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
// src/lib/logger.ts
|
|
43
|
+
import debug from "debug";
|
|
44
|
+
var PACKAGE_NAME = "@civic/auth";
|
|
45
|
+
var DebugLogger = class {
|
|
46
|
+
constructor(namespace) {
|
|
47
|
+
this.debugLogger = debug(`${PACKAGE_NAME}:${namespace}:debug`);
|
|
48
|
+
this.infoLogger = debug(`${PACKAGE_NAME}:${namespace}:info`);
|
|
49
|
+
this.warnLogger = debug(`${PACKAGE_NAME}:${namespace}:warn`);
|
|
50
|
+
this.errorLogger = debug(`${PACKAGE_NAME}:${namespace}:error`);
|
|
51
|
+
this.debugLogger.color = "4";
|
|
52
|
+
this.infoLogger.color = "2";
|
|
53
|
+
this.warnLogger.color = "3";
|
|
54
|
+
this.errorLogger.color = "1";
|
|
55
|
+
}
|
|
56
|
+
debug(message, ...args) {
|
|
57
|
+
this.debugLogger(message, ...args);
|
|
58
|
+
}
|
|
59
|
+
info(message, ...args) {
|
|
60
|
+
this.infoLogger(message, ...args);
|
|
61
|
+
}
|
|
62
|
+
warn(message, ...args) {
|
|
63
|
+
this.warnLogger(message, ...args);
|
|
64
|
+
}
|
|
65
|
+
error(message, ...args) {
|
|
66
|
+
this.errorLogger(message, ...args);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var createLogger = (namespace) => new DebugLogger(namespace);
|
|
70
|
+
var loggers = {
|
|
71
|
+
// Next.js specific loggers
|
|
72
|
+
nextjs: {
|
|
73
|
+
routes: createLogger("api:routes"),
|
|
74
|
+
middleware: createLogger("api:middleware"),
|
|
75
|
+
handlers: {
|
|
76
|
+
auth: createLogger("api:handlers:auth")
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
// React specific loggers
|
|
80
|
+
react: {
|
|
81
|
+
components: createLogger("react:components"),
|
|
82
|
+
hooks: createLogger("react:hooks"),
|
|
83
|
+
context: createLogger("react:context")
|
|
84
|
+
},
|
|
85
|
+
// Shared utilities loggers
|
|
86
|
+
services: {
|
|
87
|
+
validation: createLogger("utils:validation"),
|
|
88
|
+
network: createLogger("utils:network")
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// src/nextjs/config.ts
|
|
93
|
+
var logger = loggers.nextjs.handlers.auth;
|
|
94
|
+
var defaultAuthConfig = {
|
|
95
|
+
oauthServer: "https://auth-dev.civic.com/oauth",
|
|
96
|
+
callbackUrl: "/api/auth/callback",
|
|
97
|
+
challengeUrl: "/api/auth/challenge",
|
|
98
|
+
logoutUrl: "/api/auth/logout",
|
|
99
|
+
loginUrl: "/",
|
|
100
|
+
include: ["/*"],
|
|
101
|
+
exclude: [],
|
|
102
|
+
cookies: {
|
|
103
|
+
tokens: {
|
|
104
|
+
sameSite: "strict",
|
|
105
|
+
path: "/",
|
|
106
|
+
maxAge: 60 * 60
|
|
107
|
+
// 1 hour
|
|
108
|
+
},
|
|
109
|
+
user: {
|
|
110
|
+
sameSite: "strict",
|
|
111
|
+
path: "/",
|
|
112
|
+
maxAge: 60 * 60
|
|
113
|
+
// 1 hour
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
var withoutUndefined = (obj) => {
|
|
118
|
+
const result = {};
|
|
119
|
+
for (const key in obj) {
|
|
120
|
+
if (obj[key] !== void 0) {
|
|
121
|
+
result[key] = obj[key];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
};
|
|
126
|
+
var resolveAuthConfig = (config = {}) => {
|
|
127
|
+
var _a, _b, _c, _d;
|
|
128
|
+
const configFromEnv = withoutUndefined({
|
|
129
|
+
clientId: process.env._civic_auth_client_id,
|
|
130
|
+
oauthServer: process.env._civic_oauth_server,
|
|
131
|
+
callbackUrl: process.env._civic_auth_callback_url,
|
|
132
|
+
loginUrl: process.env._civic_auth_login_url,
|
|
133
|
+
logoutUrl: process.env._civic_auth_logout_url,
|
|
134
|
+
include: (_a = process.env._civic_auth_includes) == null ? void 0 : _a.split(","),
|
|
135
|
+
exclude: (_b = process.env._civic_auth_excludes) == null ? void 0 : _b.split(","),
|
|
136
|
+
cookies: process.env._civic_auth_cookie_config ? JSON.parse(process.env._civic_auth_cookie_config) : void 0
|
|
137
|
+
});
|
|
138
|
+
const mergedConfig = __spreadProps(__spreadValues(__spreadValues(__spreadValues({}, defaultAuthConfig), configFromEnv), config), {
|
|
139
|
+
// Override with directly passed config
|
|
140
|
+
cookies: {
|
|
141
|
+
tokens: __spreadValues(__spreadValues({}, defaultAuthConfig.cookies.tokens), ((_c = config.cookies) == null ? void 0 : _c.tokens) || {}),
|
|
142
|
+
user: __spreadValues(__spreadValues({}, defaultAuthConfig.cookies.user), ((_d = config.cookies) == null ? void 0 : _d.user) || {})
|
|
143
|
+
}
|
|
53
144
|
});
|
|
54
|
-
|
|
55
|
-
|
|
145
|
+
logger.debug("Config from environment:", configFromEnv);
|
|
146
|
+
logger.debug("Resolved config:", mergedConfig);
|
|
147
|
+
if (mergedConfig.clientId === void 0) {
|
|
148
|
+
throw new Error("Civic Auth client ID is required");
|
|
56
149
|
}
|
|
150
|
+
return mergedConfig;
|
|
57
151
|
};
|
|
58
|
-
var
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
152
|
+
var createCivicAuthPlugin = (clientId, authConfig = {}) => {
|
|
153
|
+
return (nextConfig) => {
|
|
154
|
+
const resolvedConfig = resolveAuthConfig(__spreadProps(__spreadValues({}, authConfig), { clientId }));
|
|
155
|
+
return __spreadProps(__spreadValues({}, nextConfig), {
|
|
156
|
+
env: __spreadProps(__spreadValues({}, nextConfig == null ? void 0 : nextConfig.env), {
|
|
157
|
+
// Internal environment variables - do not set these manually
|
|
158
|
+
_civic_auth_client_id: clientId,
|
|
159
|
+
_civic_oauth_server: resolvedConfig.oauthServer,
|
|
160
|
+
_civic_auth_callback_url: resolvedConfig.callbackUrl,
|
|
161
|
+
_civic_auth_login_url: resolvedConfig.loginUrl,
|
|
162
|
+
_civic_auth_logout_url: resolvedConfig.logoutUrl,
|
|
163
|
+
_civic_auth_includes: resolvedConfig.include.join(","),
|
|
164
|
+
_civic_auth_excludes: resolvedConfig.exclude.join(","),
|
|
165
|
+
_civic_auth_cookie_config: JSON.stringify(resolvedConfig.cookies)
|
|
166
|
+
})
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// src/nextjs/routeHandler.ts
|
|
172
|
+
import { NextResponse } from "next/server.js";
|
|
173
|
+
import { revalidatePath } from "next/cache.js";
|
|
174
|
+
|
|
175
|
+
// src/nextjs/NextJSSessionService.ts
|
|
176
|
+
import { cookies } from "next/headers.js";
|
|
177
|
+
|
|
178
|
+
// src/services/UserInfoService.ts
|
|
179
|
+
import { parseJWT } from "oslo/jwt";
|
|
180
|
+
var UserInfoServiceImpl = class {
|
|
181
|
+
constructor(endpoints) {
|
|
182
|
+
this.endpoints = endpoints;
|
|
183
|
+
}
|
|
184
|
+
extractUserFromIdToken(idToken) {
|
|
185
|
+
const parsedJWT = parseJWT(idToken);
|
|
186
|
+
if (!parsedJWT) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
return parsedJWT.payload;
|
|
190
|
+
}
|
|
191
|
+
getUserInfo(accessToken, idToken) {
|
|
192
|
+
return __async(this, null, function* () {
|
|
193
|
+
if (idToken) {
|
|
194
|
+
return this.extractUserFromIdToken(idToken);
|
|
195
|
+
}
|
|
196
|
+
const userInfo = yield fetch(this.endpoints.userinfo, {
|
|
197
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
198
|
+
});
|
|
199
|
+
return userInfo.json();
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// src/services/SessionService.ts
|
|
205
|
+
import { OAuth2Client, generateCodeVerifier } from "oslo/oauth2";
|
|
206
|
+
import * as jose from "jose";
|
|
207
|
+
|
|
208
|
+
// src/lib/oauth.ts
|
|
209
|
+
import { v4 as uuid } from "uuid";
|
|
210
|
+
var getIssuerVariations = (issuer) => {
|
|
211
|
+
const issuerWithoutSlash = issuer.endsWith("/") ? issuer.slice(0, issuer.length - 1) : issuer;
|
|
212
|
+
const issuerWithSlash = `${issuerWithoutSlash}/`;
|
|
213
|
+
return [issuerWithoutSlash, issuerWithSlash];
|
|
214
|
+
};
|
|
215
|
+
var addSlashIfNeeded = (url) => url.endsWith("/") ? url : `${url}/`;
|
|
216
|
+
var getOauthEndpoints = (oauthServer) => __async(void 0, null, function* () {
|
|
217
|
+
const openIdConfigResponse = yield fetch(
|
|
218
|
+
`${addSlashIfNeeded(oauthServer)}.well-known/openid-configuration`
|
|
219
|
+
);
|
|
220
|
+
const openIdConfig = yield openIdConfigResponse.json();
|
|
221
|
+
return {
|
|
222
|
+
jwks: openIdConfig.jwks_uri,
|
|
223
|
+
auth: openIdConfig.authorization_endpoint,
|
|
224
|
+
token: openIdConfig.token_endpoint,
|
|
225
|
+
userinfo: openIdConfig.userinfo_endpoint
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
var generateState = (displayMode) => {
|
|
229
|
+
const jsonString = JSON.stringify({
|
|
230
|
+
uuid: uuid(),
|
|
231
|
+
displayMode
|
|
232
|
+
});
|
|
233
|
+
return btoa(jsonString);
|
|
234
|
+
};
|
|
235
|
+
var displayModeFromState = (state, sessionDisplayMode) => {
|
|
236
|
+
try {
|
|
237
|
+
const jsonString = btoa(state);
|
|
238
|
+
return JSON.parse(jsonString).displayMode;
|
|
239
|
+
} catch (e) {
|
|
240
|
+
console.error("Failed to parse displayMode from state:", e);
|
|
241
|
+
return sessionDisplayMode;
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// src/utils.ts
|
|
246
|
+
import { clsx } from "clsx";
|
|
247
|
+
import { twMerge } from "tailwind-merge";
|
|
248
|
+
var isPopupBlocked = () => {
|
|
249
|
+
const popup = window.open("", "", "width=1,height=1");
|
|
250
|
+
if (!popup) {
|
|
251
|
+
return true;
|
|
63
252
|
}
|
|
64
253
|
try {
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
254
|
+
if (typeof popup.closed === "undefined") {
|
|
255
|
+
throw new Error("Popup is blocked");
|
|
256
|
+
}
|
|
257
|
+
} catch (e) {
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
popup.close();
|
|
261
|
+
return false;
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// src/services/SessionService.ts
|
|
265
|
+
var AuthSessionServiceImpl = class {
|
|
266
|
+
constructor(clientId, redirectUrl, oauthServer, inputEndpoints) {
|
|
267
|
+
this.clientId = clientId;
|
|
268
|
+
this.redirectUrl = redirectUrl;
|
|
269
|
+
this.oauthServer = oauthServer;
|
|
270
|
+
this.inputEndpoints = inputEndpoints;
|
|
271
|
+
this.codeVerifier = void 0;
|
|
272
|
+
this.refreshTokenTimeout = null;
|
|
273
|
+
this.codeVerifier = this.getCodeVerifier();
|
|
274
|
+
this.endpoints = inputEndpoints;
|
|
275
|
+
}
|
|
276
|
+
getCodeVerifier() {
|
|
277
|
+
return generateCodeVerifier();
|
|
278
|
+
}
|
|
279
|
+
getUserInfoService() {
|
|
280
|
+
return __async(this, null, function* () {
|
|
281
|
+
if (this.userInfoService) {
|
|
282
|
+
return this.userInfoService;
|
|
283
|
+
}
|
|
284
|
+
const endpoints = yield this.getEndpoints();
|
|
285
|
+
this.userInfoService = new UserInfoServiceImpl(endpoints);
|
|
286
|
+
return this.userInfoService;
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
getEndpoints() {
|
|
290
|
+
return __async(this, null, function* () {
|
|
291
|
+
var _a;
|
|
292
|
+
if ((_a = this.endpoints) == null ? void 0 : _a.auth) {
|
|
293
|
+
return this.endpoints;
|
|
294
|
+
}
|
|
295
|
+
const jwksEndpoints = yield getOauthEndpoints(this.oauthServer);
|
|
296
|
+
return this.endpoints ? __spreadValues(__spreadValues({}, this.endpoints), jwksEndpoints) : jwksEndpoints;
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
getOauth2Client() {
|
|
300
|
+
return __async(this, null, function* () {
|
|
301
|
+
if (this.oauth2Client) {
|
|
302
|
+
return this.oauth2Client;
|
|
303
|
+
}
|
|
304
|
+
const endpoints = yield this.getEndpoints();
|
|
305
|
+
this.oauth2Client = new OAuth2Client(
|
|
306
|
+
this.clientId,
|
|
307
|
+
endpoints.auth,
|
|
308
|
+
endpoints.token,
|
|
309
|
+
// this
|
|
310
|
+
{ redirectURI: this.redirectUrl }
|
|
311
|
+
);
|
|
312
|
+
return this.oauth2Client;
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
getSessionData() {
|
|
316
|
+
return JSON.parse(
|
|
317
|
+
localStorage.getItem(`civic-auth:${this.clientId}`) || "{}"
|
|
69
318
|
);
|
|
70
|
-
|
|
71
|
-
|
|
319
|
+
}
|
|
320
|
+
updateSessionData(data) {
|
|
321
|
+
localStorage.setItem(
|
|
322
|
+
`civic-auth:${this.clientId}`,
|
|
323
|
+
JSON.stringify(__spreadValues({}, data))
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
getUser() {
|
|
327
|
+
return JSON.parse(
|
|
328
|
+
localStorage.getItem(`civic-auth:${this.clientId}:user`) || "{}"
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
setUser(data) {
|
|
332
|
+
localStorage.setItem(
|
|
333
|
+
`civic-auth:${this.clientId}:user`,
|
|
334
|
+
JSON.stringify(data === null ? {} : data)
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
clearSessionData() {
|
|
338
|
+
localStorage.setItem(`civic-auth:${this.clientId}`, JSON.stringify({}));
|
|
339
|
+
}
|
|
340
|
+
getAuthorizationUrlWithChallenge(state, scopes) {
|
|
341
|
+
return __async(this, null, function* () {
|
|
342
|
+
var _a;
|
|
343
|
+
const oauth2Client = yield this.getOauth2Client();
|
|
344
|
+
if ((_a = this.endpoints) == null ? void 0 : _a.challenge) {
|
|
345
|
+
const challenge = yield fetch(this.endpoints.challenge).then(
|
|
346
|
+
(res) => res.json().then((data) => data.challenge)
|
|
347
|
+
);
|
|
348
|
+
const oAuthUrl2 = yield oauth2Client.createAuthorizationURL({
|
|
349
|
+
state,
|
|
350
|
+
scopes
|
|
351
|
+
});
|
|
352
|
+
oAuthUrl2.searchParams.append("code_challenge", challenge);
|
|
353
|
+
oAuthUrl2.searchParams.append("code_challenge_method", "S256");
|
|
354
|
+
return oAuthUrl2;
|
|
355
|
+
}
|
|
356
|
+
const oAuthUrl = yield oauth2Client.createAuthorizationURL({
|
|
357
|
+
state,
|
|
358
|
+
codeVerifier: this.codeVerifier,
|
|
359
|
+
codeChallengeMethod: "S256",
|
|
360
|
+
scopes
|
|
361
|
+
});
|
|
362
|
+
return oAuthUrl;
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
getAuthorizationUrl(scopes, displayMode, nonce) {
|
|
366
|
+
return __async(this, null, function* () {
|
|
367
|
+
const state = generateState(displayMode);
|
|
368
|
+
const existingSessionData = this.getSessionData();
|
|
369
|
+
this.updateSessionData(__spreadProps(__spreadValues({}, existingSessionData), {
|
|
370
|
+
codeVerifier: this.codeVerifier,
|
|
371
|
+
displayMode
|
|
372
|
+
}));
|
|
373
|
+
const oAuthUrl = yield this.getAuthorizationUrlWithChallenge(state, scopes);
|
|
374
|
+
if (nonce) {
|
|
375
|
+
oAuthUrl.searchParams.append("nonce", nonce);
|
|
376
|
+
}
|
|
377
|
+
oAuthUrl.searchParams.append("prompt", "consent");
|
|
378
|
+
return oAuthUrl.toString();
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
// TODO fix the Window reference
|
|
382
|
+
loadAuthorizationUrl(authorizationURL, displayMode) {
|
|
383
|
+
switch (displayMode) {
|
|
384
|
+
case "iframe":
|
|
385
|
+
break;
|
|
386
|
+
case "redirect":
|
|
387
|
+
window.location.href = authorizationURL;
|
|
388
|
+
break;
|
|
389
|
+
case "new_tab":
|
|
390
|
+
window.open(authorizationURL, "_blank");
|
|
391
|
+
break;
|
|
392
|
+
case "custom_tab":
|
|
393
|
+
break;
|
|
72
394
|
}
|
|
73
|
-
|
|
74
|
-
|
|
395
|
+
}
|
|
396
|
+
init() {
|
|
397
|
+
return __async(this, null, function* () {
|
|
398
|
+
this.updateSessionData({ authenticated: false });
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
determineDisplayMode(displayMode) {
|
|
402
|
+
if (isPopupBlocked() && displayMode === "iframe") {
|
|
403
|
+
displayMode = "redirect";
|
|
404
|
+
}
|
|
405
|
+
return displayMode;
|
|
406
|
+
}
|
|
407
|
+
signIn(displayMode, scopes, nonce) {
|
|
408
|
+
return __async(this, null, function* () {
|
|
409
|
+
const authorizationURL = yield this.getAuthorizationUrl(
|
|
410
|
+
scopes,
|
|
411
|
+
displayMode,
|
|
412
|
+
nonce
|
|
413
|
+
);
|
|
414
|
+
this.loadAuthorizationUrl(authorizationURL, displayMode);
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
tokenExchange(responseUrl) {
|
|
418
|
+
return __async(this, null, function* () {
|
|
419
|
+
let session = this.getSessionData();
|
|
420
|
+
if (!session.authenticated) {
|
|
421
|
+
const url = new URL(responseUrl);
|
|
422
|
+
const authorizationCode = url.searchParams.get("code");
|
|
423
|
+
const returnedState = url.searchParams.get("state");
|
|
424
|
+
if (!authorizationCode || !returnedState) {
|
|
425
|
+
throw new Error("Invalid authorization response");
|
|
426
|
+
}
|
|
427
|
+
const codeVerifier = session.codeVerifier;
|
|
428
|
+
const oauth2Client = yield this.getOauth2Client();
|
|
429
|
+
const tokens = yield oauth2Client.validateAuthorizationCode(
|
|
430
|
+
authorizationCode,
|
|
431
|
+
{
|
|
432
|
+
codeVerifier
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
try {
|
|
436
|
+
yield this.validateTokens(tokens);
|
|
437
|
+
} catch (error) {
|
|
438
|
+
console.error("tokenExchange tokens", { error, tokens });
|
|
439
|
+
throw new Error(
|
|
440
|
+
`OIDC tokens validation failed: ${error.message}`
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
const parsedDisplayMode = displayModeFromState(
|
|
444
|
+
returnedState,
|
|
445
|
+
session.displayMode
|
|
446
|
+
);
|
|
447
|
+
session = __spreadProps(__spreadValues({}, session), {
|
|
448
|
+
displayMode: parsedDisplayMode,
|
|
449
|
+
idToken: tokens.id_token,
|
|
450
|
+
authenticated: true,
|
|
451
|
+
state: returnedState,
|
|
452
|
+
accessToken: tokens.access_token,
|
|
453
|
+
refreshToken: tokens.refresh_token,
|
|
454
|
+
timestamp: Date.now(),
|
|
455
|
+
expiresIn: tokens.expires_in
|
|
456
|
+
});
|
|
457
|
+
this.updateSessionData(session);
|
|
458
|
+
const user = yield (yield this.getUserInfoService()).getUserInfo(tokens.access_token, tokens.id_token || null);
|
|
459
|
+
this.setUser(user);
|
|
460
|
+
}
|
|
461
|
+
this.setupTokenRefresh(session);
|
|
462
|
+
if (session.displayMode === "new_tab") {
|
|
463
|
+
window.close();
|
|
464
|
+
} else if (session.displayMode === "redirect") {
|
|
465
|
+
}
|
|
466
|
+
return session;
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
setupTokenRefresh(session) {
|
|
470
|
+
if (this.refreshTokenTimeout) {
|
|
471
|
+
clearTimeout(this.refreshTokenTimeout);
|
|
75
472
|
}
|
|
76
|
-
if (
|
|
77
|
-
|
|
473
|
+
if (session.expiresIn) {
|
|
474
|
+
const elapsedTime = Date.now() - (session.timestamp || 0);
|
|
475
|
+
const remainingTime = session.expiresIn * 1e3 - elapsedTime;
|
|
476
|
+
const refreshTime = Math.max(0, remainingTime - 6e4);
|
|
477
|
+
this.refreshTokenTimeout = setTimeout(() => {
|
|
478
|
+
this.refreshToken().then((newSession) => {
|
|
479
|
+
console.log("Token refreshed successfully", newSession);
|
|
480
|
+
}).catch((error) => {
|
|
481
|
+
console.error("Failed to refresh token:", error);
|
|
482
|
+
this.updateSessionData({});
|
|
483
|
+
});
|
|
484
|
+
}, refreshTime);
|
|
78
485
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
486
|
+
}
|
|
487
|
+
refreshToken() {
|
|
488
|
+
return __async(this, null, function* () {
|
|
489
|
+
const sessionData = this.getSessionData();
|
|
490
|
+
if (!sessionData.refreshToken) {
|
|
491
|
+
throw new Error("No refresh token available");
|
|
492
|
+
}
|
|
493
|
+
const oauth2Client = yield this.getOauth2Client();
|
|
494
|
+
const tokens = yield oauth2Client.refreshAccessToken(
|
|
495
|
+
sessionData.refreshToken
|
|
496
|
+
);
|
|
497
|
+
const session = __spreadProps(__spreadValues({}, sessionData), {
|
|
498
|
+
idToken: tokens.id_token,
|
|
499
|
+
authenticated: true,
|
|
500
|
+
accessToken: tokens.access_token,
|
|
501
|
+
refreshToken: tokens.refresh_token,
|
|
502
|
+
timestamp: Date.now(),
|
|
503
|
+
expiresIn: tokens.expires_in
|
|
504
|
+
});
|
|
505
|
+
this.updateSessionData(session);
|
|
506
|
+
this.setupTokenRefresh(session);
|
|
507
|
+
return session;
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
getUserInfo() {
|
|
511
|
+
return __async(this, null, function* () {
|
|
512
|
+
const sessionData = this.getSessionData();
|
|
513
|
+
if (!sessionData.accessToken) {
|
|
514
|
+
throw new Error("No access token available");
|
|
515
|
+
}
|
|
516
|
+
const userInfoService = yield this.getUserInfoService();
|
|
517
|
+
return userInfoService.getUserInfo(
|
|
518
|
+
sessionData.accessToken,
|
|
519
|
+
sessionData.idToken || null
|
|
520
|
+
);
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Uses the jose library to validate a JWT token using the OAuth JWKS endpoint
|
|
525
|
+
* @param {string} token
|
|
526
|
+
* @returns {Promise<jose.JWTPayload>}
|
|
527
|
+
* @throws {Error} if the token is invalid
|
|
528
|
+
*/
|
|
529
|
+
validateTokens(tokens) {
|
|
530
|
+
return __async(this, null, function* () {
|
|
531
|
+
const endpoints = yield this.getEndpoints();
|
|
532
|
+
const JWKS = jose.createRemoteJWKSet(new URL(endpoints.jwks));
|
|
533
|
+
const returnPayload = {};
|
|
534
|
+
console.log("issuer", getIssuerVariations(this.oauthServer));
|
|
535
|
+
const idTokenResponse = yield jose.jwtVerify(tokens.id_token, JWKS, {
|
|
536
|
+
issuer: getIssuerVariations(this.oauthServer),
|
|
537
|
+
audience: this.clientId
|
|
538
|
+
});
|
|
539
|
+
returnPayload.idToken = idTokenResponse.payload;
|
|
540
|
+
const accessTokenResponse = yield jose.jwtVerify(
|
|
541
|
+
tokens.access_token,
|
|
542
|
+
JWKS,
|
|
543
|
+
{
|
|
544
|
+
issuer: getIssuerVariations(this.oauthServer)
|
|
545
|
+
}
|
|
546
|
+
);
|
|
547
|
+
returnPayload.accessToken = accessTokenResponse.payload;
|
|
548
|
+
if (tokens.refresh_token) {
|
|
549
|
+
returnPayload.refreshToken = tokens.refresh_token;
|
|
550
|
+
}
|
|
551
|
+
return returnPayload;
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
validateExistingSession() {
|
|
555
|
+
return __async(this, null, function* () {
|
|
556
|
+
const sessionData = this.getSessionData();
|
|
557
|
+
try {
|
|
558
|
+
if (!sessionData.idToken || !sessionData.accessToken) {
|
|
559
|
+
const unAuthenticatedSession = __spreadProps(__spreadValues({}, sessionData), { authenticated: false });
|
|
560
|
+
this.updateSessionData(unAuthenticatedSession);
|
|
561
|
+
return unAuthenticatedSession;
|
|
562
|
+
}
|
|
563
|
+
yield this.validateTokens({
|
|
564
|
+
id_token: sessionData.idToken,
|
|
565
|
+
access_token: sessionData.accessToken,
|
|
566
|
+
refresh_token: sessionData.refreshToken
|
|
567
|
+
});
|
|
568
|
+
sessionData.authenticated = true;
|
|
569
|
+
return sessionData;
|
|
570
|
+
} catch (error) {
|
|
571
|
+
console.warn("Failed to validate existing tokens", error);
|
|
572
|
+
const unAuthenticatedSession = {
|
|
573
|
+
authenticated: false
|
|
574
|
+
};
|
|
575
|
+
this.updateSessionData(unAuthenticatedSession);
|
|
576
|
+
return unAuthenticatedSession;
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
// src/nextjs/cookies.ts
|
|
583
|
+
var createSecureTokenCookies = (response, sessionData, config) => {
|
|
584
|
+
var _a, _b;
|
|
585
|
+
const maxAge = (_a = sessionData.expiresIn) != null ? _a : 3600;
|
|
586
|
+
const cookieOptions = __spreadProps(__spreadValues({}, (_b = config.cookies) == null ? void 0 : _b.tokens), {
|
|
587
|
+
maxAge
|
|
588
|
+
});
|
|
589
|
+
if (sessionData.accessToken) {
|
|
590
|
+
response.cookies.set("access_token", sessionData.accessToken, __spreadProps(__spreadValues({}, cookieOptions), {
|
|
591
|
+
httpOnly: true
|
|
592
|
+
}));
|
|
593
|
+
}
|
|
594
|
+
if (sessionData.idToken) {
|
|
595
|
+
response.cookies.set("id_token", sessionData.idToken, __spreadProps(__spreadValues({}, cookieOptions), {
|
|
596
|
+
httpOnly: true
|
|
597
|
+
}));
|
|
598
|
+
}
|
|
599
|
+
if (sessionData.refreshToken) {
|
|
600
|
+
response.cookies.set("refresh_token", sessionData.refreshToken, __spreadProps(__spreadValues({}, cookieOptions), {
|
|
601
|
+
httpOnly: true
|
|
602
|
+
}));
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
var createUserInfoCookie = (response, user, sessionData, config) => {
|
|
606
|
+
var _a, _b, _c;
|
|
607
|
+
if (!user) {
|
|
608
|
+
response.cookies.set("user", "", __spreadProps(__spreadValues({}, (_a = config.cookies) == null ? void 0 : _a.user), {
|
|
609
|
+
maxAge: 0
|
|
610
|
+
}));
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const maxAge = (_b = sessionData.expiresIn) != null ? _b : 3600;
|
|
614
|
+
const frontendUser = __spreadValues({}, user);
|
|
615
|
+
response.cookies.set("user", JSON.stringify(frontendUser), __spreadProps(__spreadValues({}, (_c = config.cookies) == null ? void 0 : _c.user), {
|
|
616
|
+
maxAge
|
|
617
|
+
}));
|
|
618
|
+
};
|
|
619
|
+
var clearAuthCookies = (response, config) => {
|
|
620
|
+
var _a, _b;
|
|
621
|
+
const clearOptions = __spreadProps(__spreadValues({}, (_a = config.cookies) == null ? void 0 : _a.tokens), {
|
|
622
|
+
maxAge: 0
|
|
623
|
+
});
|
|
624
|
+
response.cookies.set("access_token", "", clearOptions);
|
|
625
|
+
response.cookies.set("id_token", "", clearOptions);
|
|
626
|
+
response.cookies.set("refresh_token", "", clearOptions);
|
|
627
|
+
response.cookies.set("codeVerifier", "", clearOptions);
|
|
628
|
+
response.cookies.set("user", "", __spreadProps(__spreadValues({}, (_b = config.cookies) == null ? void 0 : _b.user), {
|
|
629
|
+
maxAge: 0
|
|
630
|
+
}));
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
// src/nextjs/NextJSSessionService.ts
|
|
634
|
+
var NextJSAuthSessionServiceImpl = class extends AuthSessionServiceImpl {
|
|
635
|
+
constructor(authConfig, request, response, inputEndpoints) {
|
|
636
|
+
super(
|
|
637
|
+
authConfig.clientId,
|
|
638
|
+
authConfig.callbackUrl,
|
|
639
|
+
authConfig.oauthServer,
|
|
640
|
+
inputEndpoints
|
|
641
|
+
);
|
|
642
|
+
this.authConfig = authConfig;
|
|
643
|
+
this.request = request;
|
|
644
|
+
this.response = response;
|
|
645
|
+
this.inputEndpoints = inputEndpoints;
|
|
646
|
+
}
|
|
647
|
+
getCodeVerifier() {
|
|
648
|
+
const codeVerifier = cookies().get("codeVerifier");
|
|
649
|
+
if (!codeVerifier) {
|
|
650
|
+
throw new Error("Code verifier not found in cookies");
|
|
82
651
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
652
|
+
return codeVerifier.value;
|
|
653
|
+
}
|
|
654
|
+
getSessionData() {
|
|
655
|
+
var _a, _b, _c, _d;
|
|
656
|
+
const authenticated = cookies().get("access_token") !== void 0;
|
|
657
|
+
return {
|
|
658
|
+
authenticated,
|
|
659
|
+
codeVerifier: (_a = cookies().get("codeVerifier")) == null ? void 0 : _a.value,
|
|
660
|
+
accessToken: (_b = cookies().get("access_token")) == null ? void 0 : _b.value,
|
|
661
|
+
idToken: (_c = cookies().get("id_token")) == null ? void 0 : _c.value,
|
|
662
|
+
refreshToken: (_d = cookies().get("refresh_token")) == null ? void 0 : _d.value
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
updateSessionData(data) {
|
|
666
|
+
createSecureTokenCookies(
|
|
667
|
+
this.response,
|
|
668
|
+
data,
|
|
669
|
+
this.authConfig
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
getUser() {
|
|
673
|
+
const userCookie = cookies().get("user");
|
|
674
|
+
if (!userCookie) return null;
|
|
675
|
+
return JSON.parse(userCookie.value);
|
|
676
|
+
}
|
|
677
|
+
setUser(user) {
|
|
678
|
+
createUserInfoCookie(
|
|
679
|
+
this.response,
|
|
680
|
+
user,
|
|
681
|
+
{ authenticated: true },
|
|
682
|
+
this.authConfig
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
clearSessionData() {
|
|
686
|
+
clearAuthCookies(this.response, this.authConfig);
|
|
687
|
+
}
|
|
688
|
+
// TODO fix the Window reference
|
|
689
|
+
loadAuthorizationUrl() {
|
|
690
|
+
throw new Error("Not implemented");
|
|
691
|
+
}
|
|
692
|
+
init() {
|
|
693
|
+
return __async(this, null, function* () {
|
|
694
|
+
this.updateSessionData({ authenticated: false });
|
|
90
695
|
});
|
|
91
|
-
} catch (error) {
|
|
92
|
-
console.error("Failed to decode id_token:", error);
|
|
93
|
-
return redirectNoLoops(config.loginUrl, req);
|
|
94
696
|
}
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
// src/nextjs/routeHandler.ts
|
|
700
|
+
import { generateCodeVerifier as generateCodeVerifier2 } from "oslo/oauth2";
|
|
701
|
+
var logger2 = loggers.nextjs.handlers.auth;
|
|
702
|
+
var AuthError = class extends Error {
|
|
703
|
+
constructor(message, status = 401) {
|
|
704
|
+
super(message);
|
|
705
|
+
this.status = status;
|
|
706
|
+
this.name = "AuthError";
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
function generateCodeChallenge(codeVerifier) {
|
|
710
|
+
return __async(this, null, function* () {
|
|
711
|
+
const encoder = new TextEncoder();
|
|
712
|
+
const data = encoder.encode(codeVerifier);
|
|
713
|
+
const digest = yield crypto.subtle.digest("SHA-256", data);
|
|
714
|
+
return btoa(String.fromCharCode(...new Uint8Array(digest))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
function handleChallenge() {
|
|
718
|
+
return __async(this, null, function* () {
|
|
719
|
+
const codeVerifier = generateCodeVerifier2();
|
|
720
|
+
console.log("handleChallenge codeVerifier", codeVerifier);
|
|
721
|
+
const challenge = yield generateCodeChallenge(codeVerifier);
|
|
722
|
+
const response = NextResponse.json({ status: "success", challenge });
|
|
723
|
+
response.cookies.set("codeVerifier", codeVerifier, {
|
|
724
|
+
httpOnly: true,
|
|
725
|
+
secure: true,
|
|
726
|
+
sameSite: "strict"
|
|
727
|
+
});
|
|
728
|
+
return response;
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
function handleCallback(request, config) {
|
|
732
|
+
return __async(this, null, function* () {
|
|
733
|
+
const code = request.nextUrl.searchParams.get("code");
|
|
734
|
+
if (!code) {
|
|
735
|
+
throw new AuthError("Missing authorization code");
|
|
736
|
+
}
|
|
737
|
+
try {
|
|
738
|
+
const response = new NextResponse(`<html></html>`);
|
|
739
|
+
response.headers.set("Content-Type", "text/html; charset=utf-8");
|
|
740
|
+
const resolvedConfigs = resolveAuthConfig(config);
|
|
741
|
+
const callbackUrl = new URL(
|
|
742
|
+
resolvedConfigs == null ? void 0 : resolvedConfigs.callbackUrl,
|
|
743
|
+
request.url
|
|
744
|
+
).toString();
|
|
745
|
+
const authService = getDefaultAuthSessionService(
|
|
746
|
+
__spreadProps(__spreadValues({}, resolvedConfigs), {
|
|
747
|
+
callbackUrl
|
|
748
|
+
}),
|
|
749
|
+
request,
|
|
750
|
+
response
|
|
751
|
+
);
|
|
752
|
+
console.log("handleCallback authService", authService);
|
|
753
|
+
const tokens = yield authService.tokenExchange(request.nextUrl.toString());
|
|
754
|
+
if (!tokens.accessToken) {
|
|
755
|
+
throw new AuthError("Missing access token");
|
|
756
|
+
}
|
|
757
|
+
return response;
|
|
758
|
+
} catch (error) {
|
|
759
|
+
logger2.error("Token exchange failed:", error);
|
|
760
|
+
throw new AuthError("Failed to authenticate user", 401);
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
function handleLogout(request, config) {
|
|
765
|
+
return __async(this, null, function* () {
|
|
766
|
+
var _a;
|
|
767
|
+
const resolvedConfigs = resolveAuthConfig(config);
|
|
768
|
+
const path = (_a = resolvedConfigs.loginUrl) != null ? _a : "/";
|
|
769
|
+
const redirectTarget = new URL(path, request.url).toString();
|
|
770
|
+
const response = NextResponse.redirect(redirectTarget);
|
|
771
|
+
clearAuthCookies(response, resolvedConfigs);
|
|
772
|
+
try {
|
|
773
|
+
revalidatePath(path);
|
|
774
|
+
} catch (error) {
|
|
775
|
+
logger2.warn("Failed to revalidate path after logout:", error);
|
|
776
|
+
}
|
|
777
|
+
return response;
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
var getDefaultAuthSessionService = (authConfig, request, response) => {
|
|
781
|
+
return new NextJSAuthSessionServiceImpl(authConfig, request, response);
|
|
782
|
+
};
|
|
783
|
+
function handler(authConfig = {}) {
|
|
784
|
+
return (request) => __async(this, null, function* () {
|
|
785
|
+
const config = resolveAuthConfig(authConfig);
|
|
786
|
+
try {
|
|
787
|
+
const pathname = request.nextUrl.pathname;
|
|
788
|
+
const pathSegments = pathname.split("/");
|
|
789
|
+
const lastSegment = pathSegments[pathSegments.length - 1];
|
|
790
|
+
switch (lastSegment) {
|
|
791
|
+
case "challenge":
|
|
792
|
+
return yield handleChallenge();
|
|
793
|
+
case "callback":
|
|
794
|
+
return yield handleCallback(request, config);
|
|
795
|
+
case "logout":
|
|
796
|
+
return yield handleLogout(request, config);
|
|
797
|
+
default:
|
|
798
|
+
throw new AuthError(`Invalid auth route: ${pathname}`, 404);
|
|
799
|
+
}
|
|
800
|
+
} catch (error) {
|
|
801
|
+
logger2.error("Auth handler error:", error);
|
|
802
|
+
const status = error instanceof AuthError ? error.status : 500;
|
|
803
|
+
const message = error instanceof Error ? error.message : "Authentication failed";
|
|
804
|
+
const response = NextResponse.json({ error: message }, { status });
|
|
805
|
+
clearAuthCookies(response, config);
|
|
806
|
+
return response;
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// src/nextjs/GetUser.ts
|
|
812
|
+
import { cookies as cookies2 } from "next/headers.js";
|
|
813
|
+
var getUser = () => {
|
|
814
|
+
var _a;
|
|
815
|
+
const user = (_a = cookies2().get("user")) == null ? void 0 : _a.value;
|
|
816
|
+
if (!user) return null;
|
|
817
|
+
return JSON.parse(user);
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
// src/nextjs/middleware.ts
|
|
821
|
+
import { NextResponse as NextResponse2 } from "next/server.js";
|
|
822
|
+
import picomatch from "picomatch";
|
|
823
|
+
var matchGlob = (pathname, globPattern) => {
|
|
824
|
+
const matches = picomatch(globPattern);
|
|
825
|
+
return matches(pathname);
|
|
826
|
+
};
|
|
827
|
+
var matchesGlobs = (pathname, patterns) => patterns.some((pattern) => {
|
|
828
|
+
if (!pattern) return false;
|
|
829
|
+
console.log("matching", {
|
|
830
|
+
pattern,
|
|
831
|
+
pathname,
|
|
832
|
+
match: matchGlob(pathname, pattern)
|
|
833
|
+
});
|
|
834
|
+
return matchGlob(pathname, pattern);
|
|
835
|
+
});
|
|
836
|
+
var applyAuth = (authConfig, request) => __async(void 0, null, function* () {
|
|
837
|
+
const authConfigWithDefaults = resolveAuthConfig(authConfig);
|
|
838
|
+
const isAuthenticated = !!request.cookies.get("id_token");
|
|
839
|
+
if (request.nextUrl.pathname === authConfigWithDefaults.loginUrl) {
|
|
840
|
+
console.log("\u2192 Skipping auth check - this is the login URL");
|
|
841
|
+
return void 0;
|
|
842
|
+
}
|
|
843
|
+
if (!matchesGlobs(request.nextUrl.pathname, authConfigWithDefaults.include)) {
|
|
844
|
+
console.log("\u2192 Skipping auth check - path not in include patterns");
|
|
845
|
+
return void 0;
|
|
846
|
+
}
|
|
847
|
+
if (matchesGlobs(request.nextUrl.pathname, authConfigWithDefaults.exclude)) {
|
|
848
|
+
console.log("\u2192 Skipping auth check - path in exclude patterns");
|
|
849
|
+
return void 0;
|
|
850
|
+
}
|
|
851
|
+
if (!isAuthenticated) {
|
|
852
|
+
console.log("\u2192 No valid token found - redirecting to login");
|
|
853
|
+
const loginUrl = new URL(authConfigWithDefaults.loginUrl, request.url);
|
|
854
|
+
return NextResponse2.redirect(loginUrl);
|
|
855
|
+
}
|
|
856
|
+
console.log("\u2192 Auth check passed");
|
|
857
|
+
return void 0;
|
|
858
|
+
});
|
|
859
|
+
var authMiddleware = (authConfig = defaultAuthConfig) => (request) => __async(void 0, null, function* () {
|
|
860
|
+
const response = yield applyAuth(authConfig, request);
|
|
861
|
+
if (response) return response;
|
|
862
|
+
return NextResponse2.next();
|
|
95
863
|
});
|
|
864
|
+
function withAuth(middleware) {
|
|
865
|
+
return (request) => __async(this, null, function* () {
|
|
866
|
+
const response = yield applyAuth({}, request);
|
|
867
|
+
if (response) return response;
|
|
868
|
+
return middleware(request);
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
function auth(authConfig = {}) {
|
|
872
|
+
return (middleware) => {
|
|
873
|
+
return (request) => __async(this, null, function* () {
|
|
874
|
+
const response = yield applyAuth(authConfig, request);
|
|
875
|
+
if (response) return response;
|
|
876
|
+
return middleware(request);
|
|
877
|
+
});
|
|
878
|
+
};
|
|
879
|
+
}
|
|
96
880
|
export {
|
|
97
|
-
|
|
881
|
+
auth,
|
|
882
|
+
authMiddleware,
|
|
883
|
+
createCivicAuthPlugin,
|
|
884
|
+
getUser,
|
|
885
|
+
handler,
|
|
886
|
+
withAuth
|
|
98
887
|
};
|
|
99
888
|
//# sourceMappingURL=nextjs.mjs.map
|