@civic/auth 0.0.1-beta.0 → 0.0.1-beta.10
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 +36 -10
- 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-yT0eVchS.d.mts → index-Bfi0hVMZ.d.mts} +14 -8
- package/dist/{index-yT0eVchS.d.ts → index-Bfi0hVMZ.d.ts} +14 -8
- package/dist/index.css +66 -66
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/nextjs.d.mts +220 -4
- package/dist/nextjs.d.ts +220 -4
- package/dist/nextjs.js +228 -104
- package/dist/nextjs.js.map +1 -1
- package/dist/nextjs.mjs +228 -82
- package/dist/nextjs.mjs.map +1 -1
- package/dist/react.d.mts +60 -24
- package/dist/react.d.ts +60 -24
- package/dist/react.js +759 -895
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +726 -828
- 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 +20 -6
package/README.md
CHANGED
|
@@ -33,34 +33,34 @@ First, import the CSS styles in your main application file (e.g., `_app.tsx` for
|
|
|
33
33
|
import "@civic/auth/styles.css";
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
### Setup
|
|
36
|
+
### Setup CivicAuthProvider
|
|
37
37
|
|
|
38
|
-
To use the Civic Auth Client SDK, wrap your application with the `
|
|
38
|
+
To use the Civic Auth Client SDK, wrap your application with the `CivicAuthProvider` component. This will allow the authentication context to be accessible throughout your app.
|
|
39
39
|
|
|
40
40
|
```tsx
|
|
41
|
-
import {
|
|
41
|
+
import { CivicAuthProvider } from "@civic/auth/react";
|
|
42
42
|
|
|
43
43
|
function App({ children }) {
|
|
44
44
|
return (
|
|
45
|
-
<
|
|
45
|
+
<CivicAuthProvider clientId="your-client-id" redirectUrl="https://your-app.com/callback">
|
|
46
46
|
{children}
|
|
47
|
-
</
|
|
47
|
+
</CivicAuthProvider>
|
|
48
48
|
);
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
The only required prop for `
|
|
52
|
+
The only required prop for `CivicAuthProvider` is the `clientId`. By default, the SDK uses Civic's endpoints. If you need to use your own endpoints, you can provide them using the `config` prop. See the advanced configuration section below for more details.
|
|
53
53
|
|
|
54
54
|
### Advanced Configuration
|
|
55
55
|
|
|
56
|
-
If you want to use your own endpoints, you can pass a `config` object to the `
|
|
56
|
+
If you want to use your own endpoints, you can pass a `config` object to the `CivicAuthProvider` as shown below:
|
|
57
57
|
|
|
58
58
|
```tsx
|
|
59
|
-
import {
|
|
59
|
+
import { CivicAuthProvider } from "@civic/auth/react";
|
|
60
60
|
|
|
61
61
|
function App({ children }) {
|
|
62
62
|
return (
|
|
63
|
-
<
|
|
63
|
+
<CivicAuthProvider
|
|
64
64
|
clientId="your-client-id"
|
|
65
65
|
redirectUrl="https://your-app.com/callback"
|
|
66
66
|
config={{
|
|
@@ -72,7 +72,7 @@ function App({ children }) {
|
|
|
72
72
|
}}
|
|
73
73
|
>
|
|
74
74
|
{children}
|
|
75
|
-
</
|
|
75
|
+
</CivicAuthProvider>
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
```
|
|
@@ -118,6 +118,32 @@ function Header() {
|
|
|
118
118
|
}
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
+
### Embedding the login iframe in your page
|
|
122
|
+
|
|
123
|
+
The default displayMode for user login is 'iframe' which will show a modal containing the login page for users, when the `signIn` hook is called. If you want to customize where this page is shown and embed it into your page instead i.e. in the case where you have a landing page and don't want users to have to click on a 'sign-in' button, you can embed the login iframe directly inside your page and it will work just like in the modal, as long as it is a child of a <CivicAuthProvider>. In this mode, the iframe auto-loads the login page.
|
|
124
|
+
|
|
125
|
+
To enable this mode, you need to set the parameter 'modalIframe' to `false` (it defaults to `true` in normal operation).
|
|
126
|
+
|
|
127
|
+
The example below shows the iframe centered inside a div embedded on the page:
|
|
128
|
+
```tsx
|
|
129
|
+
import { CivicAuthProvider } from "@civic/auth/react";
|
|
130
|
+
|
|
131
|
+
function App({ children }) {
|
|
132
|
+
return (
|
|
133
|
+
<CivicAuthProvider
|
|
134
|
+
clientId="your-client-id"
|
|
135
|
+
redirectUrl="https://your-app.com/callback"
|
|
136
|
+
modalIframe={false}
|
|
137
|
+
>
|
|
138
|
+
{children}
|
|
139
|
+
<div className="flex min-h-[200px] items-center justify-center">
|
|
140
|
+
<CivicAuthIframeContainer />
|
|
141
|
+
</div>
|
|
142
|
+
</CivicAuthProvider>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
121
147
|
### Token Management with useToken Hook
|
|
122
148
|
|
|
123
149
|
The `useToken` hook can be used to access and manage tokens within your application. This hook provides the current access and ID tokens, a refresh function, and token loading/error states.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __objRest = (source, exclude) => {
|
|
21
|
+
var target = {};
|
|
22
|
+
for (var prop in source)
|
|
23
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
24
|
+
target[prop] = source[prop];
|
|
25
|
+
if (source != null && __getOwnPropSymbols)
|
|
26
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
27
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
28
|
+
target[prop] = source[prop];
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
};
|
|
32
|
+
var __async = (__this, __arguments, generator) => {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
var fulfilled = (value) => {
|
|
35
|
+
try {
|
|
36
|
+
step(generator.next(value));
|
|
37
|
+
} catch (e) {
|
|
38
|
+
reject(e);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var rejected = (value) => {
|
|
42
|
+
try {
|
|
43
|
+
step(generator.throw(value));
|
|
44
|
+
} catch (e) {
|
|
45
|
+
reject(e);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
49
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
exports.__spreadValues = __spreadValues; exports.__spreadProps = __spreadProps; exports.__objRest = __objRest; exports.__async = __async;
|
|
59
|
+
//# sourceMappingURL=chunk-CRTRMMJ7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevincolgan/code/civic-auth/packages/civic-auth-client/dist/chunk-CRTRMMJ7.js"],"names":[],"mappings":"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","file":"/Users/kevincolgan/code/civic-auth/packages/civic-auth-client/dist/chunk-CRTRMMJ7.js"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {
|
|
2
|
+
withoutUndefined
|
|
3
|
+
} from "./chunk-PMDIR5XE.mjs";
|
|
4
|
+
import {
|
|
5
|
+
__spreadProps,
|
|
6
|
+
__spreadValues
|
|
7
|
+
} from "./chunk-RGHW4PYM.mjs";
|
|
8
|
+
|
|
9
|
+
// src/lib/logger.ts
|
|
10
|
+
import debug from "debug";
|
|
11
|
+
var PACKAGE_NAME = "@civic/auth";
|
|
12
|
+
var DebugLogger = class {
|
|
13
|
+
constructor(namespace) {
|
|
14
|
+
this.debugLogger = debug(`${PACKAGE_NAME}:${namespace}:debug`);
|
|
15
|
+
this.infoLogger = debug(`${PACKAGE_NAME}:${namespace}:info`);
|
|
16
|
+
this.warnLogger = debug(`${PACKAGE_NAME}:${namespace}:warn`);
|
|
17
|
+
this.errorLogger = debug(`${PACKAGE_NAME}:${namespace}:error`);
|
|
18
|
+
this.debugLogger.color = "4";
|
|
19
|
+
this.infoLogger.color = "2";
|
|
20
|
+
this.warnLogger.color = "3";
|
|
21
|
+
this.errorLogger.color = "1";
|
|
22
|
+
}
|
|
23
|
+
debug(message, ...args) {
|
|
24
|
+
this.debugLogger(message, ...args);
|
|
25
|
+
}
|
|
26
|
+
info(message, ...args) {
|
|
27
|
+
this.infoLogger(message, ...args);
|
|
28
|
+
}
|
|
29
|
+
warn(message, ...args) {
|
|
30
|
+
this.warnLogger(message, ...args);
|
|
31
|
+
}
|
|
32
|
+
error(message, ...args) {
|
|
33
|
+
this.errorLogger(message, ...args);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var createLogger = (namespace) => new DebugLogger(namespace);
|
|
37
|
+
var loggers = {
|
|
38
|
+
// Next.js specific loggers
|
|
39
|
+
nextjs: {
|
|
40
|
+
routes: createLogger("api:routes"),
|
|
41
|
+
middleware: createLogger("api:middleware"),
|
|
42
|
+
handlers: {
|
|
43
|
+
auth: createLogger("api:handlers:auth")
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
// React specific loggers
|
|
47
|
+
react: {
|
|
48
|
+
components: createLogger("react:components"),
|
|
49
|
+
hooks: createLogger("react:hooks"),
|
|
50
|
+
context: createLogger("react:context")
|
|
51
|
+
},
|
|
52
|
+
// Shared utilities loggers
|
|
53
|
+
services: {
|
|
54
|
+
validation: createLogger("utils:validation"),
|
|
55
|
+
network: createLogger("utils:network")
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/nextjs/config.ts
|
|
60
|
+
var logger = loggers.nextjs.handlers.auth;
|
|
61
|
+
var defaultAuthConfig = {
|
|
62
|
+
oauthServer: "https://auth-dev.civic.com/oauth",
|
|
63
|
+
callbackUrl: "/api/auth/callback",
|
|
64
|
+
challengeUrl: "/api/auth/challenge",
|
|
65
|
+
logoutUrl: "/api/auth/logout",
|
|
66
|
+
loginUrl: "/",
|
|
67
|
+
include: ["/*"],
|
|
68
|
+
exclude: [],
|
|
69
|
+
cookies: {
|
|
70
|
+
tokens: {
|
|
71
|
+
sameSite: "strict",
|
|
72
|
+
path: "/",
|
|
73
|
+
maxAge: 60 * 60
|
|
74
|
+
// 1 hour
|
|
75
|
+
},
|
|
76
|
+
user: {
|
|
77
|
+
sameSite: "strict",
|
|
78
|
+
path: "/",
|
|
79
|
+
maxAge: 60 * 60
|
|
80
|
+
// 1 hour
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var resolveAuthConfig = (config = {}) => {
|
|
85
|
+
var _a, _b, _c, _d;
|
|
86
|
+
const configFromEnv = withoutUndefined({
|
|
87
|
+
clientId: process.env._civic_auth_client_id,
|
|
88
|
+
oauthServer: process.env._civic_oauth_server,
|
|
89
|
+
callbackUrl: process.env._civic_auth_callback_url,
|
|
90
|
+
challengeUrl: process.env._civic_auth_challenge_url,
|
|
91
|
+
loginUrl: process.env._civic_auth_login_url,
|
|
92
|
+
appUrl: process.env._civic_auth_app_url,
|
|
93
|
+
logoutUrl: process.env._civic_auth_logout_url,
|
|
94
|
+
include: (_a = process.env._civic_auth_includes) == null ? void 0 : _a.split(","),
|
|
95
|
+
exclude: (_b = process.env._civic_auth_excludes) == null ? void 0 : _b.split(","),
|
|
96
|
+
cookies: process.env._civic_auth_cookie_config ? JSON.parse(process.env._civic_auth_cookie_config) : void 0
|
|
97
|
+
});
|
|
98
|
+
const mergedConfig = __spreadProps(__spreadValues(__spreadValues(__spreadValues({}, defaultAuthConfig), configFromEnv), config), {
|
|
99
|
+
// Override with directly passed config
|
|
100
|
+
cookies: {
|
|
101
|
+
tokens: __spreadValues(__spreadValues({}, defaultAuthConfig.cookies.tokens), ((_c = config.cookies) == null ? void 0 : _c.tokens) || {}),
|
|
102
|
+
user: __spreadValues(__spreadValues({}, defaultAuthConfig.cookies.user), ((_d = config.cookies) == null ? void 0 : _d.user) || {})
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
logger.debug("Config from environment:", configFromEnv);
|
|
106
|
+
logger.debug("Resolved config:", mergedConfig);
|
|
107
|
+
if (mergedConfig.clientId === void 0) {
|
|
108
|
+
throw new Error("Civic Auth client ID is required");
|
|
109
|
+
}
|
|
110
|
+
return mergedConfig;
|
|
111
|
+
};
|
|
112
|
+
var createCivicAuthPlugin = (clientId, authConfig = {}) => {
|
|
113
|
+
return (nextConfig) => {
|
|
114
|
+
const resolvedConfig = resolveAuthConfig(__spreadProps(__spreadValues({}, authConfig), { clientId }));
|
|
115
|
+
return __spreadProps(__spreadValues({}, nextConfig), {
|
|
116
|
+
env: __spreadProps(__spreadValues({}, nextConfig == null ? void 0 : nextConfig.env), {
|
|
117
|
+
// Internal environment variables - do not set these manually
|
|
118
|
+
_civic_auth_client_id: clientId,
|
|
119
|
+
_civic_oauth_server: resolvedConfig.oauthServer,
|
|
120
|
+
_civic_auth_callback_url: resolvedConfig.callbackUrl,
|
|
121
|
+
_civic_auth_challenge_url: resolvedConfig.challengeUrl,
|
|
122
|
+
_civic_auth_login_url: resolvedConfig.loginUrl,
|
|
123
|
+
_civic_auth_logout_url: resolvedConfig.logoutUrl,
|
|
124
|
+
_civic_auth_app_url: resolvedConfig.appUrl,
|
|
125
|
+
_civic_auth_includes: resolvedConfig.include.join(","),
|
|
126
|
+
_civic_auth_excludes: resolvedConfig.exclude.join(","),
|
|
127
|
+
_civic_auth_cookie_config: JSON.stringify(resolvedConfig.cookies)
|
|
128
|
+
})
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/nextjs/utils.ts
|
|
134
|
+
var resolveCallbackUrl = (config, alternativeUrl) => {
|
|
135
|
+
var _a;
|
|
136
|
+
const baseUrl = (_a = config.appUrl) != null ? _a : alternativeUrl;
|
|
137
|
+
const callbackUrl = new URL(config == null ? void 0 : config.callbackUrl, baseUrl).toString();
|
|
138
|
+
return callbackUrl.toString();
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export {
|
|
142
|
+
loggers,
|
|
143
|
+
defaultAuthConfig,
|
|
144
|
+
resolveAuthConfig,
|
|
145
|
+
createCivicAuthPlugin,
|
|
146
|
+
resolveCallbackUrl
|
|
147
|
+
};
|
|
148
|
+
//# sourceMappingURL=chunk-EAANLFR5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/logger.ts","../src/nextjs/config.ts","../src/nextjs/utils.ts"],"sourcesContent":["import debug from \"debug\";\n\nconst PACKAGE_NAME = \"@civic/auth\";\n\nexport interface Logger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nclass DebugLogger implements Logger {\n private debugLogger: debug.Debugger;\n private infoLogger: debug.Debugger;\n private warnLogger: debug.Debugger;\n private errorLogger: debug.Debugger;\n\n constructor(namespace: string) {\n // Format: @org/package:library:component:level\n this.debugLogger = debug(`${PACKAGE_NAME}:${namespace}:debug`);\n this.infoLogger = debug(`${PACKAGE_NAME}:${namespace}:info`);\n this.warnLogger = debug(`${PACKAGE_NAME}:${namespace}:warn`);\n this.errorLogger = debug(`${PACKAGE_NAME}:${namespace}:error`);\n\n this.debugLogger.color = \"4\";\n this.infoLogger.color = \"2\";\n this.warnLogger.color = \"3\";\n this.errorLogger.color = \"1\";\n }\n\n debug(message: string, ...args: unknown[]): void {\n this.debugLogger(message, ...args);\n }\n\n info(message: string, ...args: unknown[]): void {\n this.infoLogger(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n this.warnLogger(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n this.errorLogger(message, ...args);\n }\n}\n\nexport const createLogger = (namespace: string): Logger =>\n new DebugLogger(namespace);\n\n// Pre-configured loggers for different parts of your package\nexport const loggers = {\n // Next.js specific loggers\n nextjs: {\n routes: createLogger(\"api:routes\"),\n middleware: createLogger(\"api:middleware\"),\n handlers: {\n auth: createLogger(\"api:handlers:auth\"),\n },\n },\n // React specific loggers\n react: {\n components: createLogger(\"react:components\"),\n hooks: createLogger(\"react:hooks\"),\n context: createLogger(\"react:context\"),\n },\n // Shared utilities loggers\n services: {\n validation: createLogger(\"utils:validation\"),\n network: createLogger(\"utils:network\"),\n },\n} as const;\n","/* eslint-disable turbo/no-undeclared-env-vars */\nimport { NextConfig } from \"next\";\nimport { loggers } from \"@/lib/logger\";\nimport { withoutUndefined } from \"@/utils\";\n\nconst logger = loggers.nextjs.handlers.auth;\n\nexport interface CookieConfig {\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n domain?: string;\n path?: string;\n maxAge?: number;\n}\n\nexport type AuthConfigWithDefaults = {\n clientId: string;\n oauthServer: string;\n callbackUrl: string;\n loginUrl: string;\n logoutUrl: string;\n appUrl?: string;\n challengeUrl: string;\n include: string[];\n exclude: string[];\n cookies: {\n tokens: CookieConfig;\n user: CookieConfig;\n };\n};\n\nexport type AuthConfig = Partial<AuthConfigWithDefaults>;\n\nexport type DefinedAuthConfig = AuthConfigWithDefaults;\n\n/**\n * Default configuration values that will be used if not overridden\n */\nexport const defaultAuthConfig: Omit<AuthConfigWithDefaults, \"clientId\"> = {\n oauthServer: \"https://auth-dev.civic.com/oauth\",\n callbackUrl: \"/api/auth/callback\",\n challengeUrl: \"/api/auth/challenge\",\n logoutUrl: \"/api/auth/logout\",\n loginUrl: \"/\",\n include: [\"/*\"],\n exclude: [],\n cookies: {\n tokens: {\n sameSite: \"strict\",\n path: \"/\",\n maxAge: 60 * 60, // 1 hour\n },\n user: {\n sameSite: \"strict\",\n path: \"/\",\n maxAge: 60 * 60, // 1 hour\n },\n },\n};\n\n/**\n * Resolves the authentication configuration by combining:\n * 1. Default values\n * 2. Environment variables (set internally by the plugin)\n * 3. Explicitly passed configuration\n *\n * Note: Developers should not set _civic_auth_* environment variables directly.\n * Instead, pass configuration to the createCivicAuthPlugin in next.config.js:\n *\n * @example\n * ```js\n * // next.config.js\n * export default createCivicAuthPlugin({\n * callbackUrl: '/custom/callback',\n * })\n * ```\n */\nexport const resolveAuthConfig = (\n config: AuthConfig = {},\n): AuthConfigWithDefaults & { clientId: string } => {\n // Read configuration that was set by the plugin via environment variables\n const configFromEnv = withoutUndefined({\n clientId: process.env._civic_auth_client_id,\n oauthServer: process.env._civic_oauth_server,\n callbackUrl: process.env._civic_auth_callback_url,\n challengeUrl: process.env._civic_auth_challenge_url,\n loginUrl: process.env._civic_auth_login_url,\n appUrl: process.env._civic_auth_app_url,\n logoutUrl: process.env._civic_auth_logout_url,\n include: process.env._civic_auth_includes?.split(\",\"),\n exclude: process.env._civic_auth_excludes?.split(\",\"),\n cookies: process.env._civic_auth_cookie_config\n ? JSON.parse(process.env._civic_auth_cookie_config)\n : undefined,\n });\n\n const mergedConfig = {\n ...defaultAuthConfig,\n ...configFromEnv, // Apply plugin-set config\n ...config, // Override with directly passed config\n cookies: {\n tokens: {\n ...defaultAuthConfig.cookies.tokens,\n ...(config.cookies?.tokens || {}),\n },\n user: {\n ...defaultAuthConfig.cookies.user,\n ...(config.cookies?.user || {}),\n },\n },\n };\n\n logger.debug(\"Config from environment:\", configFromEnv);\n logger.debug(\"Resolved config:\", mergedConfig);\n if (mergedConfig.clientId === undefined) {\n throw new Error(\"Civic Auth client ID is required\");\n }\n return mergedConfig as AuthConfigWithDefaults & { clientId: string };\n};\n\n/**\n * Creates a Next.js plugin that handles auth configuration.\n *\n * This is the main configuration point for the auth system.\n * Do not set _civic_auth_* environment variables directly - instead,\n * pass your configuration here:\n *\n * @example\n * ```js\n * // next.config.js\n * export default createCivicAuthPlugin({\n * clientId: 'my-client-id',\n * callbackUrl: '/custom/callback',\n * loginUrl: '/custom/login',\n * logoutUrl: '/custom/logout',\n * include: ['/protected/*'],\n * exclude: ['/public/*']\n * })\n * ```\n *\n * The plugin sets internal environment variables that are used by\n * the auth system. These variables should not be set manually.\n */\nexport const createCivicAuthPlugin = (\n clientId: string,\n authConfig: AuthConfig = {},\n) => {\n return (nextConfig?: NextConfig) => {\n const resolvedConfig = resolveAuthConfig({ ...authConfig, clientId });\n return {\n ...nextConfig,\n env: {\n ...nextConfig?.env,\n // Internal environment variables - do not set these manually\n _civic_auth_client_id: clientId,\n _civic_oauth_server: resolvedConfig.oauthServer,\n _civic_auth_callback_url: resolvedConfig.callbackUrl,\n _civic_auth_challenge_url: resolvedConfig.challengeUrl,\n _civic_auth_login_url: resolvedConfig.loginUrl,\n _civic_auth_logout_url: resolvedConfig.logoutUrl,\n _civic_auth_app_url: resolvedConfig.appUrl,\n _civic_auth_includes: resolvedConfig.include.join(\",\"),\n _civic_auth_excludes: resolvedConfig.exclude.join(\",\"),\n _civic_auth_cookie_config: JSON.stringify(resolvedConfig.cookies),\n },\n };\n };\n};\n","import { AuthConfigWithDefaults } from \"@/nextjs/config\";\n\nexport const resolveCallbackUrl = (\n config: AuthConfigWithDefaults,\n alternativeUrl?: string,\n): string => {\n const baseUrl = config.appUrl ?? alternativeUrl;\n const callbackUrl = new URL(config?.callbackUrl, baseUrl).toString();\n return callbackUrl.toString();\n};\n"],"mappings":";;;;;;;;;AAAA,OAAO,WAAW;AAElB,IAAM,eAAe;AASrB,IAAM,cAAN,MAAoC;AAAA,EAMlC,YAAY,WAAmB;AAE7B,SAAK,cAAc,MAAM,GAAG,YAAY,IAAI,SAAS,QAAQ;AAC7D,SAAK,aAAa,MAAM,GAAG,YAAY,IAAI,SAAS,OAAO;AAC3D,SAAK,aAAa,MAAM,GAAG,YAAY,IAAI,SAAS,OAAO;AAC3D,SAAK,cAAc,MAAM,GAAG,YAAY,IAAI,SAAS,QAAQ;AAE7D,SAAK,YAAY,QAAQ;AACzB,SAAK,WAAW,QAAQ;AACxB,SAAK,WAAW,QAAQ;AACxB,SAAK,YAAY,QAAQ;AAAA,EAC3B;AAAA,EAEA,MAAM,YAAoB,MAAuB;AAC/C,SAAK,YAAY,SAAS,GAAG,IAAI;AAAA,EACnC;AAAA,EAEA,KAAK,YAAoB,MAAuB;AAC9C,SAAK,WAAW,SAAS,GAAG,IAAI;AAAA,EAClC;AAAA,EAEA,KAAK,YAAoB,MAAuB;AAC9C,SAAK,WAAW,SAAS,GAAG,IAAI;AAAA,EAClC;AAAA,EAEA,MAAM,YAAoB,MAAuB;AAC/C,SAAK,YAAY,SAAS,GAAG,IAAI;AAAA,EACnC;AACF;AAEO,IAAM,eAAe,CAAC,cAC3B,IAAI,YAAY,SAAS;AAGpB,IAAM,UAAU;AAAA;AAAA,EAErB,QAAQ;AAAA,IACN,QAAQ,aAAa,YAAY;AAAA,IACjC,YAAY,aAAa,gBAAgB;AAAA,IACzC,UAAU;AAAA,MACR,MAAM,aAAa,mBAAmB;AAAA,IACxC;AAAA,EACF;AAAA;AAAA,EAEA,OAAO;AAAA,IACL,YAAY,aAAa,kBAAkB;AAAA,IAC3C,OAAO,aAAa,aAAa;AAAA,IACjC,SAAS,aAAa,eAAe;AAAA,EACvC;AAAA;AAAA,EAEA,UAAU;AAAA,IACR,YAAY,aAAa,kBAAkB;AAAA,IAC3C,SAAS,aAAa,eAAe;AAAA,EACvC;AACF;;;AClEA,IAAM,SAAS,QAAQ,OAAO,SAAS;AAiChC,IAAM,oBAA8D;AAAA,EACzE,aAAa;AAAA,EACb,aAAa;AAAA,EACb,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS,CAAC,IAAI;AAAA,EACd,SAAS,CAAC;AAAA,EACV,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,UAAU;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,KAAK;AAAA;AAAA,IACf;AAAA,IACA,MAAM;AAAA,MACJ,UAAU;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,KAAK;AAAA;AAAA,IACf;AAAA,EACF;AACF;AAmBO,IAAM,oBAAoB,CAC/B,SAAqB,CAAC,MAC4B;AA/EpD;AAiFE,QAAM,gBAAgB,iBAAiB;AAAA,IACrC,UAAU,QAAQ,IAAI;AAAA,IACtB,aAAa,QAAQ,IAAI;AAAA,IACzB,aAAa,QAAQ,IAAI;AAAA,IACzB,cAAc,QAAQ,IAAI;AAAA,IAC1B,UAAU,QAAQ,IAAI;AAAA,IACtB,QAAQ,QAAQ,IAAI;AAAA,IACpB,WAAW,QAAQ,IAAI;AAAA,IACvB,UAAS,aAAQ,IAAI,yBAAZ,mBAAkC,MAAM;AAAA,IACjD,UAAS,aAAQ,IAAI,yBAAZ,mBAAkC,MAAM;AAAA,IACjD,SAAS,QAAQ,IAAI,4BACjB,KAAK,MAAM,QAAQ,IAAI,yBAAyB,IAChD;AAAA,EACN,CAAC;AAED,QAAM,eAAe,+DAChB,oBACA,gBACA,SAHgB;AAAA;AAAA,IAInB,SAAS;AAAA,MACP,QAAQ,kCACH,kBAAkB,QAAQ,WACzB,YAAO,YAAP,mBAAgB,WAAU,CAAC;AAAA,MAEjC,MAAM,kCACD,kBAAkB,QAAQ,SACzB,YAAO,YAAP,mBAAgB,SAAQ,CAAC;AAAA,IAEjC;AAAA,EACF;AAEA,SAAO,MAAM,4BAA4B,aAAa;AACtD,SAAO,MAAM,oBAAoB,YAAY;AAC7C,MAAI,aAAa,aAAa,QAAW;AACvC,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AACA,SAAO;AACT;AAyBO,IAAM,wBAAwB,CACnC,UACA,aAAyB,CAAC,MACvB;AACH,SAAO,CAAC,eAA4B;AAClC,UAAM,iBAAiB,kBAAkB,iCAAK,aAAL,EAAiB,SAAS,EAAC;AACpE,WAAO,iCACF,aADE;AAAA,MAEL,KAAK,iCACA,yCAAY,MADZ;AAAA;AAAA,QAGH,uBAAuB;AAAA,QACvB,qBAAqB,eAAe;AAAA,QACpC,0BAA0B,eAAe;AAAA,QACzC,2BAA2B,eAAe;AAAA,QAC1C,uBAAuB,eAAe;AAAA,QACtC,wBAAwB,eAAe;AAAA,QACvC,qBAAqB,eAAe;AAAA,QACpC,sBAAsB,eAAe,QAAQ,KAAK,GAAG;AAAA,QACrD,sBAAsB,eAAe,QAAQ,KAAK,GAAG;AAAA,QACrD,2BAA2B,KAAK,UAAU,eAAe,OAAO;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AACF;;;ACrKO,IAAM,qBAAqB,CAChC,QACA,mBACW;AALb;AAME,QAAM,WAAU,YAAO,WAAP,YAAiB;AACjC,QAAM,cAAc,IAAI,IAAI,iCAAQ,aAAa,OAAO,EAAE,SAAS;AACnE,SAAO,YAAY,SAAS;AAC9B;","names":[]}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AUTH_SERVER,
|
|
3
|
+
DEFAULT_SCOPES,
|
|
4
|
+
GenericAuthenticationInitiator,
|
|
5
|
+
GenericPublicClientPKCEProducer,
|
|
6
|
+
exchangeTokens,
|
|
7
|
+
getEndpointsWithOverrides,
|
|
8
|
+
retrieveTokens,
|
|
9
|
+
storeTokens
|
|
10
|
+
} from "./chunk-PMDIR5XE.mjs";
|
|
11
|
+
import {
|
|
12
|
+
__async,
|
|
13
|
+
__spreadProps,
|
|
14
|
+
__spreadValues
|
|
15
|
+
} from "./chunk-RGHW4PYM.mjs";
|
|
16
|
+
|
|
17
|
+
// src/shared/storage.ts
|
|
18
|
+
var DEFAULT_COOKIE_DURATION = 60 * 15;
|
|
19
|
+
var CookieStorage = class {
|
|
20
|
+
constructor(settings = {}) {
|
|
21
|
+
var _a, _b, _c, _d, _e;
|
|
22
|
+
this.settings = {
|
|
23
|
+
httpOnly: (_a = settings.httpOnly) != null ? _a : true,
|
|
24
|
+
secure: (_b = settings.secure) != null ? _b : true,
|
|
25
|
+
// the callback request comes the auth server
|
|
26
|
+
// 'lax' ensures the code_verifier cookie is sent with the request
|
|
27
|
+
sameSite: (_c = settings.sameSite) != null ? _c : "lax",
|
|
28
|
+
expires: (_d = settings.expires) != null ? _d : new Date(Date.now() + 1e3 * DEFAULT_COOKIE_DURATION),
|
|
29
|
+
path: (_e = settings.path) != null ? _e : "/"
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// src/server/ServerAuthenticationResolver.ts
|
|
35
|
+
import { OAuth2Client } from "oslo/oauth2";
|
|
36
|
+
var ServerAuthenticationResolver = class _ServerAuthenticationResolver {
|
|
37
|
+
constructor(authConfig, storage, endpointOverrides) {
|
|
38
|
+
this.authConfig = authConfig;
|
|
39
|
+
this.storage = storage;
|
|
40
|
+
this.endpointOverrides = endpointOverrides;
|
|
41
|
+
this.pkceProducer = new GenericPublicClientPKCEProducer(storage);
|
|
42
|
+
}
|
|
43
|
+
validateExistingSession() {
|
|
44
|
+
throw new Error("Method not implemented.");
|
|
45
|
+
}
|
|
46
|
+
init() {
|
|
47
|
+
return __async(this, null, function* () {
|
|
48
|
+
this.endpoints = yield getEndpointsWithOverrides(
|
|
49
|
+
this.authConfig.oauthServer,
|
|
50
|
+
this.endpointOverrides
|
|
51
|
+
);
|
|
52
|
+
this.oauth2client = new OAuth2Client(
|
|
53
|
+
this.authConfig.clientId,
|
|
54
|
+
this.endpoints.auth,
|
|
55
|
+
this.endpoints.token,
|
|
56
|
+
{
|
|
57
|
+
redirectURI: this.authConfig.redirectUrl
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
return this;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
tokenExchange(code, state) {
|
|
64
|
+
return __async(this, null, function* () {
|
|
65
|
+
if (!this.oauth2client) yield this.init();
|
|
66
|
+
const codeVerifier = yield this.pkceProducer.getCodeVerifier();
|
|
67
|
+
if (!codeVerifier) throw new Error("Code verifier not found in storage");
|
|
68
|
+
const tokens = yield exchangeTokens(
|
|
69
|
+
code,
|
|
70
|
+
state,
|
|
71
|
+
this.pkceProducer,
|
|
72
|
+
this.oauth2client,
|
|
73
|
+
// clean up types here to avoid the ! operator
|
|
74
|
+
this.authConfig.oauthServer,
|
|
75
|
+
this.endpoints
|
|
76
|
+
// clean up types here to avoid the ! operator
|
|
77
|
+
);
|
|
78
|
+
storeTokens(this.storage, tokens);
|
|
79
|
+
return tokens;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
getSessionData() {
|
|
83
|
+
return __async(this, null, function* () {
|
|
84
|
+
const storageData = retrieveTokens(this.storage);
|
|
85
|
+
if (!storageData) return null;
|
|
86
|
+
return {
|
|
87
|
+
authenticated: !!storageData.id_token,
|
|
88
|
+
idToken: storageData.id_token,
|
|
89
|
+
accessToken: storageData.access_token,
|
|
90
|
+
refreshToken: storageData.refresh_token
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
static build(authConfig, storage, endpointOverrides) {
|
|
95
|
+
return __async(this, null, function* () {
|
|
96
|
+
const resolver = new _ServerAuthenticationResolver(
|
|
97
|
+
authConfig,
|
|
98
|
+
storage,
|
|
99
|
+
endpointOverrides
|
|
100
|
+
);
|
|
101
|
+
yield resolver.init();
|
|
102
|
+
return resolver;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// src/server/login.ts
|
|
108
|
+
function resolveOAuthAccessCode(code, state, storage, config) {
|
|
109
|
+
return __async(this, null, function* () {
|
|
110
|
+
var _a;
|
|
111
|
+
const authSessionService = yield ServerAuthenticationResolver.build(
|
|
112
|
+
__spreadProps(__spreadValues({}, config), {
|
|
113
|
+
oauthServer: (_a = config.oauthServer) != null ? _a : AUTH_SERVER
|
|
114
|
+
}),
|
|
115
|
+
storage,
|
|
116
|
+
config.endpointOverrides
|
|
117
|
+
);
|
|
118
|
+
return authSessionService.tokenExchange(code, state);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
function isLoggedIn(storage) {
|
|
122
|
+
return !!storage.get("id_token");
|
|
123
|
+
}
|
|
124
|
+
function buildLoginUrl(config, storage) {
|
|
125
|
+
return __async(this, null, function* () {
|
|
126
|
+
var _a, _b, _c;
|
|
127
|
+
const state = (_a = config.state) != null ? _a : Math.random().toString(36).substring(2);
|
|
128
|
+
const scopes = (_b = config.scopes) != null ? _b : DEFAULT_SCOPES;
|
|
129
|
+
const pkceProducer = new GenericPublicClientPKCEProducer(storage);
|
|
130
|
+
const authInitiator = new GenericAuthenticationInitiator(__spreadProps(__spreadValues({}, config), {
|
|
131
|
+
state,
|
|
132
|
+
scopes,
|
|
133
|
+
oauthServer: (_c = config.oauthServer) != null ? _c : AUTH_SERVER,
|
|
134
|
+
// When retrieving the PKCE challenge on the server-side, we produce it and store it in the session
|
|
135
|
+
pkceConsumer: pkceProducer
|
|
136
|
+
}));
|
|
137
|
+
return authInitiator.signIn();
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/shared/GenericAuthenticationRefresher.ts
|
|
142
|
+
import { OAuth2Client as OAuth2Client2 } from "oslo/oauth2";
|
|
143
|
+
var GenericAuthenticationRefresher = class _GenericAuthenticationRefresher {
|
|
144
|
+
constructor(authConfig, storage, endpointOverrides) {
|
|
145
|
+
this.authConfig = authConfig;
|
|
146
|
+
this.storage = storage;
|
|
147
|
+
this.endpointOverrides = endpointOverrides;
|
|
148
|
+
}
|
|
149
|
+
init() {
|
|
150
|
+
return __async(this, null, function* () {
|
|
151
|
+
this.endpoints = yield getEndpointsWithOverrides(
|
|
152
|
+
this.authConfig.oauthServer,
|
|
153
|
+
this.endpointOverrides
|
|
154
|
+
);
|
|
155
|
+
this.oauth2client = new OAuth2Client2(
|
|
156
|
+
this.authConfig.clientId,
|
|
157
|
+
this.endpoints.auth,
|
|
158
|
+
this.endpoints.token,
|
|
159
|
+
{
|
|
160
|
+
redirectURI: this.authConfig.redirectUrl
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
return this;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
static build(authConfig, storage, endpointOverrides) {
|
|
167
|
+
return __async(this, null, function* () {
|
|
168
|
+
const refresher = new _GenericAuthenticationRefresher(
|
|
169
|
+
authConfig,
|
|
170
|
+
storage,
|
|
171
|
+
endpointOverrides
|
|
172
|
+
);
|
|
173
|
+
yield refresher.init();
|
|
174
|
+
return refresher;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
refreshTokens() {
|
|
178
|
+
return __async(this, null, function* () {
|
|
179
|
+
if (!this.oauth2client) yield this.init();
|
|
180
|
+
const tokens = retrieveTokens(this.storage);
|
|
181
|
+
if (!(tokens == null ? void 0 : tokens.refresh_token)) throw new Error("No refresh token available");
|
|
182
|
+
const oauth2Client = this.oauth2client;
|
|
183
|
+
const refreshedTokens = yield oauth2Client.refreshAccessToken(
|
|
184
|
+
tokens.refresh_token
|
|
185
|
+
);
|
|
186
|
+
storeTokens(this.storage, refreshedTokens);
|
|
187
|
+
return tokens;
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// src/server/refresh.ts
|
|
193
|
+
function refreshTokens(storage, config) {
|
|
194
|
+
return __async(this, null, function* () {
|
|
195
|
+
var _a;
|
|
196
|
+
const refresher = yield GenericAuthenticationRefresher.build(
|
|
197
|
+
__spreadProps(__spreadValues({}, config), {
|
|
198
|
+
oauthServer: (_a = config.oauthServer) != null ? _a : AUTH_SERVER
|
|
199
|
+
}),
|
|
200
|
+
storage,
|
|
201
|
+
config.endpointOverrides
|
|
202
|
+
);
|
|
203
|
+
return refresher.refreshTokens();
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
CookieStorage,
|
|
209
|
+
resolveOAuthAccessCode,
|
|
210
|
+
isLoggedIn,
|
|
211
|
+
buildLoginUrl,
|
|
212
|
+
refreshTokens
|
|
213
|
+
};
|
|
214
|
+
//# sourceMappingURL=chunk-EGFTMH5S.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/storage.ts","../src/server/ServerAuthenticationResolver.ts","../src/server/login.ts","../src/shared/GenericAuthenticationRefresher.ts","../src/server/refresh.ts"],"sourcesContent":["import { AuthStorage, SessionData, UnknownObject, User } from \"@/types.js\";\n\ntype SameSiteOption = \"strict\" | \"lax\" | \"none\";\n\nexport interface SessionStorage {\n get(): SessionData;\n getUser(): User<UnknownObject> | null;\n set(data: Partial<SessionData>): void;\n setUser(data: User<UnknownObject> | null): void;\n clear(): void;\n}\n\nexport type CookieStorageSettings = {\n httpOnly: boolean;\n secure: boolean;\n sameSite: SameSiteOption;\n expires: Date;\n path: string;\n};\n\nexport const DEFAULT_COOKIE_DURATION = 60 * 15; // 15 minutes\n\nexport abstract class CookieStorage implements AuthStorage {\n protected settings: CookieStorageSettings;\n protected constructor(settings: Partial<CookieStorageSettings> = {}) {\n this.settings = {\n httpOnly: settings.httpOnly ?? true,\n secure: settings.secure ?? true,\n // the callback request comes the auth server\n // 'lax' ensures the code_verifier cookie is sent with the request\n sameSite: settings.sameSite ?? \"lax\",\n expires:\n settings.expires ??\n new Date(Date.now() + 1000 * DEFAULT_COOKIE_DURATION),\n path: settings.path ?? \"/\",\n };\n }\n abstract get(key: string): string | null;\n abstract set(key: string, value: string): void;\n}\n","import { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport {\n AuthStorage,\n Endpoints,\n OIDCTokenResponseBody,\n SessionData,\n} from \"@/types.js\";\nimport { AuthConfig } from \"@/server/config.js\";\nimport {\n exchangeTokens,\n getEndpointsWithOverrides,\n retrieveTokens,\n storeTokens,\n} from \"@/shared/util.js\";\nimport { AuthenticationResolver, PKCEProducer } from \"@/services/types.ts\";\n\nexport class ServerAuthenticationResolver implements AuthenticationResolver {\n private pkceProducer: PKCEProducer;\n private oauth2client: OAuth2Client | undefined;\n private endpoints: Endpoints | undefined;\n\n private constructor(\n readonly authConfig: AuthConfig,\n readonly storage: AuthStorage,\n readonly endpointOverrides?: Partial<Endpoints>,\n ) {\n this.pkceProducer = new GenericPublicClientPKCEProducer(storage);\n }\n validateExistingSession(): Promise<SessionData> {\n throw new Error(\"Method not implemented.\");\n }\n\n async init(): Promise<this> {\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.authConfig.oauthServer,\n this.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.authConfig.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.authConfig.redirectUrl,\n },\n );\n\n return this;\n }\n\n async tokenExchange(\n code: string,\n state: string,\n ): Promise<OIDCTokenResponseBody> {\n if (!this.oauth2client) await this.init();\n const codeVerifier = await this.pkceProducer.getCodeVerifier();\n if (!codeVerifier) throw new Error(\"Code verifier not found in storage\");\n\n // exchange auth code for tokens\n const tokens = await exchangeTokens(\n code,\n state,\n this.pkceProducer,\n this.oauth2client!, // clean up types here to avoid the ! operator\n this.authConfig.oauthServer,\n this.endpoints!, // clean up types here to avoid the ! operator\n );\n\n storeTokens(this.storage, tokens);\n\n return tokens;\n }\n\n async getSessionData(): Promise<SessionData | null> {\n const storageData = retrieveTokens(this.storage);\n\n if (!storageData) return null;\n\n return {\n authenticated: !!storageData.id_token,\n idToken: storageData.id_token,\n accessToken: storageData.access_token,\n refreshToken: storageData.refresh_token,\n };\n }\n\n static async build(\n authConfig: AuthConfig,\n storage: AuthStorage,\n endpointOverrides?: Partial<Endpoints>,\n ): Promise<AuthenticationResolver> {\n const resolver = new ServerAuthenticationResolver(\n authConfig,\n storage,\n endpointOverrides,\n );\n await resolver.init();\n\n return resolver;\n }\n}\n","import { AuthStorage, OIDCTokenResponseBody } from \"@/types.js\";\nimport { AUTH_SERVER, DEFAULT_SCOPES } from \"@/constants.js\";\nimport { GenericAuthenticationInitiator } from \"@/services/AuthenticationService.js\";\nimport { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { ServerAuthenticationResolver } from \"@/server/ServerAuthenticationResolver.js\";\nimport { AuthConfig } from \"@/server/config.ts\";\n/**\n * Resolve an OAuth access code to a set of OIDC tokens\n * @param code The access code, typically from a query parameter in the redirect url\n * @param state The oauth random state string, used to distinguish between requests. Typically also passed in the redirect url\n * @param storage The place that this server uses to store session data (e.g. a cookie store)\n * @param config Oauth Server configuration\n */\nexport async function resolveOAuthAccessCode(\n code: string,\n state: string,\n storage: AuthStorage,\n config: AuthConfig,\n): Promise<OIDCTokenResponseBody> {\n const authSessionService = await ServerAuthenticationResolver.build(\n {\n ...config,\n oauthServer: config.oauthServer ?? AUTH_SERVER,\n },\n storage,\n config.endpointOverrides,\n );\n\n return authSessionService.tokenExchange(code, state);\n}\n\nexport function isLoggedIn(storage: AuthStorage): boolean {\n return !!storage.get(\"id_token\");\n}\n\nexport async function buildLoginUrl(\n config: Pick<AuthConfig, \"oauthServer\" | \"clientId\" | \"redirectUrl\"> & {\n scopes?: string[];\n state?: string;\n nonce?: string;\n },\n storage: AuthStorage,\n): Promise<URL> {\n // generate a random state if not provided\n const state = config.state ?? Math.random().toString(36).substring(2);\n const scopes = config.scopes ?? DEFAULT_SCOPES;\n const pkceProducer = new GenericPublicClientPKCEProducer(storage);\n const authInitiator = new GenericAuthenticationInitiator({\n ...config,\n state,\n scopes,\n oauthServer: config.oauthServer ?? AUTH_SERVER,\n // When retrieving the PKCE challenge on the server-side, we produce it and store it in the session\n pkceConsumer: pkceProducer,\n });\n\n return authInitiator.signIn();\n}\n","import { AuthenticationRefresher } from \"@/services/types.ts\";\nimport { AuthStorage, Endpoints, OIDCTokenResponseBody } from \"@/types\";\nimport {\n getEndpointsWithOverrides,\n retrieveTokens,\n storeTokens,\n} from \"@/shared/util.ts\";\nimport { AuthConfig } from \"@/server/config.ts\";\nimport { OAuth2Client } from \"oslo/oauth2\";\n\nexport class GenericAuthenticationRefresher implements AuthenticationRefresher {\n private oauth2client: OAuth2Client | undefined;\n private endpoints: Endpoints | undefined;\n\n private constructor(\n private authConfig: AuthConfig,\n private storage: AuthStorage,\n private endpointOverrides?: Partial<Endpoints>,\n ) {}\n\n async init(): Promise<this> {\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.authConfig.oauthServer,\n this.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.authConfig.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.authConfig.redirectUrl,\n },\n );\n\n return this;\n }\n\n static async build(\n authConfig: AuthConfig,\n storage: AuthStorage,\n endpointOverrides?: Partial<Endpoints>,\n ): Promise<GenericAuthenticationRefresher> {\n const refresher = new GenericAuthenticationRefresher(\n authConfig,\n storage,\n endpointOverrides,\n );\n await refresher.init();\n\n return refresher;\n }\n\n async refreshTokens() {\n if (!this.oauth2client) await this.init();\n\n const tokens = retrieveTokens(this.storage);\n if (!tokens?.refresh_token) throw new Error(\"No refresh token available\");\n\n const oauth2Client = this.oauth2client!;\n const refreshedTokens =\n await oauth2Client.refreshAccessToken<OIDCTokenResponseBody>(\n tokens.refresh_token,\n );\n\n storeTokens(this.storage, refreshedTokens);\n\n return tokens;\n }\n}\n","import { AuthStorage, OIDCTokenResponseBody } from \"@/types.js\";\nimport { AUTH_SERVER } from \"@/constants.js\";\nimport { GenericAuthenticationRefresher } from \"@/shared/GenericAuthenticationRefresher.ts\";\nimport { AuthConfig } from \"@/server/config.ts\";\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 GenericAuthenticationRefresher.build(\n {\n ...config,\n oauthServer: config.oauthServer ?? AUTH_SERVER,\n },\n storage,\n config.endpointOverrides,\n );\n\n return refresher.refreshTokens();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBO,IAAM,0BAA0B,KAAK;AAErC,IAAe,gBAAf,MAAoD;AAAA,EAE/C,YAAY,WAA2C,CAAC,GAAG;AAxBvE;AAyBI,SAAK,WAAW;AAAA,MACd,WAAU,cAAS,aAAT,YAAqB;AAAA,MAC/B,SAAQ,cAAS,WAAT,YAAmB;AAAA;AAAA;AAAA,MAG3B,WAAU,cAAS,aAAT,YAAqB;AAAA,MAC/B,UACE,cAAS,YAAT,YACA,IAAI,KAAK,KAAK,IAAI,IAAI,MAAO,uBAAuB;AAAA,MACtD,OAAM,cAAS,SAAT,YAAiB;AAAA,IACzB;AAAA,EACF;AAGF;;;ACtCA,SAAS,oBAAoB;AAgBtB,IAAM,+BAAN,MAAM,8BAA+D;AAAA,EAKlE,YACG,YACA,SACA,mBACT;AAHS;AACA;AACA;AAET,SAAK,eAAe,IAAI,gCAAgC,OAAO;AAAA,EACjE;AAAA,EACA,0BAAgD;AAC9C,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAAA,EAEM,OAAsB;AAAA;AAE1B,WAAK,YAAY,MAAM;AAAA,QACrB,KAAK,WAAW;AAAA,QAChB,KAAK;AAAA,MACP;AACA,WAAK,eAAe,IAAI;AAAA,QACtB,KAAK,WAAW;AAAA,QAChB,KAAK,UAAU;AAAA,QACf,KAAK,UAAU;AAAA,QACf;AAAA,UACE,aAAa,KAAK,WAAW;AAAA,QAC/B;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA;AAAA,EAEM,cACJ,MACA,OACgC;AAAA;AAChC,UAAI,CAAC,KAAK,aAAc,OAAM,KAAK,KAAK;AACxC,YAAM,eAAe,MAAM,KAAK,aAAa,gBAAgB;AAC7D,UAAI,CAAC,aAAc,OAAM,IAAI,MAAM,oCAAoC;AAGvE,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA;AAAA,QACL,KAAK,WAAW;AAAA,QAChB,KAAK;AAAA;AAAA,MACP;AAEA,kBAAY,KAAK,SAAS,MAAM;AAEhC,aAAO;AAAA,IACT;AAAA;AAAA,EAEM,iBAA8C;AAAA;AAClD,YAAM,cAAc,eAAe,KAAK,OAAO;AAE/C,UAAI,CAAC,YAAa,QAAO;AAEzB,aAAO;AAAA,QACL,eAAe,CAAC,CAAC,YAAY;AAAA,QAC7B,SAAS,YAAY;AAAA,QACrB,aAAa,YAAY;AAAA,QACzB,cAAc,YAAY;AAAA,MAC5B;AAAA,IACF;AAAA;AAAA,EAEA,OAAa,MACX,YACA,SACA,mBACiC;AAAA;AACjC,YAAM,WAAW,IAAI;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,YAAM,SAAS,KAAK;AAEpB,aAAO;AAAA,IACT;AAAA;AACF;;;ACxFA,SAAsB,uBACpB,MACA,OACA,SACA,QACgC;AAAA;AAlBlC;AAmBE,UAAM,qBAAqB,MAAM,6BAA6B;AAAA,MAC5D,iCACK,SADL;AAAA,QAEE,cAAa,YAAO,gBAAP,YAAsB;AAAA,MACrC;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AAEA,WAAO,mBAAmB,cAAc,MAAM,KAAK;AAAA,EACrD;AAAA;AAEO,SAAS,WAAW,SAA+B;AACxD,SAAO,CAAC,CAAC,QAAQ,IAAI,UAAU;AACjC;AAEA,SAAsB,cACpB,QAKA,SACc;AAAA;AA1ChB;AA4CE,UAAM,SAAQ,YAAO,UAAP,YAAgB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC;AACpE,UAAM,UAAS,YAAO,WAAP,YAAiB;AAChC,UAAM,eAAe,IAAI,gCAAgC,OAAO;AAChE,UAAM,gBAAgB,IAAI,+BAA+B,iCACpD,SADoD;AAAA,MAEvD;AAAA,MACA;AAAA,MACA,cAAa,YAAO,gBAAP,YAAsB;AAAA;AAAA,MAEnC,cAAc;AAAA,IAChB,EAAC;AAED,WAAO,cAAc,OAAO;AAAA,EAC9B;AAAA;;;ACjDA,SAAS,gBAAAA,qBAAoB;AAEtB,IAAM,iCAAN,MAAM,gCAAkE;AAAA,EAIrE,YACE,YACA,SACA,mBACR;AAHQ;AACA;AACA;AAAA,EACP;AAAA,EAEG,OAAsB;AAAA;AAE1B,WAAK,YAAY,MAAM;AAAA,QACrB,KAAK,WAAW;AAAA,QAChB,KAAK;AAAA,MACP;AACA,WAAK,eAAe,IAAIC;AAAA,QACtB,KAAK,WAAW;AAAA,QAChB,KAAK,UAAU;AAAA,QACf,KAAK,UAAU;AAAA,QACf;AAAA,UACE,aAAa,KAAK,WAAW;AAAA,QAC/B;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA;AAAA,EAEA,OAAa,MACX,YACA,SACA,mBACyC;AAAA;AACzC,YAAM,YAAY,IAAI;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,YAAM,UAAU,KAAK;AAErB,aAAO;AAAA,IACT;AAAA;AAAA,EAEM,gBAAgB;AAAA;AACpB,UAAI,CAAC,KAAK,aAAc,OAAM,KAAK,KAAK;AAExC,YAAM,SAAS,eAAe,KAAK,OAAO;AAC1C,UAAI,EAAC,iCAAQ,eAAe,OAAM,IAAI,MAAM,4BAA4B;AAExE,YAAM,eAAe,KAAK;AAC1B,YAAM,kBACJ,MAAM,aAAa;AAAA,QACjB,OAAO;AAAA,MACT;AAEF,kBAAY,KAAK,SAAS,eAAe;AAEzC,aAAO;AAAA,IACT;AAAA;AACF;;;AC7DA,SAAsB,cACpB,SACA,QACgC;AAAA;AAXlC;AAYE,UAAM,YAAY,MAAM,+BAA+B;AAAA,MACrD,iCACK,SADL;AAAA,QAEE,cAAa,YAAO,gBAAP,YAAsB;AAAA,MACrC;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AAEA,WAAO,UAAU,cAAc;AAAA,EACjC;AAAA;","names":["OAuth2Client","OAuth2Client"]}
|