@civic/auth 0.0.1-beta.1 → 0.0.1-beta.11
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 +26 -0
- package/dist/chunk-CRTRMMJ7.js +59 -0
- package/dist/chunk-CRTRMMJ7.js.map +1 -0
- package/dist/chunk-EAANLFR5.mjs +148 -0
- package/dist/chunk-EAANLFR5.mjs.map +1 -0
- package/dist/chunk-EGFTMH5S.mjs +214 -0
- package/dist/chunk-EGFTMH5S.mjs.map +1 -0
- package/dist/chunk-KCSGIIPA.js +214 -0
- package/dist/chunk-KCSGIIPA.js.map +1 -0
- package/dist/chunk-MVO4UZ2A.js +148 -0
- package/dist/chunk-MVO4UZ2A.js.map +1 -0
- package/dist/chunk-PMDIR5XE.mjs +502 -0
- package/dist/chunk-PMDIR5XE.mjs.map +1 -0
- package/dist/chunk-RGHW4PYM.mjs +59 -0
- package/dist/chunk-RGHW4PYM.mjs.map +1 -0
- package/dist/chunk-YNLXRD5L.js +502 -0
- package/dist/chunk-YNLXRD5L.js.map +1 -0
- package/dist/{index-DFVNodC9.d.mts → index-Bfi0hVMZ.d.mts} +5 -13
- package/dist/{index-DFVNodC9.d.ts → index-Bfi0hVMZ.d.ts} +5 -13
- package/dist/index.css +63 -63
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/nextjs.d.mts +22 -37
- package/dist/nextjs.d.ts +22 -37
- package/dist/nextjs.js +166 -848
- package/dist/nextjs.js.map +1 -1
- package/dist/nextjs.mjs +162 -805
- package/dist/nextjs.mjs.map +1 -1
- package/dist/react.d.mts +42 -58
- package/dist/react.d.ts +42 -58
- package/dist/react.js +668 -1103
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +608 -1005
- package/dist/react.mjs.map +1 -1
- package/dist/server.d.mts +56 -0
- package/dist/server.d.ts +56 -0
- package/dist/server.js +20 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +20 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +28 -18
package/dist/nextjs.mjs
CHANGED
|
@@ -1,824 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
var fulfilled = (value) => {
|
|
24
|
-
try {
|
|
25
|
-
step(generator.next(value));
|
|
26
|
-
} catch (e) {
|
|
27
|
-
reject(e);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
var rejected = (value) => {
|
|
31
|
-
try {
|
|
32
|
-
step(generator.throw(value));
|
|
33
|
-
} catch (e) {
|
|
34
|
-
reject(e);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
38
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
39
|
-
});
|
|
40
|
-
};
|
|
41
|
-
|
|
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
|
-
}
|
|
144
|
-
});
|
|
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");
|
|
149
|
-
}
|
|
150
|
-
return mergedConfig;
|
|
151
|
-
};
|
|
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";
|
|
1
|
+
import {
|
|
2
|
+
createCivicAuthPlugin,
|
|
3
|
+
defaultAuthConfig,
|
|
4
|
+
loggers,
|
|
5
|
+
resolveAuthConfig,
|
|
6
|
+
resolveCallbackUrl
|
|
7
|
+
} from "./chunk-EAANLFR5.mjs";
|
|
8
|
+
import {
|
|
9
|
+
CookieStorage,
|
|
10
|
+
resolveOAuthAccessCode
|
|
11
|
+
} from "./chunk-EGFTMH5S.mjs";
|
|
12
|
+
import {
|
|
13
|
+
GenericPublicClientPKCEProducer,
|
|
14
|
+
GenericUserSession,
|
|
15
|
+
clearTokens,
|
|
16
|
+
getUser
|
|
17
|
+
} from "./chunk-PMDIR5XE.mjs";
|
|
18
|
+
import {
|
|
19
|
+
__async,
|
|
20
|
+
__spreadProps,
|
|
21
|
+
__spreadValues
|
|
22
|
+
} from "./chunk-RGHW4PYM.mjs";
|
|
174
23
|
|
|
175
|
-
// src/nextjs/
|
|
24
|
+
// src/nextjs/cookies.ts
|
|
176
25
|
import { cookies } from "next/headers.js";
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
};
|
|
26
|
+
var clearAuthCookies = () => __async(void 0, null, function* () {
|
|
27
|
+
const cookieStorage = new NextjsCookieStorage();
|
|
28
|
+
clearTokens(cookieStorage);
|
|
29
|
+
const clientStorage = new NextjsClientStorage();
|
|
30
|
+
const userSession = new GenericUserSession(clientStorage);
|
|
31
|
+
userSession.set(null);
|
|
227
32
|
});
|
|
228
|
-
var
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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;
|
|
252
|
-
}
|
|
253
|
-
try {
|
|
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}`) || "{}"
|
|
318
|
-
);
|
|
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;
|
|
394
|
-
}
|
|
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);
|
|
472
|
-
}
|
|
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);
|
|
485
|
-
}
|
|
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), {
|
|
33
|
+
var NextjsCookieStorage = class extends CookieStorage {
|
|
34
|
+
constructor(config = {}) {
|
|
35
|
+
super(__spreadProps(__spreadValues({}, config), {
|
|
36
|
+
secure: true,
|
|
591
37
|
httpOnly: true
|
|
592
38
|
}));
|
|
593
39
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
}));
|
|
40
|
+
get(key) {
|
|
41
|
+
var _a;
|
|
42
|
+
return ((_a = cookies().get(key)) == null ? void 0 : _a.value) || null;
|
|
598
43
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
httpOnly: true
|
|
602
|
-
}));
|
|
44
|
+
set(key, value) {
|
|
45
|
+
cookies().set(key, value, this.settings);
|
|
603
46
|
}
|
|
604
47
|
};
|
|
605
|
-
var
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
48
|
+
var NextjsClientStorage = class extends CookieStorage {
|
|
49
|
+
constructor(config = {}) {
|
|
50
|
+
super(__spreadProps(__spreadValues({}, config), {
|
|
51
|
+
secure: false,
|
|
52
|
+
httpOnly: false
|
|
610
53
|
}));
|
|
611
|
-
return;
|
|
612
54
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
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");
|
|
651
|
-
}
|
|
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 });
|
|
695
|
-
});
|
|
55
|
+
get(key) {
|
|
56
|
+
var _a;
|
|
57
|
+
return ((_a = cookies().get(key)) == null ? void 0 : _a.value) || null;
|
|
696
58
|
}
|
|
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";
|
|
59
|
+
set(key, value) {
|
|
60
|
+
cookies().set(key, value, this.settings);
|
|
707
61
|
}
|
|
708
62
|
};
|
|
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
63
|
|
|
811
64
|
// src/nextjs/GetUser.ts
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
if (!user) return null;
|
|
817
|
-
return JSON.parse(user);
|
|
65
|
+
var getUser2 = () => {
|
|
66
|
+
const clientStorage = new NextjsClientStorage();
|
|
67
|
+
const userSession = new GenericUserSession(clientStorage);
|
|
68
|
+
return userSession.get();
|
|
818
69
|
};
|
|
819
70
|
|
|
820
71
|
// src/nextjs/middleware.ts
|
|
821
|
-
import { NextResponse
|
|
72
|
+
import { NextResponse } from "next/server.js";
|
|
822
73
|
import picomatch from "picomatch";
|
|
823
74
|
var matchGlob = (pathname, globPattern) => {
|
|
824
75
|
const matches = picomatch(globPattern);
|
|
@@ -851,7 +102,7 @@ var applyAuth = (authConfig, request) => __async(void 0, null, function* () {
|
|
|
851
102
|
if (!isAuthenticated) {
|
|
852
103
|
console.log("\u2192 No valid token found - redirecting to login");
|
|
853
104
|
const loginUrl = new URL(authConfigWithDefaults.loginUrl, request.url);
|
|
854
|
-
return
|
|
105
|
+
return NextResponse.redirect(loginUrl);
|
|
855
106
|
}
|
|
856
107
|
console.log("\u2192 Auth check passed");
|
|
857
108
|
return void 0;
|
|
@@ -859,7 +110,7 @@ var applyAuth = (authConfig, request) => __async(void 0, null, function* () {
|
|
|
859
110
|
var authMiddleware = (authConfig = defaultAuthConfig) => (request) => __async(void 0, null, function* () {
|
|
860
111
|
const response = yield applyAuth(authConfig, request);
|
|
861
112
|
if (response) return response;
|
|
862
|
-
return
|
|
113
|
+
return NextResponse.next();
|
|
863
114
|
});
|
|
864
115
|
function withAuth(middleware) {
|
|
865
116
|
return (request) => __async(this, null, function* () {
|
|
@@ -877,11 +128,117 @@ function auth(authConfig = {}) {
|
|
|
877
128
|
});
|
|
878
129
|
};
|
|
879
130
|
}
|
|
131
|
+
|
|
132
|
+
// src/nextjs/routeHandler.ts
|
|
133
|
+
import { NextResponse as NextResponse2 } from "next/server.js";
|
|
134
|
+
import { revalidatePath } from "next/cache.js";
|
|
135
|
+
var logger = loggers.nextjs.handlers.auth;
|
|
136
|
+
var AuthError = class extends Error {
|
|
137
|
+
constructor(message, status = 401) {
|
|
138
|
+
super(message);
|
|
139
|
+
this.status = status;
|
|
140
|
+
this.name = "AuthError";
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
function handleChallenge() {
|
|
144
|
+
return __async(this, null, function* () {
|
|
145
|
+
const cookieStorage = new NextjsCookieStorage();
|
|
146
|
+
const pkceProducer = new GenericPublicClientPKCEProducer(cookieStorage);
|
|
147
|
+
const challenge = yield pkceProducer.getCodeChallenge();
|
|
148
|
+
return NextResponse2.json({ status: "success", challenge });
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function handleCallback(request, config) {
|
|
152
|
+
return __async(this, null, function* () {
|
|
153
|
+
const tokenExchange = request.nextUrl.searchParams.get("tokenExchange");
|
|
154
|
+
if (!tokenExchange) {
|
|
155
|
+
const response2 = new NextResponse2(`<html></html>`);
|
|
156
|
+
response2.headers.set("Content-Type", "text/html; charset=utf-8");
|
|
157
|
+
return response2;
|
|
158
|
+
}
|
|
159
|
+
const code = request.nextUrl.searchParams.get("code");
|
|
160
|
+
const state = request.nextUrl.searchParams.get("state");
|
|
161
|
+
if (!code || !state) throw new AuthError("Bad parameters", 400);
|
|
162
|
+
const cookieStorage = new NextjsCookieStorage();
|
|
163
|
+
const resolvedConfigs = resolveAuthConfig(config);
|
|
164
|
+
const callbackUrl = resolveCallbackUrl(resolvedConfigs, request.url);
|
|
165
|
+
try {
|
|
166
|
+
yield resolveOAuthAccessCode(code, state, cookieStorage, __spreadProps(__spreadValues({}, resolvedConfigs), {
|
|
167
|
+
redirectUrl: callbackUrl
|
|
168
|
+
}));
|
|
169
|
+
} catch (error) {
|
|
170
|
+
logger.error("Token exchange failed:", error);
|
|
171
|
+
throw new AuthError("Failed to authenticate user", 401);
|
|
172
|
+
}
|
|
173
|
+
const user = yield getUser(cookieStorage);
|
|
174
|
+
if (!user) {
|
|
175
|
+
throw new AuthError("Failed to get user info", 401);
|
|
176
|
+
}
|
|
177
|
+
const clientStorage = new NextjsClientStorage();
|
|
178
|
+
const userSession = new GenericUserSession(clientStorage);
|
|
179
|
+
userSession.set(user);
|
|
180
|
+
const response = new NextResponse2(`<html></html>`);
|
|
181
|
+
response.headers.set("Content-Type", "text/html; charset=utf-8");
|
|
182
|
+
return response;
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
var getAbsoluteRedirectPath = (redirectPath, currentBasePath) => {
|
|
186
|
+
if (/^(https?:\/\/|www\.).+/i.test(redirectPath)) {
|
|
187
|
+
return redirectPath;
|
|
188
|
+
}
|
|
189
|
+
return new URL(redirectPath, currentBasePath).href;
|
|
190
|
+
};
|
|
191
|
+
function handleLogout(request, config) {
|
|
192
|
+
return __async(this, null, function* () {
|
|
193
|
+
var _a;
|
|
194
|
+
const resolvedConfigs = resolveAuthConfig(config);
|
|
195
|
+
const defaultRedirectPath = (_a = resolvedConfigs.loginUrl) != null ? _a : "/";
|
|
196
|
+
const redirectTarget = new URL(request.url).searchParams.get("redirect") || defaultRedirectPath;
|
|
197
|
+
const isAbsoluteRedirect = /^(https?:\/\/|www\.).+/i.test(redirectTarget);
|
|
198
|
+
const finalRedirectUrl = getAbsoluteRedirectPath(
|
|
199
|
+
redirectTarget,
|
|
200
|
+
new URL(request.url).origin
|
|
201
|
+
);
|
|
202
|
+
const response = NextResponse2.redirect(finalRedirectUrl);
|
|
203
|
+
clearAuthCookies();
|
|
204
|
+
try {
|
|
205
|
+
revalidatePath(isAbsoluteRedirect ? finalRedirectUrl : redirectTarget);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
logger.warn("Failed to revalidate path after logout:", error);
|
|
208
|
+
}
|
|
209
|
+
return response;
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
var handler = (authConfig = {}) => (request) => __async(void 0, null, function* () {
|
|
213
|
+
const config = resolveAuthConfig(authConfig);
|
|
214
|
+
try {
|
|
215
|
+
const pathname = request.nextUrl.pathname;
|
|
216
|
+
const pathSegments = pathname.split("/");
|
|
217
|
+
const lastSegment = pathSegments[pathSegments.length - 1];
|
|
218
|
+
switch (lastSegment) {
|
|
219
|
+
case "challenge":
|
|
220
|
+
return yield handleChallenge();
|
|
221
|
+
case "callback":
|
|
222
|
+
return yield handleCallback(request, config);
|
|
223
|
+
case "logout":
|
|
224
|
+
return yield handleLogout(request, config);
|
|
225
|
+
default:
|
|
226
|
+
throw new AuthError(`Invalid auth route: ${pathname}`, 404);
|
|
227
|
+
}
|
|
228
|
+
} catch (error) {
|
|
229
|
+
logger.error("Auth handler error:", error);
|
|
230
|
+
const status = error instanceof AuthError ? error.status : 500;
|
|
231
|
+
const message = error instanceof Error ? error.message : "Authentication failed";
|
|
232
|
+
const response = NextResponse2.json({ error: message }, { status });
|
|
233
|
+
clearAuthCookies();
|
|
234
|
+
return response;
|
|
235
|
+
}
|
|
236
|
+
});
|
|
880
237
|
export {
|
|
881
238
|
auth,
|
|
882
239
|
authMiddleware,
|
|
883
240
|
createCivicAuthPlugin,
|
|
884
|
-
getUser,
|
|
241
|
+
getUser2 as getUser,
|
|
885
242
|
handler,
|
|
886
243
|
withAuth
|
|
887
244
|
};
|