@alepha/react 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/chunk-DhGyd7sr.js +28 -0
- package/dist/auth/index.browser.js +394 -114
- package/dist/auth/index.browser.js.map +1 -1
- package/dist/auth/index.cjs +80 -1927
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +1130 -420
- package/dist/auth/index.d.ts +1130 -420
- package/dist/auth/index.js +72 -1918
- package/dist/auth/index.js.map +1 -1
- package/dist/core/chunk-DhGyd7sr.js +28 -0
- package/dist/core/index.browser.js +79 -79
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.cjs +89 -85
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +1654 -154
- package/dist/core/index.d.ts +1654 -154
- package/dist/core/index.js +79 -79
- package/dist/core/index.js.map +1 -1
- package/dist/form/chunk-DhGyd7sr.js +28 -0
- package/dist/form/index.cjs +28 -8
- package/dist/form/index.cjs.map +1 -1
- package/dist/form/index.d.cts +215 -7
- package/dist/form/index.d.ts +215 -7
- package/dist/form/index.js +18 -3
- package/dist/form/index.js.map +1 -1
- package/dist/head/chunk-DhGyd7sr.js +28 -0
- package/dist/head/index.browser.js +385 -59
- package/dist/head/index.browser.js.map +1 -1
- package/dist/head/index.cjs +12 -8
- package/dist/head/index.cjs.map +1 -1
- package/dist/head/index.d.cts +1230 -24
- package/dist/head/index.d.ts +1230 -29
- package/dist/head/index.js +2 -2
- package/dist/head/index.js.map +1 -1
- package/dist/i18n/chunk-DhGyd7sr.js +28 -0
- package/dist/i18n/index.cjs +33 -20
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +282 -13
- package/dist/i18n/index.d.ts +282 -13
- package/dist/i18n/index.js +23 -14
- package/dist/i18n/index.js.map +1 -1
- package/dist/websocket/index.cjs +21 -8
- package/dist/websocket/index.cjs.map +1 -1
- package/dist/websocket/index.js +11 -2
- package/dist/websocket/index.js.map +1 -1
- package/package.json +7 -6
- package/src/auth/index.browser.ts +3 -6
- package/src/auth/index.shared.ts +0 -1
- package/src/auth/index.ts +3 -16
- package/src/auth/providers/ReactAuthProvider.ts +1 -614
- package/src/auth/services/ReactAuth.ts +6 -17
- package/src/core/descriptors/$page.ts +1 -1
- package/src/core/index.browser.ts +1 -0
- package/src/core/index.native.ts +21 -0
- package/src/core/index.shared-router.ts +15 -0
- package/src/core/index.shared.ts +0 -14
- package/src/core/index.ts +1 -0
- package/src/core/services/ReactRouter.ts +2 -2
- package/src/form/errors/FormValidationError.ts +20 -0
- package/src/form/hooks/useForm.ts +1 -1
- package/src/form/index.ts +1 -0
- package/src/head/providers/BrowserHeadProvider.ts +1 -1
- package/src/i18n/descriptors/$dictionary.ts +7 -3
- package/src/i18n/providers/I18nProvider.ts +9 -10
- package/src/websocket/hooks/useRoom.tsx +21 -2
- package/dist/auth/index.d.cts.map +0 -1
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/core/index.d.cts.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/form/index.d.cts.map +0 -1
- package/dist/form/index.d.ts.map +0 -1
- package/dist/head/index.d.cts.map +0 -1
- package/dist/head/index.d.ts.map +0 -1
- package/dist/i18n/index.d.cts.map +0 -1
- package/dist/i18n/index.d.ts.map +0 -1
- package/dist/websocket/index.d.cts.map +0 -1
- package/dist/websocket/index.d.ts.map +0 -1
- package/src/auth/descriptors/$auth.ts +0 -436
- package/src/auth/descriptors/$authApple.ts +0 -8
- package/src/auth/descriptors/$authGithub.ts +0 -81
- package/src/auth/descriptors/$authGoogle.ts +0 -38
- package/src/auth/errors/SessionExpiredError.ts +0 -6
- package/src/auth/schemas/tokenResponseSchema.ts +0 -11
- package/src/auth/schemas/tokensSchema.ts +0 -21
- package/src/auth/schemas/userinfoResponseSchema.ts +0 -10
package/dist/auth/index.cjs
CHANGED
|
@@ -6,12 +6,16 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
8
|
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
15
19
|
}
|
|
16
20
|
return to;
|
|
17
21
|
};
|
|
@@ -35,8 +39,7 @@ let node_path = require("node:path");
|
|
|
35
39
|
let alepha_server_static = require("alepha/server/static");
|
|
36
40
|
let react_dom_server = require("react-dom/server");
|
|
37
41
|
let alepha_router = require("alepha/router");
|
|
38
|
-
let
|
|
39
|
-
let alepha_security = require("alepha/security");
|
|
42
|
+
let alepha_server_auth = require("alepha/server/auth");
|
|
40
43
|
|
|
41
44
|
//#region src/core/services/ReactPageService.ts
|
|
42
45
|
var ReactPageService = class {
|
|
@@ -96,7 +99,7 @@ var ReactPageService = class {
|
|
|
96
99
|
* const userProfile = $page({
|
|
97
100
|
* path: "/users/:id",
|
|
98
101
|
* schema: {
|
|
99
|
-
* params: t.object({ id: t.
|
|
102
|
+
* params: t.object({ id: t.integer() }),
|
|
100
103
|
* query: t.object({ tab: t.optional(t.text()) })
|
|
101
104
|
* },
|
|
102
105
|
* resolve: async ({ params }) => {
|
|
@@ -185,11 +188,11 @@ $page[alepha.KIND] = PageDescriptor;
|
|
|
185
188
|
* - you want to avoid server-side rendering for a specific part of your application
|
|
186
189
|
* - you want to prevent pre-rendering of a component
|
|
187
190
|
*/
|
|
188
|
-
const ClientOnly = (props
|
|
191
|
+
const ClientOnly = (props) => {
|
|
189
192
|
const [mounted, setMounted] = (0, react.useState)(false);
|
|
190
193
|
(0, react.useEffect)(() => setMounted(true), []);
|
|
191
|
-
if (props
|
|
192
|
-
return mounted ? props
|
|
194
|
+
if (props.disabled) return props.children;
|
|
195
|
+
return mounted ? props.children : props.fallback;
|
|
193
196
|
};
|
|
194
197
|
var ClientOnly_default = ClientOnly;
|
|
195
198
|
|
|
@@ -456,8 +459,8 @@ const useRouterState = () => {
|
|
|
456
459
|
* in any part of the React component tree.
|
|
457
460
|
*/
|
|
458
461
|
var ErrorBoundary = class extends react.default.Component {
|
|
459
|
-
constructor(props
|
|
460
|
-
super(props
|
|
462
|
+
constructor(props) {
|
|
463
|
+
super(props);
|
|
461
464
|
this.state = {};
|
|
462
465
|
}
|
|
463
466
|
/**
|
|
@@ -503,7 +506,7 @@ var ErrorBoundary_default = ErrorBoundary;
|
|
|
503
506
|
* }
|
|
504
507
|
* ```
|
|
505
508
|
*/
|
|
506
|
-
const NestedView = (props
|
|
509
|
+
const NestedView = (props) => {
|
|
507
510
|
const index = (0, react.use)(RouterLayerContext)?.index ?? 0;
|
|
508
511
|
const state = useRouterState();
|
|
509
512
|
const [view, setView] = (0, react.useState)(state.layers[index]?.element);
|
|
@@ -541,7 +544,7 @@ const NestedView = (props$1) => {
|
|
|
541
544
|
}
|
|
542
545
|
}
|
|
543
546
|
}, []);
|
|
544
|
-
let element = view ?? props
|
|
547
|
+
let element = view ?? props.children ?? null;
|
|
545
548
|
if (animation) element = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
546
549
|
style: {
|
|
547
550
|
display: "flex",
|
|
@@ -561,9 +564,9 @@ const NestedView = (props$1) => {
|
|
|
561
564
|
children: element
|
|
562
565
|
})
|
|
563
566
|
});
|
|
564
|
-
if (props
|
|
565
|
-
if (props
|
|
566
|
-
fallback: props
|
|
567
|
+
if (props.errorBoundary === false) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: element });
|
|
568
|
+
if (props.errorBoundary) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBoundary_default, {
|
|
569
|
+
fallback: props.errorBoundary,
|
|
567
570
|
children: element
|
|
568
571
|
});
|
|
569
572
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBoundary_default, {
|
|
@@ -604,7 +607,7 @@ function parseAnimation(animationLike, state, type = "enter") {
|
|
|
604
607
|
|
|
605
608
|
//#endregion
|
|
606
609
|
//#region src/core/components/NotFound.tsx
|
|
607
|
-
function NotFoundPage(props
|
|
610
|
+
function NotFoundPage(props) {
|
|
608
611
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
609
612
|
style: {
|
|
610
613
|
height: "100vh",
|
|
@@ -615,7 +618,7 @@ function NotFoundPage(props$1) {
|
|
|
615
618
|
textAlign: "center",
|
|
616
619
|
fontFamily: "sans-serif",
|
|
617
620
|
padding: "1rem",
|
|
618
|
-
...props
|
|
621
|
+
...props.style
|
|
619
622
|
},
|
|
620
623
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
621
624
|
style: {
|
|
@@ -695,7 +698,7 @@ var ReactPageProvider = class {
|
|
|
695
698
|
if (alepha.t.schema.isObject(schema) && typeof value === "object") {
|
|
696
699
|
for (const key in schema.properties) if (alepha.t.schema.isObject(schema.properties[key]) && typeof value[key] === "string") try {
|
|
697
700
|
value[key] = this.alepha.codec.decode(schema.properties[key], decodeURIComponent(value[key]));
|
|
698
|
-
} catch (e
|
|
701
|
+
} catch (e) {}
|
|
699
702
|
}
|
|
700
703
|
return value;
|
|
701
704
|
};
|
|
@@ -720,14 +723,14 @@ var ReactPageProvider = class {
|
|
|
720
723
|
try {
|
|
721
724
|
this.convertStringObjectToObject(route$1.schema?.query, state.query);
|
|
722
725
|
config.query = route$1.schema?.query ? this.alepha.codec.decode(route$1.schema.query, state.query) : {};
|
|
723
|
-
} catch (e
|
|
724
|
-
it.error = e
|
|
726
|
+
} catch (e) {
|
|
727
|
+
it.error = e;
|
|
725
728
|
break;
|
|
726
729
|
}
|
|
727
730
|
try {
|
|
728
731
|
config.params = route$1.schema?.params ? this.alepha.codec.decode(route$1.schema.params, state.params) : {};
|
|
729
|
-
} catch (e
|
|
730
|
-
it.error = e
|
|
732
|
+
} catch (e) {
|
|
733
|
+
it.error = e;
|
|
731
734
|
break;
|
|
732
735
|
}
|
|
733
736
|
it.config = { ...config };
|
|
@@ -755,23 +758,23 @@ var ReactPageProvider = class {
|
|
|
755
758
|
try {
|
|
756
759
|
const args = Object.create(state);
|
|
757
760
|
Object.assign(args, config, context);
|
|
758
|
-
const props
|
|
759
|
-
it.props = { ...props
|
|
761
|
+
const props = await route$1.resolve?.(args) ?? {};
|
|
762
|
+
it.props = { ...props };
|
|
760
763
|
context = {
|
|
761
764
|
...context,
|
|
762
|
-
...props
|
|
765
|
+
...props
|
|
763
766
|
};
|
|
764
|
-
} catch (e
|
|
765
|
-
if (e
|
|
766
|
-
this.log.error("Page resolver has failed", e
|
|
767
|
-
it.error = e
|
|
767
|
+
} catch (e) {
|
|
768
|
+
if (e instanceof Redirection) return { redirect: e.redirect };
|
|
769
|
+
this.log.error("Page resolver has failed", e);
|
|
770
|
+
it.error = e;
|
|
768
771
|
break;
|
|
769
772
|
}
|
|
770
773
|
}
|
|
771
774
|
let acc = "";
|
|
772
775
|
for (let i = 0; i < stack.length; i++) {
|
|
773
776
|
const it = stack[i];
|
|
774
|
-
const props
|
|
777
|
+
const props = it.props ?? {};
|
|
775
778
|
const params = { ...it.config?.params };
|
|
776
779
|
for (const key of Object.keys(params)) params[key] = String(params[key]);
|
|
777
780
|
acc += "/";
|
|
@@ -788,12 +791,12 @@ var ReactPageProvider = class {
|
|
|
788
791
|
}
|
|
789
792
|
if (!it.error) try {
|
|
790
793
|
const element = await this.createElement(it.route, {
|
|
791
|
-
...props
|
|
794
|
+
...props,
|
|
792
795
|
...context
|
|
793
796
|
});
|
|
794
797
|
state.layers.push({
|
|
795
798
|
name: it.route.name,
|
|
796
|
-
props
|
|
799
|
+
props,
|
|
797
800
|
part: it.route.path,
|
|
798
801
|
config: it.config,
|
|
799
802
|
element: this.renderView(i + 1, path, element, it.route),
|
|
@@ -802,8 +805,8 @@ var ReactPageProvider = class {
|
|
|
802
805
|
route: it.route,
|
|
803
806
|
cache: it.cache
|
|
804
807
|
});
|
|
805
|
-
} catch (e
|
|
806
|
-
it.error = e
|
|
808
|
+
} catch (e) {
|
|
809
|
+
it.error = e;
|
|
807
810
|
}
|
|
808
811
|
if (it.error) try {
|
|
809
812
|
let element = await state.onError(it.error, state);
|
|
@@ -811,7 +814,7 @@ var ReactPageProvider = class {
|
|
|
811
814
|
if (element instanceof Redirection) return { redirect: element.redirect };
|
|
812
815
|
if (element === null) element = this.renderError(it.error);
|
|
813
816
|
state.layers.push({
|
|
814
|
-
props
|
|
817
|
+
props,
|
|
815
818
|
error: it.error,
|
|
816
819
|
name: it.route.name,
|
|
817
820
|
part: it.route.path,
|
|
@@ -822,9 +825,9 @@ var ReactPageProvider = class {
|
|
|
822
825
|
route: it.route
|
|
823
826
|
});
|
|
824
827
|
break;
|
|
825
|
-
} catch (e
|
|
826
|
-
if (e
|
|
827
|
-
throw e
|
|
828
|
+
} catch (e) {
|
|
829
|
+
if (e instanceof Redirection) return { redirect: e.redirect };
|
|
830
|
+
throw e;
|
|
828
831
|
}
|
|
829
832
|
}
|
|
830
833
|
return { state };
|
|
@@ -840,10 +843,10 @@ var ReactPageProvider = class {
|
|
|
840
843
|
parent = parent.parent;
|
|
841
844
|
}
|
|
842
845
|
}
|
|
843
|
-
async createElement(page, props
|
|
846
|
+
async createElement(page, props) {
|
|
844
847
|
if (page.lazy && page.component) this.log.warn(`Page ${page.name} has both lazy and component options, lazy will be used`);
|
|
845
|
-
if (page.lazy) return (0, react.createElement)((await page.lazy()).default, props
|
|
846
|
-
if (page.component) return (0, react.createElement)(page.component, props
|
|
848
|
+
if (page.lazy) return (0, react.createElement)((await page.lazy()).default, props);
|
|
849
|
+
if (page.component) return (0, react.createElement)(page.component, props);
|
|
847
850
|
}
|
|
848
851
|
renderError(error) {
|
|
849
852
|
return (0, react.createElement)(ErrorViewer_default, {
|
|
@@ -1331,20 +1334,20 @@ var ReactBrowserRouterProvider = class extends alepha_router.RouterProvider {
|
|
|
1331
1334
|
});
|
|
1332
1335
|
await this.alepha.events.emit("react:action:success", { type: "transition" });
|
|
1333
1336
|
await this.alepha.events.emit("react:transition:success", { state });
|
|
1334
|
-
} catch (e
|
|
1335
|
-
this.log.error("Transition has failed", e
|
|
1337
|
+
} catch (e) {
|
|
1338
|
+
this.log.error("Transition has failed", e);
|
|
1336
1339
|
state.layers = [{
|
|
1337
1340
|
name: "error",
|
|
1338
|
-
element: this.pageApi.renderError(e
|
|
1341
|
+
element: this.pageApi.renderError(e),
|
|
1339
1342
|
index: 0,
|
|
1340
1343
|
path: "/"
|
|
1341
1344
|
}];
|
|
1342
1345
|
await this.alepha.events.emit("react:action:error", {
|
|
1343
1346
|
type: "transition",
|
|
1344
|
-
error: e
|
|
1347
|
+
error: e
|
|
1345
1348
|
});
|
|
1346
1349
|
await this.alepha.events.emit("react:transition:error", {
|
|
1347
|
-
error: e
|
|
1350
|
+
error: e,
|
|
1348
1351
|
state
|
|
1349
1352
|
});
|
|
1350
1353
|
}
|
|
@@ -1425,12 +1428,12 @@ var ReactBrowserProvider = class {
|
|
|
1425
1428
|
if (replace) this.history.replaceState({}, "", url);
|
|
1426
1429
|
else this.history.pushState({}, "", url);
|
|
1427
1430
|
}
|
|
1428
|
-
async invalidate(props
|
|
1431
|
+
async invalidate(props) {
|
|
1429
1432
|
const previous = [];
|
|
1430
1433
|
this.log.trace("Invalidating layers");
|
|
1431
|
-
if (props
|
|
1432
|
-
const [key] = Object.keys(props
|
|
1433
|
-
const value = props
|
|
1434
|
+
if (props) {
|
|
1435
|
+
const [key] = Object.keys(props);
|
|
1436
|
+
const value = props[key];
|
|
1434
1437
|
for (const layer of this.state.layers) {
|
|
1435
1438
|
if (layer.props?.[key]) {
|
|
1436
1439
|
previous.push({
|
|
@@ -1552,7 +1555,7 @@ var ReactRouter = class {
|
|
|
1552
1555
|
path(name, config = {}) {
|
|
1553
1556
|
return this.pageApi.pathname(name, {
|
|
1554
1557
|
params: {
|
|
1555
|
-
...this.state
|
|
1558
|
+
...this.state?.params,
|
|
1556
1559
|
...config.params
|
|
1557
1560
|
},
|
|
1558
1561
|
query: config.query
|
|
@@ -1594,8 +1597,8 @@ var ReactRouter = class {
|
|
|
1594
1597
|
async forward() {
|
|
1595
1598
|
this.browser?.history.forward();
|
|
1596
1599
|
}
|
|
1597
|
-
async invalidate(props
|
|
1598
|
-
await this.browser?.invalidate(props
|
|
1600
|
+
async invalidate(props) {
|
|
1601
|
+
await this.browser?.invalidate(props);
|
|
1599
1602
|
}
|
|
1600
1603
|
async go(path, options) {
|
|
1601
1604
|
for (const page of this.pages) if (page.name === path) {
|
|
@@ -1668,1411 +1671,30 @@ const AlephaReact = (0, alepha.$module)({
|
|
|
1668
1671
|
});
|
|
1669
1672
|
|
|
1670
1673
|
//#endregion
|
|
1671
|
-
//#region
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
}
|
|
1682
|
-
const ERR_INVALID_ARG_VALUE$1 = "ERR_INVALID_ARG_VALUE";
|
|
1683
|
-
const ERR_INVALID_ARG_TYPE$1 = "ERR_INVALID_ARG_TYPE";
|
|
1684
|
-
function CodedTypeError$1(message, code, cause) {
|
|
1685
|
-
const err = new TypeError(message, { cause });
|
|
1686
|
-
Object.assign(err, { code });
|
|
1687
|
-
return err;
|
|
1688
|
-
}
|
|
1689
|
-
const allowInsecureRequests$1 = Symbol();
|
|
1690
|
-
const clockSkew$1 = Symbol();
|
|
1691
|
-
const clockTolerance$1 = Symbol();
|
|
1692
|
-
const customFetch$1 = Symbol();
|
|
1693
|
-
const modifyAssertion$1 = Symbol();
|
|
1694
|
-
const jweDecrypt = Symbol();
|
|
1695
|
-
const encoder = new TextEncoder();
|
|
1696
|
-
const decoder$1 = new TextDecoder();
|
|
1697
|
-
function buf(input) {
|
|
1698
|
-
if (typeof input === "string") return encoder.encode(input);
|
|
1699
|
-
return decoder$1.decode(input);
|
|
1700
|
-
}
|
|
1701
|
-
let encodeBase64Url;
|
|
1702
|
-
if (Uint8Array.prototype.toBase64) encodeBase64Url = (input) => {
|
|
1703
|
-
if (input instanceof ArrayBuffer) input = new Uint8Array(input);
|
|
1704
|
-
return input.toBase64({
|
|
1705
|
-
alphabet: "base64url",
|
|
1706
|
-
omitPadding: true
|
|
1707
|
-
});
|
|
1708
|
-
};
|
|
1709
|
-
else {
|
|
1710
|
-
const CHUNK_SIZE = 32768;
|
|
1711
|
-
encodeBase64Url = (input) => {
|
|
1712
|
-
if (input instanceof ArrayBuffer) input = new Uint8Array(input);
|
|
1713
|
-
const arr = [];
|
|
1714
|
-
for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
1715
|
-
return btoa(arr.join("")).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
1716
|
-
};
|
|
1717
|
-
}
|
|
1718
|
-
let decodeBase64Url;
|
|
1719
|
-
if (Uint8Array.fromBase64) decodeBase64Url = (input) => {
|
|
1720
|
-
try {
|
|
1721
|
-
return Uint8Array.fromBase64(input, { alphabet: "base64url" });
|
|
1722
|
-
} catch (cause) {
|
|
1723
|
-
throw CodedTypeError$1("The input to be decoded is not correctly encoded.", ERR_INVALID_ARG_VALUE$1, cause);
|
|
1724
|
-
}
|
|
1725
|
-
};
|
|
1726
|
-
else decodeBase64Url = (input) => {
|
|
1727
|
-
try {
|
|
1728
|
-
const binary = atob(input.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, ""));
|
|
1729
|
-
const bytes = new Uint8Array(binary.length);
|
|
1730
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
1731
|
-
return bytes;
|
|
1732
|
-
} catch (cause) {
|
|
1733
|
-
throw CodedTypeError$1("The input to be decoded is not correctly encoded.", ERR_INVALID_ARG_VALUE$1, cause);
|
|
1734
|
-
}
|
|
1735
|
-
};
|
|
1736
|
-
function b64u(input) {
|
|
1737
|
-
if (typeof input === "string") return decodeBase64Url(input);
|
|
1738
|
-
return encodeBase64Url(input);
|
|
1739
|
-
}
|
|
1740
|
-
var UnsupportedOperationError = class extends Error {
|
|
1741
|
-
code;
|
|
1742
|
-
constructor(message, options) {
|
|
1743
|
-
super(message, options);
|
|
1744
|
-
this.name = this.constructor.name;
|
|
1745
|
-
this.code = UNSUPPORTED_OPERATION;
|
|
1746
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
1747
|
-
}
|
|
1748
|
-
};
|
|
1749
|
-
var OperationProcessingError = class extends Error {
|
|
1750
|
-
code;
|
|
1751
|
-
constructor(message, options) {
|
|
1752
|
-
super(message, options);
|
|
1753
|
-
this.name = this.constructor.name;
|
|
1754
|
-
if (options?.code) this.code = options?.code;
|
|
1755
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
1756
|
-
}
|
|
1757
|
-
};
|
|
1758
|
-
function OPE(message, code, cause) {
|
|
1759
|
-
return new OperationProcessingError(message, {
|
|
1760
|
-
code,
|
|
1761
|
-
cause
|
|
1762
|
-
});
|
|
1763
|
-
}
|
|
1764
|
-
function isJsonObject(input) {
|
|
1765
|
-
if (input === null || typeof input !== "object" || Array.isArray(input)) return false;
|
|
1766
|
-
return true;
|
|
1767
|
-
}
|
|
1768
|
-
function prepareHeaders(input) {
|
|
1769
|
-
if (looseInstanceOf(input, Headers)) input = Object.fromEntries(input.entries());
|
|
1770
|
-
const headers$1 = new Headers(input ?? {});
|
|
1771
|
-
if (USER_AGENT$1 && !headers$1.has("user-agent")) headers$1.set("user-agent", USER_AGENT$1);
|
|
1772
|
-
if (headers$1.has("authorization")) throw CodedTypeError$1("\"options.headers\" must not include the \"authorization\" header name", ERR_INVALID_ARG_VALUE$1);
|
|
1773
|
-
return headers$1;
|
|
1774
|
-
}
|
|
1775
|
-
function signal$1(url, value) {
|
|
1776
|
-
if (value !== void 0) {
|
|
1777
|
-
if (typeof value === "function") value = value(url.href);
|
|
1778
|
-
if (!(value instanceof AbortSignal)) throw CodedTypeError$1("\"options.signal\" must return or be an instance of AbortSignal", ERR_INVALID_ARG_TYPE$1);
|
|
1779
|
-
return value;
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
function replaceDoubleSlash(pathname) {
|
|
1783
|
-
if (pathname.includes("//")) return pathname.replace("//", "/");
|
|
1784
|
-
return pathname;
|
|
1785
|
-
}
|
|
1786
|
-
function prependWellKnown(url, wellKnown, allowTerminatingSlash = false) {
|
|
1787
|
-
if (url.pathname === "/") url.pathname = wellKnown;
|
|
1788
|
-
else url.pathname = replaceDoubleSlash(`${wellKnown}/${allowTerminatingSlash ? url.pathname : url.pathname.replace(/(\/)$/, "")}`);
|
|
1789
|
-
return url;
|
|
1790
|
-
}
|
|
1791
|
-
function appendWellKnown(url, wellKnown) {
|
|
1792
|
-
url.pathname = replaceDoubleSlash(`${url.pathname}/${wellKnown}`);
|
|
1793
|
-
return url;
|
|
1794
|
-
}
|
|
1795
|
-
async function performDiscovery$1(input, urlName, transform, options) {
|
|
1796
|
-
if (!(input instanceof URL)) throw CodedTypeError$1(`"${urlName}" must be an instance of URL`, ERR_INVALID_ARG_TYPE$1);
|
|
1797
|
-
checkProtocol(input, options?.[allowInsecureRequests$1] !== true);
|
|
1798
|
-
const url = transform(new URL(input.href));
|
|
1799
|
-
const headers$1 = prepareHeaders(options?.headers);
|
|
1800
|
-
headers$1.set("accept", "application/json");
|
|
1801
|
-
return (options?.[customFetch$1] || fetch)(url.href, {
|
|
1802
|
-
body: void 0,
|
|
1803
|
-
headers: Object.fromEntries(headers$1.entries()),
|
|
1804
|
-
method: "GET",
|
|
1805
|
-
redirect: "manual",
|
|
1806
|
-
signal: signal$1(url, options?.signal)
|
|
1807
|
-
});
|
|
1808
|
-
}
|
|
1809
|
-
async function discoveryRequest(issuerIdentifier, options) {
|
|
1810
|
-
return performDiscovery$1(issuerIdentifier, "issuerIdentifier", (url) => {
|
|
1811
|
-
switch (options?.algorithm) {
|
|
1812
|
-
case void 0:
|
|
1813
|
-
case "oidc":
|
|
1814
|
-
appendWellKnown(url, ".well-known/openid-configuration");
|
|
1815
|
-
break;
|
|
1816
|
-
case "oauth2":
|
|
1817
|
-
prependWellKnown(url, ".well-known/oauth-authorization-server");
|
|
1818
|
-
break;
|
|
1819
|
-
default: throw CodedTypeError$1("\"options.algorithm\" must be \"oidc\" (default), or \"oauth2\"", ERR_INVALID_ARG_VALUE$1);
|
|
1820
|
-
}
|
|
1821
|
-
return url;
|
|
1822
|
-
}, options);
|
|
1823
|
-
}
|
|
1824
|
-
function assertNumber(input, allow0, it, code, cause) {
|
|
1825
|
-
try {
|
|
1826
|
-
if (typeof input !== "number" || !Number.isFinite(input)) throw CodedTypeError$1(`${it} must be a number`, ERR_INVALID_ARG_TYPE$1, cause);
|
|
1827
|
-
if (input > 0) return;
|
|
1828
|
-
if (allow0) {
|
|
1829
|
-
if (input !== 0) throw CodedTypeError$1(`${it} must be a non-negative number`, ERR_INVALID_ARG_VALUE$1, cause);
|
|
1830
|
-
return;
|
|
1831
|
-
}
|
|
1832
|
-
throw CodedTypeError$1(`${it} must be a positive number`, ERR_INVALID_ARG_VALUE$1, cause);
|
|
1833
|
-
} catch (err) {
|
|
1834
|
-
if (code) throw OPE(err.message, code, cause);
|
|
1835
|
-
throw err;
|
|
1836
|
-
}
|
|
1837
|
-
}
|
|
1838
|
-
function assertString$1(input, it, code, cause) {
|
|
1839
|
-
try {
|
|
1840
|
-
if (typeof input !== "string") throw CodedTypeError$1(`${it} must be a string`, ERR_INVALID_ARG_TYPE$1, cause);
|
|
1841
|
-
if (input.length === 0) throw CodedTypeError$1(`${it} must not be empty`, ERR_INVALID_ARG_VALUE$1, cause);
|
|
1842
|
-
} catch (err) {
|
|
1843
|
-
if (code) throw OPE(err.message, code, cause);
|
|
1844
|
-
throw err;
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
async function processDiscoveryResponse(expectedIssuerIdentifier, response) {
|
|
1848
|
-
const expected = expectedIssuerIdentifier;
|
|
1849
|
-
if (!(expected instanceof URL) && expected !== _nodiscoverycheck) throw CodedTypeError$1("\"expectedIssuerIdentifier\" must be an instance of URL", ERR_INVALID_ARG_TYPE$1);
|
|
1850
|
-
if (!looseInstanceOf(response, Response)) throw CodedTypeError$1("\"response\" must be an instance of Response", ERR_INVALID_ARG_TYPE$1);
|
|
1851
|
-
if (response.status !== 200) throw OPE("\"response\" is not a conform Authorization Server Metadata response (unexpected HTTP status code)", RESPONSE_IS_NOT_CONFORM, response);
|
|
1852
|
-
assertReadableResponse(response);
|
|
1853
|
-
const json = await getResponseJsonBody(response);
|
|
1854
|
-
assertString$1(json.issuer, "\"response\" body \"issuer\" property", INVALID_RESPONSE, { body: json });
|
|
1855
|
-
if (expected !== _nodiscoverycheck && new URL(json.issuer).href !== expected.href) throw OPE("\"response\" body \"issuer\" property does not match the expected value", JSON_ATTRIBUTE_COMPARISON, {
|
|
1856
|
-
expected: expected.href,
|
|
1857
|
-
body: json,
|
|
1858
|
-
attribute: "issuer"
|
|
1859
|
-
});
|
|
1860
|
-
return json;
|
|
1861
|
-
}
|
|
1862
|
-
function assertApplicationJson(response) {
|
|
1863
|
-
assertContentType(response, "application/json");
|
|
1864
|
-
}
|
|
1865
|
-
function notJson(response, ...types) {
|
|
1866
|
-
let msg = "\"response\" content-type must be ";
|
|
1867
|
-
if (types.length > 2) {
|
|
1868
|
-
const last = types.pop();
|
|
1869
|
-
msg += `${types.join(", ")}, or ${last}`;
|
|
1870
|
-
} else if (types.length === 2) msg += `${types[0]} or ${types[1]}`;
|
|
1871
|
-
else msg += types[0];
|
|
1872
|
-
return OPE(msg, RESPONSE_IS_NOT_JSON, response);
|
|
1873
|
-
}
|
|
1874
|
-
function assertContentType(response, contentType) {
|
|
1875
|
-
if (getContentType(response) !== contentType) throw notJson(response, contentType);
|
|
1876
|
-
}
|
|
1877
|
-
function randomBytes() {
|
|
1878
|
-
return b64u(crypto.getRandomValues(new Uint8Array(32)));
|
|
1879
|
-
}
|
|
1880
|
-
function generateRandomCodeVerifier() {
|
|
1881
|
-
return randomBytes();
|
|
1882
|
-
}
|
|
1883
|
-
function generateRandomState() {
|
|
1884
|
-
return randomBytes();
|
|
1885
|
-
}
|
|
1886
|
-
async function calculatePKCECodeChallenge$1(codeVerifier) {
|
|
1887
|
-
assertString$1(codeVerifier, "codeVerifier");
|
|
1888
|
-
return b64u(await crypto.subtle.digest("SHA-256", buf(codeVerifier)));
|
|
1889
|
-
}
|
|
1890
|
-
function getClockSkew(client) {
|
|
1891
|
-
const skew = client?.[clockSkew$1];
|
|
1892
|
-
return typeof skew === "number" && Number.isFinite(skew) ? skew : 0;
|
|
1893
|
-
}
|
|
1894
|
-
function getClockTolerance(client) {
|
|
1895
|
-
const tolerance = client?.[clockTolerance$1];
|
|
1896
|
-
return typeof tolerance === "number" && Number.isFinite(tolerance) && Math.sign(tolerance) !== -1 ? tolerance : 30;
|
|
1897
|
-
}
|
|
1898
|
-
function epochTime() {
|
|
1899
|
-
return Math.floor(Date.now() / 1e3);
|
|
1900
|
-
}
|
|
1901
|
-
function assertAs(as) {
|
|
1902
|
-
if (typeof as !== "object" || as === null) throw CodedTypeError$1("\"as\" must be an object", ERR_INVALID_ARG_TYPE$1);
|
|
1903
|
-
assertString$1(as.issuer, "\"as.issuer\"");
|
|
1904
|
-
}
|
|
1905
|
-
function assertClient(client) {
|
|
1906
|
-
if (typeof client !== "object" || client === null) throw CodedTypeError$1("\"client\" must be an object", ERR_INVALID_ARG_TYPE$1);
|
|
1907
|
-
assertString$1(client.client_id, "\"client.client_id\"");
|
|
1908
|
-
}
|
|
1909
|
-
function ClientSecretPost$1(clientSecret) {
|
|
1910
|
-
assertString$1(clientSecret, "\"clientSecret\"");
|
|
1911
|
-
return (_as, client, body, _headers) => {
|
|
1912
|
-
body.set("client_id", client.client_id);
|
|
1913
|
-
body.set("client_secret", clientSecret);
|
|
1914
|
-
};
|
|
1915
|
-
}
|
|
1916
|
-
function None$1() {
|
|
1917
|
-
return (_as, client, body, _headers) => {
|
|
1918
|
-
body.set("client_id", client.client_id);
|
|
1919
|
-
};
|
|
1920
|
-
}
|
|
1921
|
-
const URLParse = URL.parse ? (url, base) => URL.parse(url, base) : (url, base) => {
|
|
1922
|
-
try {
|
|
1923
|
-
return new URL(url, base);
|
|
1924
|
-
} catch {
|
|
1925
|
-
return null;
|
|
1926
|
-
}
|
|
1927
|
-
};
|
|
1928
|
-
function checkProtocol(url, enforceHttps) {
|
|
1929
|
-
if (enforceHttps && url.protocol !== "https:") throw OPE("only requests to HTTPS are allowed", HTTP_REQUEST_FORBIDDEN, url);
|
|
1930
|
-
if (url.protocol !== "https:" && url.protocol !== "http:") throw OPE("only HTTP and HTTPS requests are allowed", REQUEST_PROTOCOL_FORBIDDEN, url);
|
|
1931
|
-
}
|
|
1932
|
-
function validateEndpoint(value, endpoint, useMtlsAlias, enforceHttps) {
|
|
1933
|
-
let url;
|
|
1934
|
-
if (typeof value !== "string" || !(url = URLParse(value))) throw OPE(`authorization server metadata does not contain a valid ${useMtlsAlias ? `"as.mtls_endpoint_aliases.${endpoint}"` : `"as.${endpoint}"`}`, value === void 0 ? MISSING_SERVER_METADATA : INVALID_SERVER_METADATA, { attribute: useMtlsAlias ? `mtls_endpoint_aliases.${endpoint}` : endpoint });
|
|
1935
|
-
checkProtocol(url, enforceHttps);
|
|
1936
|
-
return url;
|
|
1937
|
-
}
|
|
1938
|
-
function resolveEndpoint(as, endpoint, useMtlsAlias, enforceHttps) {
|
|
1939
|
-
if (useMtlsAlias && as.mtls_endpoint_aliases && endpoint in as.mtls_endpoint_aliases) return validateEndpoint(as.mtls_endpoint_aliases[endpoint], endpoint, useMtlsAlias, enforceHttps);
|
|
1940
|
-
return validateEndpoint(as[endpoint], endpoint, useMtlsAlias, enforceHttps);
|
|
1941
|
-
}
|
|
1942
|
-
function isDPoPNonceError(err) {
|
|
1943
|
-
if (err instanceof WWWAuthenticateChallengeError) {
|
|
1944
|
-
const { 0: challenge, length } = err.cause;
|
|
1945
|
-
return length === 1 && challenge.scheme === "dpop" && challenge.parameters.error === "use_dpop_nonce";
|
|
1946
|
-
}
|
|
1947
|
-
if (err instanceof ResponseBodyError) return err.error === "use_dpop_nonce";
|
|
1948
|
-
return false;
|
|
1949
|
-
}
|
|
1950
|
-
var ResponseBodyError = class extends Error {
|
|
1951
|
-
cause;
|
|
1952
|
-
code;
|
|
1953
|
-
error;
|
|
1954
|
-
status;
|
|
1955
|
-
error_description;
|
|
1956
|
-
response;
|
|
1957
|
-
constructor(message, options) {
|
|
1958
|
-
super(message, options);
|
|
1959
|
-
this.name = this.constructor.name;
|
|
1960
|
-
this.code = RESPONSE_BODY_ERROR;
|
|
1961
|
-
this.cause = options.cause;
|
|
1962
|
-
this.error = options.cause.error;
|
|
1963
|
-
this.status = options.response.status;
|
|
1964
|
-
this.error_description = options.cause.error_description;
|
|
1965
|
-
Object.defineProperty(this, "response", {
|
|
1966
|
-
enumerable: false,
|
|
1967
|
-
value: options.response
|
|
1968
|
-
});
|
|
1969
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
1970
|
-
}
|
|
1971
|
-
};
|
|
1972
|
-
var AuthorizationResponseError = class extends Error {
|
|
1973
|
-
cause;
|
|
1974
|
-
code;
|
|
1975
|
-
error;
|
|
1976
|
-
error_description;
|
|
1977
|
-
constructor(message, options) {
|
|
1978
|
-
super(message, options);
|
|
1979
|
-
this.name = this.constructor.name;
|
|
1980
|
-
this.code = AUTHORIZATION_RESPONSE_ERROR;
|
|
1981
|
-
this.cause = options.cause;
|
|
1982
|
-
this.error = options.cause.get("error");
|
|
1983
|
-
this.error_description = options.cause.get("error_description") ?? void 0;
|
|
1984
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
1985
|
-
}
|
|
1986
|
-
};
|
|
1987
|
-
var WWWAuthenticateChallengeError = class extends Error {
|
|
1988
|
-
cause;
|
|
1989
|
-
code;
|
|
1990
|
-
response;
|
|
1991
|
-
status;
|
|
1992
|
-
constructor(message, options) {
|
|
1993
|
-
super(message, options);
|
|
1994
|
-
this.name = this.constructor.name;
|
|
1995
|
-
this.code = WWW_AUTHENTICATE_CHALLENGE;
|
|
1996
|
-
this.cause = options.cause;
|
|
1997
|
-
this.status = options.response.status;
|
|
1998
|
-
this.response = options.response;
|
|
1999
|
-
Object.defineProperty(this, "response", { enumerable: false });
|
|
2000
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
2001
|
-
}
|
|
2002
|
-
};
|
|
2003
|
-
const tokenMatch = "[a-zA-Z0-9!#$%&\\'\\*\\+\\-\\.\\^_`\\|~]+";
|
|
2004
|
-
const token68Match = "[a-zA-Z0-9\\-\\._\\~\\+\\/]+[=]{0,2}";
|
|
2005
|
-
const quotedParamMatcher = "(" + tokenMatch + ")\\s*=\\s*\"((?:[^\"\\\\]|\\\\.)*)\"";
|
|
2006
|
-
const paramMatcher = "(" + tokenMatch + ")\\s*=\\s*([a-zA-Z0-9!#$%&\\'\\*\\+\\-\\.\\^_`\\|~]+)";
|
|
2007
|
-
const schemeRE = /* @__PURE__ */ new RegExp("^[,\\s]*(" + tokenMatch + ")\\s(.*)");
|
|
2008
|
-
const quotedParamRE = /* @__PURE__ */ new RegExp("^[,\\s]*" + quotedParamMatcher + "[,\\s]*(.*)");
|
|
2009
|
-
const unquotedParamRE = /* @__PURE__ */ new RegExp("^[,\\s]*" + paramMatcher + "[,\\s]*(.*)");
|
|
2010
|
-
const token68ParamRE = /* @__PURE__ */ new RegExp("^(" + token68Match + ")(?:$|[,\\s])(.*)");
|
|
2011
|
-
function parseWwwAuthenticateChallenges(response) {
|
|
2012
|
-
if (!looseInstanceOf(response, Response)) throw CodedTypeError$1("\"response\" must be an instance of Response", ERR_INVALID_ARG_TYPE$1);
|
|
2013
|
-
const header = response.headers.get("www-authenticate");
|
|
2014
|
-
if (header === null) return;
|
|
2015
|
-
const challenges = [];
|
|
2016
|
-
let rest = header;
|
|
2017
|
-
while (rest) {
|
|
2018
|
-
let match = rest.match(schemeRE);
|
|
2019
|
-
const scheme = match?.["1"].toLowerCase();
|
|
2020
|
-
rest = match?.["2"];
|
|
2021
|
-
if (!scheme) return;
|
|
2022
|
-
const parameters = {};
|
|
2023
|
-
let token68;
|
|
2024
|
-
while (rest) {
|
|
2025
|
-
let key;
|
|
2026
|
-
let value;
|
|
2027
|
-
if (match = rest.match(quotedParamRE)) {
|
|
2028
|
-
[, key, value, rest] = match;
|
|
2029
|
-
if (value.includes("\\")) try {
|
|
2030
|
-
value = JSON.parse(`"${value}"`);
|
|
2031
|
-
} catch {}
|
|
2032
|
-
parameters[key.toLowerCase()] = value;
|
|
2033
|
-
continue;
|
|
2034
|
-
}
|
|
2035
|
-
if (match = rest.match(unquotedParamRE)) {
|
|
2036
|
-
[, key, value, rest] = match;
|
|
2037
|
-
parameters[key.toLowerCase()] = value;
|
|
2038
|
-
continue;
|
|
2039
|
-
}
|
|
2040
|
-
if (match = rest.match(token68ParamRE)) {
|
|
2041
|
-
if (Object.keys(parameters).length) break;
|
|
2042
|
-
[, token68, rest] = match;
|
|
2043
|
-
break;
|
|
2044
|
-
}
|
|
2045
|
-
return;
|
|
2046
|
-
}
|
|
2047
|
-
const challenge = {
|
|
2048
|
-
scheme,
|
|
2049
|
-
parameters
|
|
2050
|
-
};
|
|
2051
|
-
if (token68) challenge.token68 = token68;
|
|
2052
|
-
challenges.push(challenge);
|
|
2053
|
-
}
|
|
2054
|
-
if (!challenges.length) return;
|
|
2055
|
-
return challenges;
|
|
2056
|
-
}
|
|
2057
|
-
async function parseOAuthResponseErrorBody(response) {
|
|
2058
|
-
if (response.status > 399 && response.status < 500) {
|
|
2059
|
-
assertReadableResponse(response);
|
|
2060
|
-
assertApplicationJson(response);
|
|
2061
|
-
try {
|
|
2062
|
-
const json = await response.clone().json();
|
|
2063
|
-
if (isJsonObject(json) && typeof json.error === "string" && json.error.length) return json;
|
|
2064
|
-
} catch {}
|
|
2065
|
-
}
|
|
2066
|
-
}
|
|
2067
|
-
async function checkOAuthBodyError(response, expected, label) {
|
|
2068
|
-
if (response.status !== expected) {
|
|
2069
|
-
checkAuthenticationChallenges(response);
|
|
2070
|
-
let err;
|
|
2071
|
-
if (err = await parseOAuthResponseErrorBody(response)) {
|
|
2072
|
-
await response.body?.cancel();
|
|
2073
|
-
throw new ResponseBodyError("server responded with an error in the response body", {
|
|
2074
|
-
cause: err,
|
|
2075
|
-
response
|
|
2076
|
-
});
|
|
2077
|
-
}
|
|
2078
|
-
throw OPE(`"response" is not a conform ${label} response (unexpected HTTP status code)`, RESPONSE_IS_NOT_CONFORM, response);
|
|
2079
|
-
}
|
|
2080
|
-
}
|
|
2081
|
-
function assertDPoP(option) {
|
|
2082
|
-
if (!branded.has(option)) throw CodedTypeError$1("\"options.DPoP\" is not a valid DPoPHandle", ERR_INVALID_ARG_VALUE$1);
|
|
2083
|
-
}
|
|
2084
|
-
const skipSubjectCheck$1 = Symbol();
|
|
2085
|
-
function getContentType(input) {
|
|
2086
|
-
return input.headers.get("content-type")?.split(";")[0];
|
|
2087
|
-
}
|
|
2088
|
-
async function authenticatedRequest(as, client, clientAuthentication, url, body, headers$1, options) {
|
|
2089
|
-
await clientAuthentication(as, client, body, headers$1);
|
|
2090
|
-
headers$1.set("content-type", "application/x-www-form-urlencoded;charset=UTF-8");
|
|
2091
|
-
return (options?.[customFetch$1] || fetch)(url.href, {
|
|
2092
|
-
body,
|
|
2093
|
-
headers: Object.fromEntries(headers$1.entries()),
|
|
2094
|
-
method: "POST",
|
|
2095
|
-
redirect: "manual",
|
|
2096
|
-
signal: signal$1(url, options?.signal)
|
|
2097
|
-
});
|
|
2098
|
-
}
|
|
2099
|
-
async function tokenEndpointRequest(as, client, clientAuthentication, grantType, parameters, options) {
|
|
2100
|
-
const url = resolveEndpoint(as, "token_endpoint", client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests$1] !== true);
|
|
2101
|
-
parameters.set("grant_type", grantType);
|
|
2102
|
-
const headers$1 = prepareHeaders(options?.headers);
|
|
2103
|
-
headers$1.set("accept", "application/json");
|
|
2104
|
-
if (options?.DPoP !== void 0) {
|
|
2105
|
-
assertDPoP(options.DPoP);
|
|
2106
|
-
await options.DPoP.addProof(url, headers$1, "POST");
|
|
2107
|
-
}
|
|
2108
|
-
const response = await authenticatedRequest(as, client, clientAuthentication, url, parameters, headers$1, options);
|
|
2109
|
-
options?.DPoP?.cacheNonce(response, url);
|
|
2110
|
-
return response;
|
|
2111
|
-
}
|
|
2112
|
-
async function refreshTokenGrantRequest(as, client, clientAuthentication, refreshToken, options) {
|
|
2113
|
-
assertAs(as);
|
|
2114
|
-
assertClient(client);
|
|
2115
|
-
assertString$1(refreshToken, "\"refreshToken\"");
|
|
2116
|
-
const parameters = new URLSearchParams(options?.additionalParameters);
|
|
2117
|
-
parameters.set("refresh_token", refreshToken);
|
|
2118
|
-
return tokenEndpointRequest(as, client, clientAuthentication, "refresh_token", parameters, options);
|
|
2119
|
-
}
|
|
2120
|
-
const idTokenClaims = /* @__PURE__ */ new WeakMap();
|
|
2121
|
-
const jwtRefs = /* @__PURE__ */ new WeakMap();
|
|
2122
|
-
function getValidatedIdTokenClaims(ref) {
|
|
2123
|
-
if (!ref.id_token) return;
|
|
2124
|
-
const claims = idTokenClaims.get(ref);
|
|
2125
|
-
if (!claims) throw CodedTypeError$1("\"ref\" was already garbage collected or did not resolve from the proper sources", ERR_INVALID_ARG_VALUE$1);
|
|
2126
|
-
return claims;
|
|
2127
|
-
}
|
|
2128
|
-
async function processGenericAccessTokenResponse(as, client, response, additionalRequiredIdTokenClaims, decryptFn, recognizedTokenTypes) {
|
|
2129
|
-
assertAs(as);
|
|
2130
|
-
assertClient(client);
|
|
2131
|
-
if (!looseInstanceOf(response, Response)) throw CodedTypeError$1("\"response\" must be an instance of Response", ERR_INVALID_ARG_TYPE$1);
|
|
2132
|
-
await checkOAuthBodyError(response, 200, "Token Endpoint");
|
|
2133
|
-
assertReadableResponse(response);
|
|
2134
|
-
const json = await getResponseJsonBody(response);
|
|
2135
|
-
assertString$1(json.access_token, "\"response\" body \"access_token\" property", INVALID_RESPONSE, { body: json });
|
|
2136
|
-
assertString$1(json.token_type, "\"response\" body \"token_type\" property", INVALID_RESPONSE, { body: json });
|
|
2137
|
-
json.token_type = json.token_type.toLowerCase();
|
|
2138
|
-
if (json.expires_in !== void 0) {
|
|
2139
|
-
let expiresIn = typeof json.expires_in !== "number" ? parseFloat(json.expires_in) : json.expires_in;
|
|
2140
|
-
assertNumber(expiresIn, true, "\"response\" body \"expires_in\" property", INVALID_RESPONSE, { body: json });
|
|
2141
|
-
json.expires_in = expiresIn;
|
|
2142
|
-
}
|
|
2143
|
-
if (json.refresh_token !== void 0) assertString$1(json.refresh_token, "\"response\" body \"refresh_token\" property", INVALID_RESPONSE, { body: json });
|
|
2144
|
-
if (json.scope !== void 0 && typeof json.scope !== "string") throw OPE("\"response\" body \"scope\" property must be a string", INVALID_RESPONSE, { body: json });
|
|
2145
|
-
if (json.id_token !== void 0) {
|
|
2146
|
-
assertString$1(json.id_token, "\"response\" body \"id_token\" property", INVALID_RESPONSE, { body: json });
|
|
2147
|
-
const requiredClaims = [
|
|
2148
|
-
"aud",
|
|
2149
|
-
"exp",
|
|
2150
|
-
"iat",
|
|
2151
|
-
"iss",
|
|
2152
|
-
"sub"
|
|
2153
|
-
];
|
|
2154
|
-
if (client.require_auth_time === true) requiredClaims.push("auth_time");
|
|
2155
|
-
if (client.default_max_age !== void 0) {
|
|
2156
|
-
assertNumber(client.default_max_age, true, "\"client.default_max_age\"");
|
|
2157
|
-
requiredClaims.push("auth_time");
|
|
2158
|
-
}
|
|
2159
|
-
if (additionalRequiredIdTokenClaims?.length) requiredClaims.push(...additionalRequiredIdTokenClaims);
|
|
2160
|
-
const { claims, jwt } = await validateJwt(json.id_token, checkSigningAlgorithm.bind(void 0, client.id_token_signed_response_alg, as.id_token_signing_alg_values_supported, "RS256"), getClockSkew(client), getClockTolerance(client), decryptFn).then(validatePresence.bind(void 0, requiredClaims)).then(validateIssuer.bind(void 0, as)).then(validateAudience.bind(void 0, client.client_id));
|
|
2161
|
-
if (Array.isArray(claims.aud) && claims.aud.length !== 1) {
|
|
2162
|
-
if (claims.azp === void 0) throw OPE("ID Token \"aud\" (audience) claim includes additional untrusted audiences", JWT_CLAIM_COMPARISON, {
|
|
2163
|
-
claims,
|
|
2164
|
-
claim: "aud"
|
|
2165
|
-
});
|
|
2166
|
-
if (claims.azp !== client.client_id) throw OPE("unexpected ID Token \"azp\" (authorized party) claim value", JWT_CLAIM_COMPARISON, {
|
|
2167
|
-
expected: client.client_id,
|
|
2168
|
-
claims,
|
|
2169
|
-
claim: "azp"
|
|
2170
|
-
});
|
|
2171
|
-
}
|
|
2172
|
-
if (claims.auth_time !== void 0) assertNumber(claims.auth_time, true, "ID Token \"auth_time\" (authentication time)", INVALID_RESPONSE, { claims });
|
|
2173
|
-
jwtRefs.set(response, jwt);
|
|
2174
|
-
idTokenClaims.set(json, claims);
|
|
2175
|
-
}
|
|
2176
|
-
if (recognizedTokenTypes?.[json.token_type] !== void 0) recognizedTokenTypes[json.token_type](response, json);
|
|
2177
|
-
else if (json.token_type !== "dpop" && json.token_type !== "bearer") throw new UnsupportedOperationError("unsupported `token_type` value", { cause: { body: json } });
|
|
2178
|
-
return json;
|
|
2179
|
-
}
|
|
2180
|
-
function checkAuthenticationChallenges(response) {
|
|
2181
|
-
let challenges;
|
|
2182
|
-
if (challenges = parseWwwAuthenticateChallenges(response)) throw new WWWAuthenticateChallengeError("server responded with a challenge in the WWW-Authenticate HTTP Header", {
|
|
2183
|
-
cause: challenges,
|
|
2184
|
-
response
|
|
2185
|
-
});
|
|
2186
|
-
}
|
|
2187
|
-
async function processRefreshTokenResponse(as, client, response, options) {
|
|
2188
|
-
return processGenericAccessTokenResponse(as, client, response, void 0, options?.[jweDecrypt], options?.recognizedTokenTypes);
|
|
2189
|
-
}
|
|
2190
|
-
function validateAudience(expected, result) {
|
|
2191
|
-
if (Array.isArray(result.claims.aud)) {
|
|
2192
|
-
if (!result.claims.aud.includes(expected)) throw OPE("unexpected JWT \"aud\" (audience) claim value", JWT_CLAIM_COMPARISON, {
|
|
2193
|
-
expected,
|
|
2194
|
-
claims: result.claims,
|
|
2195
|
-
claim: "aud"
|
|
2196
|
-
});
|
|
2197
|
-
} else if (result.claims.aud !== expected) throw OPE("unexpected JWT \"aud\" (audience) claim value", JWT_CLAIM_COMPARISON, {
|
|
2198
|
-
expected,
|
|
2199
|
-
claims: result.claims,
|
|
2200
|
-
claim: "aud"
|
|
2201
|
-
});
|
|
2202
|
-
return result;
|
|
2203
|
-
}
|
|
2204
|
-
function validateIssuer(as, result) {
|
|
2205
|
-
const expected = as[_expectedIssuer]?.(result) ?? as.issuer;
|
|
2206
|
-
if (result.claims.iss !== expected) throw OPE("unexpected JWT \"iss\" (issuer) claim value", JWT_CLAIM_COMPARISON, {
|
|
2207
|
-
expected,
|
|
2208
|
-
claims: result.claims,
|
|
2209
|
-
claim: "iss"
|
|
2210
|
-
});
|
|
2211
|
-
return result;
|
|
2212
|
-
}
|
|
2213
|
-
const branded = /* @__PURE__ */ new WeakSet();
|
|
2214
|
-
function brand(searchParams) {
|
|
2215
|
-
branded.add(searchParams);
|
|
2216
|
-
return searchParams;
|
|
2217
|
-
}
|
|
2218
|
-
const nopkce = Symbol();
|
|
2219
|
-
async function authorizationCodeGrantRequest(as, client, clientAuthentication, callbackParameters, redirectUri, codeVerifier, options) {
|
|
2220
|
-
assertAs(as);
|
|
2221
|
-
assertClient(client);
|
|
2222
|
-
if (!branded.has(callbackParameters)) throw CodedTypeError$1("\"callbackParameters\" must be an instance of URLSearchParams obtained from \"validateAuthResponse()\", or \"validateJwtAuthResponse()", ERR_INVALID_ARG_VALUE$1);
|
|
2223
|
-
assertString$1(redirectUri, "\"redirectUri\"");
|
|
2224
|
-
const code = getURLSearchParameter(callbackParameters, "code");
|
|
2225
|
-
if (!code) throw OPE("no authorization code in \"callbackParameters\"", INVALID_RESPONSE);
|
|
2226
|
-
const parameters = new URLSearchParams(options?.additionalParameters);
|
|
2227
|
-
parameters.set("redirect_uri", redirectUri);
|
|
2228
|
-
parameters.set("code", code);
|
|
2229
|
-
if (codeVerifier !== nopkce) {
|
|
2230
|
-
assertString$1(codeVerifier, "\"codeVerifier\"");
|
|
2231
|
-
parameters.set("code_verifier", codeVerifier);
|
|
2232
|
-
}
|
|
2233
|
-
return tokenEndpointRequest(as, client, clientAuthentication, "authorization_code", parameters, options);
|
|
2234
|
-
}
|
|
2235
|
-
const jwtClaimNames = {
|
|
2236
|
-
aud: "audience",
|
|
2237
|
-
c_hash: "code hash",
|
|
2238
|
-
client_id: "client id",
|
|
2239
|
-
exp: "expiration time",
|
|
2240
|
-
iat: "issued at",
|
|
2241
|
-
iss: "issuer",
|
|
2242
|
-
jti: "jwt id",
|
|
2243
|
-
nonce: "nonce",
|
|
2244
|
-
s_hash: "state hash",
|
|
2245
|
-
sub: "subject",
|
|
2246
|
-
ath: "access token hash",
|
|
2247
|
-
htm: "http method",
|
|
2248
|
-
htu: "http uri",
|
|
2249
|
-
cnf: "confirmation",
|
|
2250
|
-
auth_time: "authentication time"
|
|
2251
|
-
};
|
|
2252
|
-
function validatePresence(required, result) {
|
|
2253
|
-
for (const claim of required) if (result.claims[claim] === void 0) throw OPE(`JWT "${claim}" (${jwtClaimNames[claim]}) claim missing`, INVALID_RESPONSE, { claims: result.claims });
|
|
2254
|
-
return result;
|
|
2255
|
-
}
|
|
2256
|
-
const expectNoNonce = Symbol();
|
|
2257
|
-
const skipAuthTimeCheck = Symbol();
|
|
2258
|
-
async function processAuthorizationCodeResponse(as, client, response, options) {
|
|
2259
|
-
if (typeof options?.expectedNonce === "string" || typeof options?.maxAge === "number" || options?.requireIdToken) return processAuthorizationCodeOpenIDResponse(as, client, response, options.expectedNonce, options.maxAge, options[jweDecrypt], options.recognizedTokenTypes);
|
|
2260
|
-
return processAuthorizationCodeOAuth2Response(as, client, response, options?.[jweDecrypt], options?.recognizedTokenTypes);
|
|
2261
|
-
}
|
|
2262
|
-
async function processAuthorizationCodeOpenIDResponse(as, client, response, expectedNonce, maxAge, decryptFn, recognizedTokenTypes) {
|
|
2263
|
-
const additionalRequiredClaims = [];
|
|
2264
|
-
switch (expectedNonce) {
|
|
2265
|
-
case void 0:
|
|
2266
|
-
expectedNonce = expectNoNonce;
|
|
2267
|
-
break;
|
|
2268
|
-
case expectNoNonce: break;
|
|
2269
|
-
default:
|
|
2270
|
-
assertString$1(expectedNonce, "\"expectedNonce\" argument");
|
|
2271
|
-
additionalRequiredClaims.push("nonce");
|
|
2272
|
-
}
|
|
2273
|
-
maxAge ??= client.default_max_age;
|
|
2274
|
-
switch (maxAge) {
|
|
2275
|
-
case void 0:
|
|
2276
|
-
maxAge = skipAuthTimeCheck;
|
|
2277
|
-
break;
|
|
2278
|
-
case skipAuthTimeCheck: break;
|
|
2279
|
-
default:
|
|
2280
|
-
assertNumber(maxAge, true, "\"maxAge\" argument");
|
|
2281
|
-
additionalRequiredClaims.push("auth_time");
|
|
2282
|
-
}
|
|
2283
|
-
const result = await processGenericAccessTokenResponse(as, client, response, additionalRequiredClaims, decryptFn, recognizedTokenTypes);
|
|
2284
|
-
assertString$1(result.id_token, "\"response\" body \"id_token\" property", INVALID_RESPONSE, { body: result });
|
|
2285
|
-
const claims = getValidatedIdTokenClaims(result);
|
|
2286
|
-
if (maxAge !== skipAuthTimeCheck) {
|
|
2287
|
-
const now = epochTime() + getClockSkew(client);
|
|
2288
|
-
const tolerance = getClockTolerance(client);
|
|
2289
|
-
if (claims.auth_time + maxAge < now - tolerance) throw OPE("too much time has elapsed since the last End-User authentication", JWT_TIMESTAMP_CHECK, {
|
|
2290
|
-
claims,
|
|
2291
|
-
now,
|
|
2292
|
-
tolerance,
|
|
2293
|
-
claim: "auth_time"
|
|
2294
|
-
});
|
|
2295
|
-
}
|
|
2296
|
-
if (expectedNonce === expectNoNonce) {
|
|
2297
|
-
if (claims.nonce !== void 0) throw OPE("unexpected ID Token \"nonce\" claim value", JWT_CLAIM_COMPARISON, {
|
|
2298
|
-
expected: void 0,
|
|
2299
|
-
claims,
|
|
2300
|
-
claim: "nonce"
|
|
2301
|
-
});
|
|
2302
|
-
} else if (claims.nonce !== expectedNonce) throw OPE("unexpected ID Token \"nonce\" claim value", JWT_CLAIM_COMPARISON, {
|
|
2303
|
-
expected: expectedNonce,
|
|
2304
|
-
claims,
|
|
2305
|
-
claim: "nonce"
|
|
2306
|
-
});
|
|
2307
|
-
return result;
|
|
2308
|
-
}
|
|
2309
|
-
async function processAuthorizationCodeOAuth2Response(as, client, response, decryptFn, recognizedTokenTypes) {
|
|
2310
|
-
const result = await processGenericAccessTokenResponse(as, client, response, void 0, decryptFn, recognizedTokenTypes);
|
|
2311
|
-
const claims = getValidatedIdTokenClaims(result);
|
|
2312
|
-
if (claims) {
|
|
2313
|
-
if (client.default_max_age !== void 0) {
|
|
2314
|
-
assertNumber(client.default_max_age, true, "\"client.default_max_age\"");
|
|
2315
|
-
const now = epochTime() + getClockSkew(client);
|
|
2316
|
-
const tolerance = getClockTolerance(client);
|
|
2317
|
-
if (claims.auth_time + client.default_max_age < now - tolerance) throw OPE("too much time has elapsed since the last End-User authentication", JWT_TIMESTAMP_CHECK, {
|
|
2318
|
-
claims,
|
|
2319
|
-
now,
|
|
2320
|
-
tolerance,
|
|
2321
|
-
claim: "auth_time"
|
|
2322
|
-
});
|
|
2323
|
-
}
|
|
2324
|
-
if (claims.nonce !== void 0) throw OPE("unexpected ID Token \"nonce\" claim value", JWT_CLAIM_COMPARISON, {
|
|
2325
|
-
expected: void 0,
|
|
2326
|
-
claims,
|
|
2327
|
-
claim: "nonce"
|
|
2328
|
-
});
|
|
2329
|
-
}
|
|
2330
|
-
return result;
|
|
2331
|
-
}
|
|
2332
|
-
const WWW_AUTHENTICATE_CHALLENGE = "OAUTH_WWW_AUTHENTICATE_CHALLENGE";
|
|
2333
|
-
const RESPONSE_BODY_ERROR = "OAUTH_RESPONSE_BODY_ERROR";
|
|
2334
|
-
const UNSUPPORTED_OPERATION = "OAUTH_UNSUPPORTED_OPERATION";
|
|
2335
|
-
const AUTHORIZATION_RESPONSE_ERROR = "OAUTH_AUTHORIZATION_RESPONSE_ERROR";
|
|
2336
|
-
const PARSE_ERROR = "OAUTH_PARSE_ERROR";
|
|
2337
|
-
const INVALID_RESPONSE = "OAUTH_INVALID_RESPONSE";
|
|
2338
|
-
const RESPONSE_IS_NOT_JSON = "OAUTH_RESPONSE_IS_NOT_JSON";
|
|
2339
|
-
const RESPONSE_IS_NOT_CONFORM = "OAUTH_RESPONSE_IS_NOT_CONFORM";
|
|
2340
|
-
const HTTP_REQUEST_FORBIDDEN = "OAUTH_HTTP_REQUEST_FORBIDDEN";
|
|
2341
|
-
const REQUEST_PROTOCOL_FORBIDDEN = "OAUTH_REQUEST_PROTOCOL_FORBIDDEN";
|
|
2342
|
-
const JWT_TIMESTAMP_CHECK = "OAUTH_JWT_TIMESTAMP_CHECK_FAILED";
|
|
2343
|
-
const JWT_CLAIM_COMPARISON = "OAUTH_JWT_CLAIM_COMPARISON_FAILED";
|
|
2344
|
-
const JSON_ATTRIBUTE_COMPARISON = "OAUTH_JSON_ATTRIBUTE_COMPARISON_FAILED";
|
|
2345
|
-
const MISSING_SERVER_METADATA = "OAUTH_MISSING_SERVER_METADATA";
|
|
2346
|
-
const INVALID_SERVER_METADATA = "OAUTH_INVALID_SERVER_METADATA";
|
|
2347
|
-
function assertReadableResponse(response) {
|
|
2348
|
-
if (response.bodyUsed) throw CodedTypeError$1("\"response\" body has been used already", ERR_INVALID_ARG_VALUE$1);
|
|
2349
|
-
}
|
|
2350
|
-
async function validateJwt(jws, checkAlg, clockSkew$2, clockTolerance$2, decryptJwt) {
|
|
2351
|
-
let { 0: protectedHeader, 1: payload, length } = jws.split(".");
|
|
2352
|
-
if (length === 5) if (decryptJwt !== void 0) {
|
|
2353
|
-
jws = await decryptJwt(jws);
|
|
2354
|
-
({0: protectedHeader, 1: payload, length} = jws.split("."));
|
|
2355
|
-
} else throw new UnsupportedOperationError("JWE decryption is not configured", { cause: jws });
|
|
2356
|
-
if (length !== 3) throw OPE("Invalid JWT", INVALID_RESPONSE, jws);
|
|
2357
|
-
let header;
|
|
2358
|
-
try {
|
|
2359
|
-
header = JSON.parse(buf(b64u(protectedHeader)));
|
|
2360
|
-
} catch (cause) {
|
|
2361
|
-
throw OPE("failed to parse JWT Header body as base64url encoded JSON", PARSE_ERROR, cause);
|
|
2362
|
-
}
|
|
2363
|
-
if (!isJsonObject(header)) throw OPE("JWT Header must be a top level object", INVALID_RESPONSE, jws);
|
|
2364
|
-
checkAlg(header);
|
|
2365
|
-
if (header.crit !== void 0) throw new UnsupportedOperationError("no JWT \"crit\" header parameter extensions are supported", { cause: { header } });
|
|
2366
|
-
let claims;
|
|
2367
|
-
try {
|
|
2368
|
-
claims = JSON.parse(buf(b64u(payload)));
|
|
2369
|
-
} catch (cause) {
|
|
2370
|
-
throw OPE("failed to parse JWT Payload body as base64url encoded JSON", PARSE_ERROR, cause);
|
|
2371
|
-
}
|
|
2372
|
-
if (!isJsonObject(claims)) throw OPE("JWT Payload must be a top level object", INVALID_RESPONSE, jws);
|
|
2373
|
-
const now = epochTime() + clockSkew$2;
|
|
2374
|
-
if (claims.exp !== void 0) {
|
|
2375
|
-
if (typeof claims.exp !== "number") throw OPE("unexpected JWT \"exp\" (expiration time) claim type", INVALID_RESPONSE, { claims });
|
|
2376
|
-
if (claims.exp <= now - clockTolerance$2) throw OPE("unexpected JWT \"exp\" (expiration time) claim value, expiration is past current timestamp", JWT_TIMESTAMP_CHECK, {
|
|
2377
|
-
claims,
|
|
2378
|
-
now,
|
|
2379
|
-
tolerance: clockTolerance$2,
|
|
2380
|
-
claim: "exp"
|
|
2381
|
-
});
|
|
2382
|
-
}
|
|
2383
|
-
if (claims.iat !== void 0) {
|
|
2384
|
-
if (typeof claims.iat !== "number") throw OPE("unexpected JWT \"iat\" (issued at) claim type", INVALID_RESPONSE, { claims });
|
|
2385
|
-
}
|
|
2386
|
-
if (claims.iss !== void 0) {
|
|
2387
|
-
if (typeof claims.iss !== "string") throw OPE("unexpected JWT \"iss\" (issuer) claim type", INVALID_RESPONSE, { claims });
|
|
2388
|
-
}
|
|
2389
|
-
if (claims.nbf !== void 0) {
|
|
2390
|
-
if (typeof claims.nbf !== "number") throw OPE("unexpected JWT \"nbf\" (not before) claim type", INVALID_RESPONSE, { claims });
|
|
2391
|
-
if (claims.nbf > now + clockTolerance$2) throw OPE("unexpected JWT \"nbf\" (not before) claim value", JWT_TIMESTAMP_CHECK, {
|
|
2392
|
-
claims,
|
|
2393
|
-
now,
|
|
2394
|
-
tolerance: clockTolerance$2,
|
|
2395
|
-
claim: "nbf"
|
|
2396
|
-
});
|
|
2397
|
-
}
|
|
2398
|
-
if (claims.aud !== void 0) {
|
|
2399
|
-
if (typeof claims.aud !== "string" && !Array.isArray(claims.aud)) throw OPE("unexpected JWT \"aud\" (audience) claim type", INVALID_RESPONSE, { claims });
|
|
2400
|
-
}
|
|
2401
|
-
return {
|
|
2402
|
-
header,
|
|
2403
|
-
claims,
|
|
2404
|
-
jwt: jws
|
|
2405
|
-
};
|
|
2406
|
-
}
|
|
2407
|
-
async function consumeStream(request) {
|
|
2408
|
-
if (request.bodyUsed) throw CodedTypeError$1("form_post Request instances must contain a readable body", ERR_INVALID_ARG_VALUE$1, { cause: request });
|
|
2409
|
-
return request.text();
|
|
2410
|
-
}
|
|
2411
|
-
async function formPostResponse(request) {
|
|
2412
|
-
if (request.method !== "POST") throw CodedTypeError$1("form_post responses are expected to use the POST method", ERR_INVALID_ARG_VALUE$1, { cause: request });
|
|
2413
|
-
if (getContentType(request) !== "application/x-www-form-urlencoded") throw CodedTypeError$1("form_post responses are expected to use the application/x-www-form-urlencoded content-type", ERR_INVALID_ARG_VALUE$1, { cause: request });
|
|
2414
|
-
return consumeStream(request);
|
|
2415
|
-
}
|
|
2416
|
-
function checkSigningAlgorithm(client, issuer, fallback, header) {
|
|
2417
|
-
if (client !== void 0) {
|
|
2418
|
-
if (typeof client === "string" ? header.alg !== client : !client.includes(header.alg)) throw OPE("unexpected JWT \"alg\" header parameter", INVALID_RESPONSE, {
|
|
2419
|
-
header,
|
|
2420
|
-
expected: client,
|
|
2421
|
-
reason: "client configuration"
|
|
2422
|
-
});
|
|
2423
|
-
return;
|
|
2424
|
-
}
|
|
2425
|
-
if (Array.isArray(issuer)) {
|
|
2426
|
-
if (!issuer.includes(header.alg)) throw OPE("unexpected JWT \"alg\" header parameter", INVALID_RESPONSE, {
|
|
2427
|
-
header,
|
|
2428
|
-
expected: issuer,
|
|
2429
|
-
reason: "authorization server metadata"
|
|
2430
|
-
});
|
|
2431
|
-
return;
|
|
2432
|
-
}
|
|
2433
|
-
if (fallback !== void 0) {
|
|
2434
|
-
if (typeof fallback === "string" ? header.alg !== fallback : typeof fallback === "function" ? !fallback(header.alg) : !fallback.includes(header.alg)) throw OPE("unexpected JWT \"alg\" header parameter", INVALID_RESPONSE, {
|
|
2435
|
-
header,
|
|
2436
|
-
expected: fallback,
|
|
2437
|
-
reason: "default value"
|
|
2438
|
-
});
|
|
2439
|
-
return;
|
|
2440
|
-
}
|
|
2441
|
-
throw OPE("missing client or server configuration to verify used JWT \"alg\" header parameter", void 0, {
|
|
2442
|
-
client,
|
|
2443
|
-
issuer,
|
|
2444
|
-
fallback
|
|
2445
|
-
});
|
|
2446
|
-
}
|
|
2447
|
-
function getURLSearchParameter(parameters, name) {
|
|
2448
|
-
const { 0: value, length } = parameters.getAll(name);
|
|
2449
|
-
if (length > 1) throw OPE(`"${name}" parameter must be provided only once`, INVALID_RESPONSE);
|
|
2450
|
-
return value;
|
|
2451
|
-
}
|
|
2452
|
-
const skipStateCheck$1 = Symbol();
|
|
2453
|
-
const expectNoState = Symbol();
|
|
2454
|
-
function validateAuthResponse(as, client, parameters, expectedState) {
|
|
2455
|
-
assertAs(as);
|
|
2456
|
-
assertClient(client);
|
|
2457
|
-
if (parameters instanceof URL) parameters = parameters.searchParams;
|
|
2458
|
-
if (!(parameters instanceof URLSearchParams)) throw CodedTypeError$1("\"parameters\" must be an instance of URLSearchParams, or URL", ERR_INVALID_ARG_TYPE$1);
|
|
2459
|
-
if (getURLSearchParameter(parameters, "response")) throw OPE("\"parameters\" contains a JARM response, use validateJwtAuthResponse() instead of validateAuthResponse()", INVALID_RESPONSE, { parameters });
|
|
2460
|
-
const iss = getURLSearchParameter(parameters, "iss");
|
|
2461
|
-
const state = getURLSearchParameter(parameters, "state");
|
|
2462
|
-
if (!iss && as.authorization_response_iss_parameter_supported) throw OPE("response parameter \"iss\" (issuer) missing", INVALID_RESPONSE, { parameters });
|
|
2463
|
-
if (iss && iss !== as.issuer) throw OPE("unexpected \"iss\" (issuer) response parameter value", INVALID_RESPONSE, {
|
|
2464
|
-
expected: as.issuer,
|
|
2465
|
-
parameters
|
|
2466
|
-
});
|
|
2467
|
-
switch (expectedState) {
|
|
2468
|
-
case void 0:
|
|
2469
|
-
case expectNoState:
|
|
2470
|
-
if (state !== void 0) throw OPE("unexpected \"state\" response parameter encountered", INVALID_RESPONSE, {
|
|
2471
|
-
expected: void 0,
|
|
2472
|
-
parameters
|
|
2473
|
-
});
|
|
2474
|
-
break;
|
|
2475
|
-
case skipStateCheck$1: break;
|
|
2476
|
-
default:
|
|
2477
|
-
assertString$1(expectedState, "\"expectedState\" argument");
|
|
2478
|
-
if (state !== expectedState) throw OPE(state === void 0 ? "response parameter \"state\" missing" : "unexpected \"state\" response parameter value", INVALID_RESPONSE, {
|
|
2479
|
-
expected: expectedState,
|
|
2480
|
-
parameters
|
|
2481
|
-
});
|
|
2482
|
-
}
|
|
2483
|
-
if (getURLSearchParameter(parameters, "error")) throw new AuthorizationResponseError("authorization response from the server is an error", { cause: parameters });
|
|
2484
|
-
const id_token = getURLSearchParameter(parameters, "id_token");
|
|
2485
|
-
const token = getURLSearchParameter(parameters, "token");
|
|
2486
|
-
if (id_token !== void 0 || token !== void 0) throw new UnsupportedOperationError("implicit and hybrid flows are not supported");
|
|
2487
|
-
return brand(new URLSearchParams(parameters));
|
|
2488
|
-
}
|
|
2489
|
-
async function getResponseJsonBody(response, check = assertApplicationJson) {
|
|
2490
|
-
let json;
|
|
2491
|
-
try {
|
|
2492
|
-
json = await response.json();
|
|
2493
|
-
} catch (cause) {
|
|
2494
|
-
check(response);
|
|
2495
|
-
throw OPE("failed to parse \"response\" body as JSON", PARSE_ERROR, cause);
|
|
2496
|
-
}
|
|
2497
|
-
if (!isJsonObject(json)) throw OPE("\"response\" body must be a top level object", INVALID_RESPONSE, { body: json });
|
|
2498
|
-
return json;
|
|
2499
|
-
}
|
|
2500
|
-
const _nodiscoverycheck = Symbol();
|
|
2501
|
-
const _expectedIssuer = Symbol();
|
|
2502
|
-
|
|
2503
|
-
//#endregion
|
|
2504
|
-
//#region ../../node_modules/openid-client/build/index.js
|
|
2505
|
-
let headers;
|
|
2506
|
-
let USER_AGENT;
|
|
2507
|
-
if (typeof navigator === "undefined" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) {
|
|
2508
|
-
USER_AGENT = `openid-client/v6.8.1`;
|
|
2509
|
-
headers = { "user-agent": USER_AGENT };
|
|
2510
|
-
}
|
|
2511
|
-
const int = (config) => {
|
|
2512
|
-
return props.get(config);
|
|
2513
|
-
};
|
|
2514
|
-
let props;
|
|
2515
|
-
let tbi;
|
|
2516
|
-
function ClientSecretPost(clientSecret) {
|
|
2517
|
-
if (clientSecret !== void 0) return ClientSecretPost$1(clientSecret);
|
|
2518
|
-
tbi ||= /* @__PURE__ */ new WeakMap();
|
|
2519
|
-
return (as, client, body, headers$1) => {
|
|
2520
|
-
let auth;
|
|
2521
|
-
if (!(auth = tbi.get(client))) {
|
|
2522
|
-
assertString(client.client_secret, "\"metadata.client_secret\"");
|
|
2523
|
-
auth = ClientSecretPost$1(client.client_secret);
|
|
2524
|
-
tbi.set(client, auth);
|
|
2525
|
-
}
|
|
2526
|
-
return auth(as, client, body, headers$1);
|
|
2527
|
-
};
|
|
2528
|
-
}
|
|
2529
|
-
function assertString(input, it) {
|
|
2530
|
-
if (typeof input !== "string") throw CodedTypeError(`${it} must be a string`, ERR_INVALID_ARG_TYPE);
|
|
2531
|
-
if (input.length === 0) throw CodedTypeError(`${it} must not be empty`, ERR_INVALID_ARG_VALUE);
|
|
2532
|
-
}
|
|
2533
|
-
function None() {
|
|
2534
|
-
return None$1();
|
|
2535
|
-
}
|
|
2536
|
-
const skipStateCheck = skipStateCheck$1;
|
|
2537
|
-
const skipSubjectCheck = skipSubjectCheck$1;
|
|
2538
|
-
const customFetch = customFetch$1;
|
|
2539
|
-
const modifyAssertion = modifyAssertion$1;
|
|
2540
|
-
const clockSkew = clockSkew$1;
|
|
2541
|
-
const clockTolerance = clockTolerance$1;
|
|
2542
|
-
const ERR_INVALID_ARG_VALUE = "ERR_INVALID_ARG_VALUE";
|
|
2543
|
-
const ERR_INVALID_ARG_TYPE = "ERR_INVALID_ARG_TYPE";
|
|
2544
|
-
function CodedTypeError(message, code, cause) {
|
|
2545
|
-
const err = new TypeError(message, { cause });
|
|
2546
|
-
Object.assign(err, { code });
|
|
2547
|
-
return err;
|
|
2548
|
-
}
|
|
2549
|
-
function calculatePKCECodeChallenge(codeVerifier) {
|
|
2550
|
-
return calculatePKCECodeChallenge$1(codeVerifier);
|
|
2551
|
-
}
|
|
2552
|
-
function randomPKCECodeVerifier() {
|
|
2553
|
-
return generateRandomCodeVerifier();
|
|
2554
|
-
}
|
|
2555
|
-
function randomState() {
|
|
2556
|
-
return generateRandomState();
|
|
2557
|
-
}
|
|
2558
|
-
var ClientError = class extends Error {
|
|
2559
|
-
code;
|
|
2560
|
-
constructor(message, options) {
|
|
2561
|
-
super(message, options);
|
|
2562
|
-
this.name = this.constructor.name;
|
|
2563
|
-
this.code = options?.code;
|
|
2564
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
2565
|
-
}
|
|
2566
|
-
};
|
|
2567
|
-
const decoder = new TextDecoder();
|
|
2568
|
-
function e(msg, cause, code) {
|
|
2569
|
-
return new ClientError(msg, {
|
|
2570
|
-
cause,
|
|
2571
|
-
code
|
|
2572
|
-
});
|
|
2573
|
-
}
|
|
2574
|
-
function errorHandler(err) {
|
|
2575
|
-
if (err instanceof TypeError || err instanceof ClientError || err instanceof ResponseBodyError || err instanceof AuthorizationResponseError || err instanceof WWWAuthenticateChallengeError) throw err;
|
|
2576
|
-
if (err instanceof OperationProcessingError) switch (err.code) {
|
|
2577
|
-
case HTTP_REQUEST_FORBIDDEN: throw e("only requests to HTTPS are allowed", err, err.code);
|
|
2578
|
-
case REQUEST_PROTOCOL_FORBIDDEN: throw e("only requests to HTTP or HTTPS are allowed", err, err.code);
|
|
2579
|
-
case RESPONSE_IS_NOT_CONFORM: throw e("unexpected HTTP response status code", err.cause, err.code);
|
|
2580
|
-
case RESPONSE_IS_NOT_JSON: throw e("unexpected response content-type", err.cause, err.code);
|
|
2581
|
-
case PARSE_ERROR: throw e("parsing error occured", err, err.code);
|
|
2582
|
-
case INVALID_RESPONSE: throw e("invalid response encountered", err, err.code);
|
|
2583
|
-
case JWT_CLAIM_COMPARISON: throw e("unexpected JWT claim value encountered", err, err.code);
|
|
2584
|
-
case JSON_ATTRIBUTE_COMPARISON: throw e("unexpected JSON attribute value encountered", err, err.code);
|
|
2585
|
-
case JWT_TIMESTAMP_CHECK: throw e("JWT timestamp claim value failed validation", err, err.code);
|
|
2586
|
-
default: throw e(err.message, err, err.code);
|
|
2587
|
-
}
|
|
2588
|
-
if (err instanceof UnsupportedOperationError) throw e("unsupported operation", err, err.code);
|
|
2589
|
-
if (err instanceof DOMException) switch (err.name) {
|
|
2590
|
-
case "OperationError": throw e("runtime operation error", err, UNSUPPORTED_OPERATION);
|
|
2591
|
-
case "NotSupportedError": throw e("runtime unsupported operation", err, UNSUPPORTED_OPERATION);
|
|
2592
|
-
case "TimeoutError": throw e("operation timed out", err, "OAUTH_TIMEOUT");
|
|
2593
|
-
case "AbortError": throw e("operation aborted", err, "OAUTH_ABORT");
|
|
2594
|
-
}
|
|
2595
|
-
throw new ClientError("something went wrong", { cause: err });
|
|
2596
|
-
}
|
|
2597
|
-
function handleEntraId(server, as, options) {
|
|
2598
|
-
if (server.origin === "https://login.microsoftonline.com" && (!options?.algorithm || options.algorithm === "oidc")) {
|
|
2599
|
-
as[kEntraId] = true;
|
|
2600
|
-
return true;
|
|
2601
|
-
}
|
|
2602
|
-
return false;
|
|
2603
|
-
}
|
|
2604
|
-
function handleB2Clogin(server, options) {
|
|
2605
|
-
if (server.hostname.endsWith(".b2clogin.com") && (!options?.algorithm || options.algorithm === "oidc")) return true;
|
|
2606
|
-
return false;
|
|
2607
|
-
}
|
|
2608
|
-
async function discovery(server, clientId, metadata, clientAuthentication, options) {
|
|
2609
|
-
const instance = new Configuration(await performDiscovery(server, options), clientId, metadata, clientAuthentication);
|
|
2610
|
-
let internals = int(instance);
|
|
2611
|
-
if (options?.[customFetch]) internals.fetch = options[customFetch];
|
|
2612
|
-
if (options?.timeout) internals.timeout = options.timeout;
|
|
2613
|
-
if (options?.execute) for (const extension of options.execute) extension(instance);
|
|
2614
|
-
return instance;
|
|
2615
|
-
}
|
|
2616
|
-
async function performDiscovery(server, options) {
|
|
2617
|
-
if (!(server instanceof URL)) throw CodedTypeError("\"server\" must be an instance of URL", ERR_INVALID_ARG_TYPE);
|
|
2618
|
-
const resolve = !server.href.includes("/.well-known/");
|
|
2619
|
-
const timeout = options?.timeout ?? 30;
|
|
2620
|
-
const signal$2 = AbortSignal.timeout(timeout * 1e3);
|
|
2621
|
-
const as = await (resolve ? discoveryRequest(server, {
|
|
2622
|
-
algorithm: options?.algorithm,
|
|
2623
|
-
[customFetch$1]: options?.[customFetch],
|
|
2624
|
-
[allowInsecureRequests$1]: options?.execute?.includes(allowInsecureRequests),
|
|
2625
|
-
signal: signal$2,
|
|
2626
|
-
headers: new Headers(headers)
|
|
2627
|
-
}) : (options?.[customFetch] || fetch)((() => {
|
|
2628
|
-
checkProtocol(server, options?.execute?.includes(allowInsecureRequests) ? false : true);
|
|
2629
|
-
return server.href;
|
|
2630
|
-
})(), {
|
|
2631
|
-
headers: Object.fromEntries(new Headers({
|
|
2632
|
-
accept: "application/json",
|
|
2633
|
-
...headers
|
|
2634
|
-
}).entries()),
|
|
2635
|
-
body: void 0,
|
|
2636
|
-
method: "GET",
|
|
2637
|
-
redirect: "manual",
|
|
2638
|
-
signal: signal$2
|
|
2639
|
-
})).then((response) => processDiscoveryResponse(_nodiscoverycheck, response)).catch(errorHandler);
|
|
2640
|
-
if (resolve && new URL(as.issuer).href !== server.href) handleEntraId(server, as, options) || handleB2Clogin(server, options) || (() => {
|
|
2641
|
-
throw new ClientError("discovered metadata issuer does not match the expected issuer", {
|
|
2642
|
-
code: JSON_ATTRIBUTE_COMPARISON,
|
|
2643
|
-
cause: {
|
|
2644
|
-
expected: server.href,
|
|
2645
|
-
body: as,
|
|
2646
|
-
attribute: "issuer"
|
|
2647
|
-
}
|
|
2648
|
-
});
|
|
2649
|
-
})();
|
|
2650
|
-
return as;
|
|
2651
|
-
}
|
|
2652
|
-
function getServerHelpers(metadata) {
|
|
2653
|
-
return { supportsPKCE: {
|
|
2654
|
-
__proto__: null,
|
|
2655
|
-
value(method = "S256") {
|
|
2656
|
-
return metadata.code_challenge_methods_supported?.includes(method) === true;
|
|
2657
|
-
}
|
|
2658
|
-
} };
|
|
2659
|
-
}
|
|
2660
|
-
function addServerHelpers(metadata) {
|
|
2661
|
-
Object.defineProperties(metadata, getServerHelpers(metadata));
|
|
2662
|
-
}
|
|
2663
|
-
const kEntraId = Symbol();
|
|
2664
|
-
var Configuration = class {
|
|
2665
|
-
constructor(server, clientId, metadata, clientAuthentication) {
|
|
2666
|
-
if (typeof clientId !== "string" || !clientId.length) throw CodedTypeError("\"clientId\" must be a non-empty string", ERR_INVALID_ARG_TYPE);
|
|
2667
|
-
if (typeof metadata === "string") metadata = { client_secret: metadata };
|
|
2668
|
-
if (metadata?.client_id !== void 0 && clientId !== metadata.client_id) throw CodedTypeError("\"clientId\" and \"metadata.client_id\" must be the same", ERR_INVALID_ARG_VALUE);
|
|
2669
|
-
const client = {
|
|
2670
|
-
...structuredClone(metadata),
|
|
2671
|
-
client_id: clientId
|
|
2672
|
-
};
|
|
2673
|
-
client[clockSkew$1] = metadata?.[clockSkew$1] ?? 0;
|
|
2674
|
-
client[clockTolerance$1] = metadata?.[clockTolerance$1] ?? 30;
|
|
2675
|
-
let auth;
|
|
2676
|
-
if (clientAuthentication) auth = clientAuthentication;
|
|
2677
|
-
else if (typeof client.client_secret === "string" && client.client_secret.length) auth = ClientSecretPost(client.client_secret);
|
|
2678
|
-
else auth = None();
|
|
2679
|
-
let c = Object.freeze(client);
|
|
2680
|
-
const clone = structuredClone(server);
|
|
2681
|
-
if (kEntraId in server) clone[_expectedIssuer] = ({ claims: { tid } }) => server.issuer.replace("{tenantid}", tid);
|
|
2682
|
-
let as = Object.freeze(clone);
|
|
2683
|
-
props ||= /* @__PURE__ */ new WeakMap();
|
|
2684
|
-
props.set(this, {
|
|
2685
|
-
__proto__: null,
|
|
2686
|
-
as,
|
|
2687
|
-
c,
|
|
2688
|
-
auth,
|
|
2689
|
-
tlsOnly: true,
|
|
2690
|
-
jwksCache: {}
|
|
2691
|
-
});
|
|
2692
|
-
}
|
|
2693
|
-
serverMetadata() {
|
|
2694
|
-
const metadata = structuredClone(int(this).as);
|
|
2695
|
-
addServerHelpers(metadata);
|
|
2696
|
-
return metadata;
|
|
2697
|
-
}
|
|
2698
|
-
clientMetadata() {
|
|
2699
|
-
return structuredClone(int(this).c);
|
|
2700
|
-
}
|
|
2701
|
-
get timeout() {
|
|
2702
|
-
return int(this).timeout;
|
|
2703
|
-
}
|
|
2704
|
-
set timeout(value) {
|
|
2705
|
-
int(this).timeout = value;
|
|
2706
|
-
}
|
|
2707
|
-
get [customFetch]() {
|
|
2708
|
-
return int(this).fetch;
|
|
2709
|
-
}
|
|
2710
|
-
set [customFetch](value) {
|
|
2711
|
-
int(this).fetch = value;
|
|
2712
|
-
}
|
|
2713
|
-
};
|
|
2714
|
-
Object.freeze(Configuration.prototype);
|
|
2715
|
-
function getHelpers(response) {
|
|
2716
|
-
let exp = void 0;
|
|
2717
|
-
if (response.expires_in !== void 0) {
|
|
2718
|
-
const now = /* @__PURE__ */ new Date();
|
|
2719
|
-
now.setSeconds(now.getSeconds() + response.expires_in);
|
|
2720
|
-
exp = now.getTime();
|
|
2721
|
-
}
|
|
2722
|
-
return {
|
|
2723
|
-
expiresIn: {
|
|
2724
|
-
__proto__: null,
|
|
2725
|
-
value() {
|
|
2726
|
-
if (exp) {
|
|
2727
|
-
const now = Date.now();
|
|
2728
|
-
if (exp > now) return Math.floor((exp - now) / 1e3);
|
|
2729
|
-
return 0;
|
|
2730
|
-
}
|
|
2731
|
-
}
|
|
2732
|
-
},
|
|
2733
|
-
claims: {
|
|
2734
|
-
__proto__: null,
|
|
2735
|
-
value() {
|
|
2736
|
-
try {
|
|
2737
|
-
return getValidatedIdTokenClaims(this);
|
|
2738
|
-
} catch {
|
|
2739
|
-
return;
|
|
2740
|
-
}
|
|
2741
|
-
}
|
|
2742
|
-
}
|
|
2743
|
-
};
|
|
2744
|
-
}
|
|
2745
|
-
function addHelpers(response) {
|
|
2746
|
-
Object.defineProperties(response, getHelpers(response));
|
|
2747
|
-
}
|
|
2748
|
-
function allowInsecureRequests(config) {
|
|
2749
|
-
int(config).tlsOnly = false;
|
|
2750
|
-
}
|
|
2751
|
-
function stripParams(url) {
|
|
2752
|
-
url = new URL(url);
|
|
2753
|
-
url.search = "";
|
|
2754
|
-
url.hash = "";
|
|
2755
|
-
return url.href;
|
|
2756
|
-
}
|
|
2757
|
-
function webInstanceOf(input, toStringTag) {
|
|
2758
|
-
try {
|
|
2759
|
-
return Object.getPrototypeOf(input)[Symbol.toStringTag] === toStringTag;
|
|
2760
|
-
} catch {
|
|
2761
|
-
return false;
|
|
2762
|
-
}
|
|
2763
|
-
}
|
|
2764
|
-
async function authorizationCodeGrant(config, currentUrl, checks, tokenEndpointParameters, options) {
|
|
2765
|
-
checkConfig(config);
|
|
2766
|
-
if (options?.flag !== retry && !(currentUrl instanceof URL) && !webInstanceOf(currentUrl, "Request")) throw CodedTypeError("\"currentUrl\" must be an instance of URL, or Request", ERR_INVALID_ARG_TYPE);
|
|
2767
|
-
let authResponse;
|
|
2768
|
-
let redirectUri;
|
|
2769
|
-
const { as, c, auth, fetch: fetch$1, tlsOnly, jarm, hybrid, nonRepudiation, timeout, decrypt, implicit } = int(config);
|
|
2770
|
-
if (options?.flag === retry) {
|
|
2771
|
-
authResponse = options.authResponse;
|
|
2772
|
-
redirectUri = options.redirectUri;
|
|
2773
|
-
} else {
|
|
2774
|
-
if (!(currentUrl instanceof URL)) {
|
|
2775
|
-
const request = currentUrl;
|
|
2776
|
-
currentUrl = new URL(currentUrl.url);
|
|
2777
|
-
switch (request.method) {
|
|
2778
|
-
case "GET": break;
|
|
2779
|
-
case "POST":
|
|
2780
|
-
const params = new URLSearchParams(await formPostResponse(request));
|
|
2781
|
-
if (hybrid) currentUrl.hash = params.toString();
|
|
2782
|
-
else for (const [k, v] of params.entries()) currentUrl.searchParams.append(k, v);
|
|
2783
|
-
break;
|
|
2784
|
-
default: throw CodedTypeError("unexpected Request HTTP method", ERR_INVALID_ARG_VALUE);
|
|
2785
|
-
}
|
|
2786
|
-
}
|
|
2787
|
-
redirectUri = stripParams(currentUrl);
|
|
2788
|
-
switch (true) {
|
|
2789
|
-
case !!jarm:
|
|
2790
|
-
authResponse = await jarm(currentUrl, checks?.expectedState);
|
|
2791
|
-
break;
|
|
2792
|
-
case !!hybrid:
|
|
2793
|
-
authResponse = await hybrid(currentUrl, checks?.expectedNonce, checks?.expectedState, checks?.maxAge);
|
|
2794
|
-
break;
|
|
2795
|
-
case !!implicit: throw new TypeError("authorizationCodeGrant() cannot be used by response_type=id_token clients");
|
|
2796
|
-
default: try {
|
|
2797
|
-
authResponse = validateAuthResponse(as, c, currentUrl.searchParams, checks?.expectedState);
|
|
2798
|
-
} catch (err) {
|
|
2799
|
-
errorHandler(err);
|
|
1674
|
+
//#region src/auth/providers/ReactAuthProvider.ts
|
|
1675
|
+
var ReactAuthProvider = class {
|
|
1676
|
+
alepha = (0, alepha.$inject)(alepha.Alepha);
|
|
1677
|
+
onRender = (0, alepha.$hook)({
|
|
1678
|
+
on: "react:server:render:begin",
|
|
1679
|
+
handler: async ({ request, state }) => {
|
|
1680
|
+
if (request?.user) {
|
|
1681
|
+
const { token, realm, ...user } = request.user;
|
|
1682
|
+
this.alepha.state.set("alepha.server.request.user", user);
|
|
1683
|
+
state.user = user;
|
|
2800
1684
|
}
|
|
2801
1685
|
}
|
|
2802
|
-
}
|
|
2803
|
-
const response = await authorizationCodeGrantRequest(as, c, auth, authResponse, redirectUri, checks?.pkceCodeVerifier || nopkce, {
|
|
2804
|
-
additionalParameters: tokenEndpointParameters,
|
|
2805
|
-
[customFetch$1]: fetch$1,
|
|
2806
|
-
[allowInsecureRequests$1]: !tlsOnly,
|
|
2807
|
-
DPoP: options?.DPoP,
|
|
2808
|
-
headers: new Headers(headers),
|
|
2809
|
-
signal: signal(timeout)
|
|
2810
|
-
}).catch(errorHandler);
|
|
2811
|
-
if (typeof checks?.expectedNonce === "string" || typeof checks?.maxAge === "number") checks.idTokenExpected = true;
|
|
2812
|
-
const p = processAuthorizationCodeResponse(as, c, response, {
|
|
2813
|
-
expectedNonce: checks?.expectedNonce,
|
|
2814
|
-
maxAge: checks?.maxAge,
|
|
2815
|
-
requireIdToken: checks?.idTokenExpected,
|
|
2816
|
-
[jweDecrypt]: decrypt
|
|
2817
1686
|
});
|
|
2818
|
-
let result;
|
|
2819
|
-
try {
|
|
2820
|
-
result = await p;
|
|
2821
|
-
} catch (err) {
|
|
2822
|
-
if (retryable(err, options)) return authorizationCodeGrant(config, void 0, checks, tokenEndpointParameters, {
|
|
2823
|
-
...options,
|
|
2824
|
-
flag: retry,
|
|
2825
|
-
authResponse,
|
|
2826
|
-
redirectUri
|
|
2827
|
-
});
|
|
2828
|
-
errorHandler(err);
|
|
2829
|
-
}
|
|
2830
|
-
result.id_token && await nonRepudiation?.(response);
|
|
2831
|
-
addHelpers(result);
|
|
2832
|
-
return result;
|
|
2833
|
-
}
|
|
2834
|
-
async function refreshTokenGrant(config, refreshToken, parameters, options) {
|
|
2835
|
-
checkConfig(config);
|
|
2836
|
-
parameters = new URLSearchParams(parameters);
|
|
2837
|
-
const { as, c, auth, fetch: fetch$1, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);
|
|
2838
|
-
const response = await refreshTokenGrantRequest(as, c, auth, refreshToken, {
|
|
2839
|
-
[customFetch$1]: fetch$1,
|
|
2840
|
-
[allowInsecureRequests$1]: !tlsOnly,
|
|
2841
|
-
additionalParameters: parameters,
|
|
2842
|
-
DPoP: options?.DPoP,
|
|
2843
|
-
headers: new Headers(headers),
|
|
2844
|
-
signal: signal(timeout)
|
|
2845
|
-
}).catch(errorHandler);
|
|
2846
|
-
const p = processRefreshTokenResponse(as, c, response, { [jweDecrypt]: decrypt });
|
|
2847
|
-
let result;
|
|
2848
|
-
try {
|
|
2849
|
-
result = await p;
|
|
2850
|
-
} catch (err) {
|
|
2851
|
-
if (retryable(err, options)) return refreshTokenGrant(config, refreshToken, parameters, {
|
|
2852
|
-
...options,
|
|
2853
|
-
flag: retry
|
|
2854
|
-
});
|
|
2855
|
-
errorHandler(err);
|
|
2856
|
-
}
|
|
2857
|
-
result.id_token && await nonRepudiation?.(response);
|
|
2858
|
-
addHelpers(result);
|
|
2859
|
-
return result;
|
|
2860
|
-
}
|
|
2861
|
-
function buildAuthorizationUrl(config, parameters) {
|
|
2862
|
-
checkConfig(config);
|
|
2863
|
-
const { as, c, tlsOnly, hybrid, jarm, implicit } = int(config);
|
|
2864
|
-
const authorizationEndpoint = resolveEndpoint(as, "authorization_endpoint", false, tlsOnly);
|
|
2865
|
-
parameters = new URLSearchParams(parameters);
|
|
2866
|
-
if (!parameters.has("client_id")) parameters.set("client_id", c.client_id);
|
|
2867
|
-
if (!parameters.has("request_uri") && !parameters.has("request")) {
|
|
2868
|
-
if (!parameters.has("response_type")) parameters.set("response_type", hybrid ? "code id_token" : implicit ? "id_token" : "code");
|
|
2869
|
-
if (implicit && !parameters.has("nonce")) throw CodedTypeError("response_type=id_token clients must provide a nonce parameter in their authorization request parameters", ERR_INVALID_ARG_VALUE);
|
|
2870
|
-
if (jarm) parameters.set("response_mode", "jwt");
|
|
2871
|
-
}
|
|
2872
|
-
for (const [k, v] of parameters.entries()) authorizationEndpoint.searchParams.append(k, v);
|
|
2873
|
-
return authorizationEndpoint;
|
|
2874
|
-
}
|
|
2875
|
-
function buildEndSessionUrl(config, parameters) {
|
|
2876
|
-
checkConfig(config);
|
|
2877
|
-
const { as, c, tlsOnly } = int(config);
|
|
2878
|
-
const endSessionEndpoint = resolveEndpoint(as, "end_session_endpoint", false, tlsOnly);
|
|
2879
|
-
parameters = new URLSearchParams(parameters);
|
|
2880
|
-
if (!parameters.has("client_id")) parameters.set("client_id", c.client_id);
|
|
2881
|
-
for (const [k, v] of parameters.entries()) endSessionEndpoint.searchParams.append(k, v);
|
|
2882
|
-
return endSessionEndpoint;
|
|
2883
|
-
}
|
|
2884
|
-
function checkConfig(input) {
|
|
2885
|
-
if (!(input instanceof Configuration)) throw CodedTypeError("\"config\" must be an instance of Configuration", ERR_INVALID_ARG_TYPE);
|
|
2886
|
-
if (Object.getPrototypeOf(input) !== Configuration.prototype) throw CodedTypeError("subclassing Configuration is not allowed", ERR_INVALID_ARG_VALUE);
|
|
2887
|
-
}
|
|
2888
|
-
function signal(timeout) {
|
|
2889
|
-
return timeout ? AbortSignal.timeout(timeout * 1e3) : void 0;
|
|
2890
|
-
}
|
|
2891
|
-
function retryable(err, options) {
|
|
2892
|
-
if (options?.DPoP && options.flag !== retry) return isDPoPNonceError(err);
|
|
2893
|
-
return false;
|
|
2894
|
-
}
|
|
2895
|
-
const retry = Symbol();
|
|
2896
|
-
|
|
2897
|
-
//#endregion
|
|
2898
|
-
//#region src/auth/descriptors/$auth.ts
|
|
2899
|
-
/**
|
|
2900
|
-
* Creates an authentication provider descriptor for handling user login flows.
|
|
2901
|
-
*
|
|
2902
|
-
* Supports multiple authentication strategies: credentials (username/password), OAuth2,
|
|
2903
|
-
* and OIDC (OpenID Connect). Handles token management, user profile retrieval, and
|
|
2904
|
-
* integration with both external identity providers (Auth0, Keycloak) and internal realms.
|
|
2905
|
-
*
|
|
2906
|
-
* **Authentication Types**: Credentials, OAuth2 (Google, GitHub), OIDC, External providers
|
|
2907
|
-
*
|
|
2908
|
-
* @example
|
|
2909
|
-
* ```ts
|
|
2910
|
-
* class AuthProviders {
|
|
2911
|
-
* // Internal credentials-based auth
|
|
2912
|
-
* credentials = $auth({
|
|
2913
|
-
* realm: this.userRealm,
|
|
2914
|
-
* credentials: {
|
|
2915
|
-
* account: async ({ username, password }) => {
|
|
2916
|
-
* return await this.validateUser(username, password);
|
|
2917
|
-
* }
|
|
2918
|
-
* }
|
|
2919
|
-
* });
|
|
2920
|
-
*
|
|
2921
|
-
* // External OIDC provider
|
|
2922
|
-
* keycloak = $auth({
|
|
2923
|
-
* oidc: {
|
|
2924
|
-
* issuer: "https://auth.example.com",
|
|
2925
|
-
* clientId: "my-app",
|
|
2926
|
-
* clientSecret: "secret",
|
|
2927
|
-
* redirectUri: "/auth/callback"
|
|
2928
|
-
* }
|
|
2929
|
-
* });
|
|
2930
|
-
* }
|
|
2931
|
-
* ```
|
|
2932
|
-
*/
|
|
2933
|
-
const $auth = (options) => {
|
|
2934
|
-
return (0, alepha.createDescriptor)(AuthDescriptor, options);
|
|
2935
|
-
};
|
|
2936
|
-
var AuthDescriptor = class extends alepha.Descriptor {
|
|
2937
|
-
securityProvider = (0, alepha.$inject)(alepha_security.SecurityProvider);
|
|
2938
|
-
dateTimeProvider = (0, alepha.$inject)(alepha_datetime.DateTimeProvider);
|
|
2939
|
-
oauth;
|
|
2940
|
-
get name() {
|
|
2941
|
-
return this.options.name ?? this.config.propertyKey;
|
|
2942
|
-
}
|
|
2943
|
-
get jwks_uri() {
|
|
2944
|
-
const jwks = this.oauth?.serverMetadata().jwks_uri;
|
|
2945
|
-
if (!jwks) throw new alepha.AlephaError("No JWKS URI available for the auth provider");
|
|
2946
|
-
return jwks;
|
|
2947
|
-
}
|
|
2948
|
-
get scope() {
|
|
2949
|
-
if ("oauth" in this.options) return this.options.oauth.scope;
|
|
2950
|
-
if ("oidc" in this.options) return this.options.oidc.scope || "openid profile email";
|
|
2951
|
-
throw new alepha.AlephaError("No OAuth2 or OIDC configuration available for the auth provider");
|
|
2952
|
-
}
|
|
2953
|
-
get redirect_uri() {
|
|
2954
|
-
if ("oauth" in this.options) return this.options.oauth.redirectUri;
|
|
2955
|
-
if ("oidc" in this.options) return this.options.oidc.redirectUri;
|
|
2956
|
-
throw new alepha.AlephaError("No OAuth2 or OIDC configuration available for the auth provider");
|
|
2957
|
-
}
|
|
2958
|
-
/**
|
|
2959
|
-
* Refreshes the access token using the refresh token.
|
|
2960
|
-
* Can be used on oauth2, oidc or credentials auth providers.
|
|
2961
|
-
*/
|
|
2962
|
-
async refresh(refreshToken, accessToken) {
|
|
2963
|
-
if ("realm" in this.options) return this.options.realm.refreshToken(refreshToken, accessToken).then((it) => it.tokens).catch((error) => {
|
|
2964
|
-
throw new alepha_security.SecurityError("Failed to refresh access token using the refresh token (realm)", { cause: error });
|
|
2965
|
-
});
|
|
2966
|
-
else if (this.oauth) try {
|
|
2967
|
-
return {
|
|
2968
|
-
...await refreshTokenGrant(this.oauth, refreshToken),
|
|
2969
|
-
issued_at: this.dateTimeProvider.now().unix()
|
|
2970
|
-
};
|
|
2971
|
-
} catch (error) {
|
|
2972
|
-
throw new alepha_security.SecurityError("Failed to refresh access token using the refresh token (oauth2)", { cause: error });
|
|
2973
|
-
}
|
|
2974
|
-
throw new alepha.AlephaError("No realm or OAuth2 configuration available for refreshing the access token");
|
|
2975
|
-
}
|
|
2976
|
-
/**
|
|
2977
|
-
* Extracts user information from the access token.
|
|
2978
|
-
* This is used to create a user account from the access token.
|
|
2979
|
-
*/
|
|
2980
|
-
async user(tokens) {
|
|
2981
|
-
try {
|
|
2982
|
-
if ("oauth" in this.options) {
|
|
2983
|
-
const profile = await this.options.oauth.userinfo(tokens);
|
|
2984
|
-
if (this.options.oauth.account) return this.options.oauth.account({
|
|
2985
|
-
...tokens,
|
|
2986
|
-
user: profile
|
|
2987
|
-
});
|
|
2988
|
-
return this.securityProvider.createUserFromPayload(profile);
|
|
2989
|
-
}
|
|
2990
|
-
if ("oidc" in this.options) {
|
|
2991
|
-
const payload = this.getUserFromIdToken(tokens.id_token || "");
|
|
2992
|
-
if (this.options.oidc.account) return this.options.oidc.account({
|
|
2993
|
-
...tokens,
|
|
2994
|
-
user: payload
|
|
2995
|
-
});
|
|
2996
|
-
return this.securityProvider.createUserFromPayload(payload);
|
|
2997
|
-
}
|
|
2998
|
-
} catch (error) {
|
|
2999
|
-
throw new alepha_security.SecurityError("Failed to extract user from identity provider tokens", { cause: error });
|
|
3000
|
-
}
|
|
3001
|
-
throw new alepha.AlephaError("This authentication does not support user extraction from tokens");
|
|
3002
|
-
}
|
|
3003
|
-
getUserFromIdToken(idToken) {
|
|
3004
|
-
try {
|
|
3005
|
-
return JSON.parse(Buffer.from(idToken.split(".")[1], "base64").toString("utf8"));
|
|
3006
|
-
} catch (error) {
|
|
3007
|
-
throw new alepha.AlephaError("Failed to parse ID Token payload", { cause: error });
|
|
3008
|
-
}
|
|
3009
|
-
}
|
|
3010
|
-
async prepare() {
|
|
3011
|
-
const addons = [];
|
|
3012
|
-
addons.push(allowInsecureRequests);
|
|
3013
|
-
if ("oidc" in this.options) {
|
|
3014
|
-
const { oidc } = this.options;
|
|
3015
|
-
this.oauth = await discovery(new URL(oidc.issuer), oidc.clientId, { client_secret: oidc.clientSecret }, void 0, { execute: addons });
|
|
3016
|
-
}
|
|
3017
|
-
if ("oauth" in this.options) {
|
|
3018
|
-
const { oauth } = this.options;
|
|
3019
|
-
this.oauth = new Configuration({
|
|
3020
|
-
authorization_endpoint: oauth.authorization,
|
|
3021
|
-
token_endpoint: oauth.token,
|
|
3022
|
-
issuer: oauth.authorization,
|
|
3023
|
-
jwks_uri: void 0,
|
|
3024
|
-
end_session_endpoint: void 0
|
|
3025
|
-
}, oauth.clientId, { client_secret: oauth.clientSecret });
|
|
3026
|
-
}
|
|
3027
|
-
}
|
|
3028
1687
|
};
|
|
3029
|
-
$auth[alepha.KIND] = AuthDescriptor;
|
|
3030
|
-
|
|
3031
|
-
//#endregion
|
|
3032
|
-
//#region src/auth/schemas/tokensSchema.ts
|
|
3033
|
-
const tokensSchema = alepha.t.object({
|
|
3034
|
-
provider: alepha.t.text(),
|
|
3035
|
-
access_token: alepha.t.text({ size: "rich" }),
|
|
3036
|
-
issued_at: alepha.t.number(),
|
|
3037
|
-
expires_in: alepha.t.optional(alepha.t.number()),
|
|
3038
|
-
refresh_token: alepha.t.optional(alepha.t.text({ size: "rich" })),
|
|
3039
|
-
refresh_token_expires_in: alepha.t.optional(alepha.t.number()),
|
|
3040
|
-
refresh_expires_in: alepha.t.optional(alepha.t.number({ description: "Alias of `refresh_token_expires_in` for compatibility with some providers." })),
|
|
3041
|
-
id_token: alepha.t.optional(alepha.t.text({ size: "rich" })),
|
|
3042
|
-
scope: alepha.t.optional(alepha.t.text())
|
|
3043
|
-
});
|
|
3044
|
-
|
|
3045
|
-
//#endregion
|
|
3046
|
-
//#region src/auth/schemas/tokenResponseSchema.ts
|
|
3047
|
-
const tokenResponseSchema = alepha.t.extend(tokensSchema, {
|
|
3048
|
-
user: alepha_security.userAccountInfoSchema,
|
|
3049
|
-
api: alepha_server_links.apiLinksResponseSchema
|
|
3050
|
-
});
|
|
3051
|
-
|
|
3052
|
-
//#endregion
|
|
3053
|
-
//#region src/auth/schemas/userinfoResponseSchema.ts
|
|
3054
|
-
const userinfoResponseSchema = alepha.t.object({
|
|
3055
|
-
user: alepha.t.optional(alepha_security.userAccountInfoSchema),
|
|
3056
|
-
api: alepha_server_links.apiLinksResponseSchema
|
|
3057
|
-
});
|
|
3058
1688
|
|
|
3059
1689
|
//#endregion
|
|
3060
1690
|
//#region src/auth/services/ReactAuth.ts
|
|
3061
1691
|
/**
|
|
3062
1692
|
* Browser, SSR friendly, service to handle authentication.
|
|
3063
1693
|
*/
|
|
3064
|
-
var ReactAuth = class
|
|
1694
|
+
var ReactAuth = class {
|
|
3065
1695
|
log = (0, alepha_logger.$logger)();
|
|
3066
1696
|
alepha = (0, alepha.$inject)(alepha.Alepha);
|
|
3067
1697
|
httpClient = (0, alepha.$inject)(alepha_server.HttpClient);
|
|
3068
|
-
static path = {
|
|
3069
|
-
login: "/oauth/login",
|
|
3070
|
-
callback: "/oauth/callback",
|
|
3071
|
-
logout: "/oauth/logout",
|
|
3072
|
-
token: "/_auth/token",
|
|
3073
|
-
refresh: "/_auth/refresh",
|
|
3074
|
-
userinfo: "/_auth/userinfo"
|
|
3075
|
-
};
|
|
3076
1698
|
onBeginTransition = (0, alepha.$hook)({
|
|
3077
1699
|
on: "react:transition:begin",
|
|
3078
1700
|
handler: async (event) => {
|
|
@@ -3094,21 +1716,21 @@ var ReactAuth = class ReactAuth {
|
|
|
3094
1716
|
return this.alepha.state.get("alepha.server.request.user");
|
|
3095
1717
|
}
|
|
3096
1718
|
async ping() {
|
|
3097
|
-
const { data } = await this.httpClient.fetch(
|
|
1719
|
+
const { data } = await this.httpClient.fetch(alepha_server_auth.alephaServerAuthRoutes.userinfo, { schema: { response: alepha_server_auth.userinfoResponseSchema } });
|
|
3098
1720
|
this.alepha.state.set("alepha.server.request.apiLinks", data.api);
|
|
3099
1721
|
this.alepha.state.set("alepha.server.request.user", data.user);
|
|
3100
1722
|
return data.user;
|
|
3101
1723
|
}
|
|
3102
1724
|
async login(provider, options) {
|
|
3103
1725
|
if (options.username || options.password) {
|
|
3104
|
-
const { data } = await this.httpClient.fetch(`${options.hostname || ""}${
|
|
1726
|
+
const { data } = await this.httpClient.fetch(`${options.hostname || ""}${alepha_server_auth.alephaServerAuthRoutes.token}?provider=${provider}`, {
|
|
3105
1727
|
method: "POST",
|
|
3106
1728
|
body: JSON.stringify({
|
|
3107
1729
|
username: options.username,
|
|
3108
1730
|
password: options.password,
|
|
3109
1731
|
...options
|
|
3110
1732
|
}),
|
|
3111
|
-
schema: { response: tokenResponseSchema }
|
|
1733
|
+
schema: { response: alepha_server_auth.tokenResponseSchema }
|
|
3112
1734
|
});
|
|
3113
1735
|
this.alepha.state.set("alepha.server.request.apiLinks", data.api);
|
|
3114
1736
|
this.alepha.state.set("alepha.server.request.user", data.user);
|
|
@@ -3117,483 +1739,18 @@ var ReactAuth = class ReactAuth {
|
|
|
3117
1739
|
if (this.alepha.isBrowser()) {
|
|
3118
1740
|
const browser = this.alepha.inject(ReactBrowserProvider);
|
|
3119
1741
|
const redirect = options.redirect || (browser.transitioning ? window.location.origin + browser.transitioning.to : window.location.href);
|
|
3120
|
-
const href = `${window.location.origin}${
|
|
1742
|
+
const href = `${window.location.origin}${alepha_server_auth.alephaServerAuthRoutes.login}?provider=${provider}&redirect_uri=${encodeURIComponent(redirect)}`;
|
|
3121
1743
|
if (browser.transitioning) throw new Redirection(href);
|
|
3122
1744
|
else {
|
|
3123
1745
|
window.location.href = href;
|
|
3124
1746
|
return {};
|
|
3125
1747
|
}
|
|
3126
1748
|
}
|
|
3127
|
-
throw new Redirection(`${
|
|
1749
|
+
throw new Redirection(`${alepha_server_auth.alephaServerAuthRoutes.login}?provider=${provider}&redirect_uri=${options.redirect || "/"}`);
|
|
3128
1750
|
}
|
|
3129
1751
|
logout() {
|
|
3130
|
-
window.location.href = `${
|
|
3131
|
-
}
|
|
3132
|
-
};
|
|
3133
|
-
|
|
3134
|
-
//#endregion
|
|
3135
|
-
//#region src/auth/providers/ReactAuthProvider.ts
|
|
3136
|
-
var ReactAuthProvider = class {
|
|
3137
|
-
log = (0, alepha_logger.$logger)();
|
|
3138
|
-
alepha = (0, alepha.$inject)(alepha.Alepha);
|
|
3139
|
-
serverCookiesProvider = (0, alepha.$inject)(alepha_server_cookies.ServerCookiesProvider);
|
|
3140
|
-
dateTimeProvider = (0, alepha.$inject)(alepha_datetime.DateTimeProvider);
|
|
3141
|
-
serverLinksProvider = (0, alepha.$inject)(alepha_server_links.ServerLinksProvider);
|
|
3142
|
-
reactAuth = (0, alepha.$inject)(ReactAuth);
|
|
3143
|
-
authorizationCode = (0, alepha_server_cookies.$cookie)({
|
|
3144
|
-
name: "authorizationCode",
|
|
3145
|
-
ttl: [15, "minutes"],
|
|
3146
|
-
httpOnly: true,
|
|
3147
|
-
schema: alepha.t.object({
|
|
3148
|
-
provider: alepha.t.text(),
|
|
3149
|
-
codeVerifier: alepha.t.optional(alepha.t.text({ size: "long" })),
|
|
3150
|
-
redirectUri: alepha.t.optional(alepha.t.text({ size: "long" })),
|
|
3151
|
-
state: alepha.t.optional(alepha.t.text()),
|
|
3152
|
-
nonce: alepha.t.optional(alepha.t.text())
|
|
3153
|
-
})
|
|
3154
|
-
});
|
|
3155
|
-
tokens = (0, alepha_server_cookies.$cookie)({
|
|
3156
|
-
name: "tokens",
|
|
3157
|
-
ttl: [30, "days"],
|
|
3158
|
-
httpOnly: true,
|
|
3159
|
-
compress: true,
|
|
3160
|
-
encrypt: true,
|
|
3161
|
-
schema: tokensSchema
|
|
3162
|
-
});
|
|
3163
|
-
onRender = (0, alepha.$hook)({
|
|
3164
|
-
on: "react:server:render:begin",
|
|
3165
|
-
handler: async ({ request, state }) => {
|
|
3166
|
-
if (request?.user) {
|
|
3167
|
-
const { token, realm, ...user } = request.user;
|
|
3168
|
-
this.alepha.state.set("alepha.server.request.user", user);
|
|
3169
|
-
state.user = user;
|
|
3170
|
-
}
|
|
3171
|
-
}
|
|
3172
|
-
});
|
|
3173
|
-
get identities() {
|
|
3174
|
-
return this.alepha.descriptors($auth).filter((auth) => !auth.options.disabled);
|
|
3175
|
-
}
|
|
3176
|
-
configure = (0, alepha.$hook)({
|
|
3177
|
-
on: "configure",
|
|
3178
|
-
handler: async () => {
|
|
3179
|
-
for (const identity of this.identities) await identity.prepare();
|
|
3180
|
-
}
|
|
3181
|
-
});
|
|
3182
|
-
getAccessTokens(tokens) {
|
|
3183
|
-
const idp = this.provider(tokens.provider);
|
|
3184
|
-
if ("oidc" in idp.options && !("realm" in idp.options) && idp.options.oidc?.useIdToken) return tokens.id_token;
|
|
3185
|
-
return tokens.access_token;
|
|
1752
|
+
window.location.href = `${alepha_server_auth.alephaServerAuthRoutes.logout}?post_logout_redirect_uri=${encodeURIComponent(window.location.origin)}`;
|
|
3186
1753
|
}
|
|
3187
|
-
/**
|
|
3188
|
-
* Fill request headers with access token from cookies or fallback to provider's fallback function.
|
|
3189
|
-
*/
|
|
3190
|
-
onRequest = (0, alepha.$hook)({
|
|
3191
|
-
on: "server:onRequest",
|
|
3192
|
-
after: this.serverCookiesProvider,
|
|
3193
|
-
handler: async ({ request }) => {
|
|
3194
|
-
const cookies = request.cookies;
|
|
3195
|
-
if (cookies) {
|
|
3196
|
-
const tokens = await this.cookiesToTokens(cookies);
|
|
3197
|
-
if (tokens) {
|
|
3198
|
-
request.headers.authorization = `Bearer ${this.getAccessTokens(tokens)}`;
|
|
3199
|
-
this.log.trace("Access token set in request headers", { provider: tokens.provider });
|
|
3200
|
-
}
|
|
3201
|
-
}
|
|
3202
|
-
if (!request.headers.authorization) {
|
|
3203
|
-
for (const provider of this.identities) if (!("realm" in provider.options) && !!provider.options.fallback) {
|
|
3204
|
-
const token = await provider.options.fallback();
|
|
3205
|
-
if (token) {
|
|
3206
|
-
request.headers.authorization = `Bearer ${token}`;
|
|
3207
|
-
break;
|
|
3208
|
-
}
|
|
3209
|
-
}
|
|
3210
|
-
}
|
|
3211
|
-
}
|
|
3212
|
-
});
|
|
3213
|
-
/**
|
|
3214
|
-
* Convert cookies to tokens.
|
|
3215
|
-
* If the tokens are expired, try to refresh them using the refresh token.
|
|
3216
|
-
*/
|
|
3217
|
-
async cookiesToTokens(cookies) {
|
|
3218
|
-
const tokens = this.tokens.get({ cookies });
|
|
3219
|
-
if (!tokens) {
|
|
3220
|
-
this.log.trace("No tokens found in cookies");
|
|
3221
|
-
return;
|
|
3222
|
-
}
|
|
3223
|
-
this.log.trace("Tokens found in cookies", {
|
|
3224
|
-
expires_in: tokens.expires_in,
|
|
3225
|
-
issued_at: tokens.issued_at
|
|
3226
|
-
});
|
|
3227
|
-
const refreshedTokens = await this.refreshTokens(tokens);
|
|
3228
|
-
if (!refreshedTokens) {
|
|
3229
|
-
this.tokens.del({ cookies });
|
|
3230
|
-
return;
|
|
3231
|
-
}
|
|
3232
|
-
if (refreshedTokens.access_token !== tokens.access_token) this.setTokens(refreshedTokens, cookies);
|
|
3233
|
-
return refreshedTokens;
|
|
3234
|
-
}
|
|
3235
|
-
async refreshTokens(tokens) {
|
|
3236
|
-
if (tokens.expires_in && tokens.issued_at) {
|
|
3237
|
-
if (tokens.issued_at + (tokens.expires_in - 10) < this.dateTimeProvider.now().unix()) {
|
|
3238
|
-
this.log.trace("Tokens are expired");
|
|
3239
|
-
if (tokens.refresh_token) {
|
|
3240
|
-
this.log.trace("Trying to refresh tokens using refresh token");
|
|
3241
|
-
try {
|
|
3242
|
-
const newTokens = {
|
|
3243
|
-
...await this.provider(tokens).refresh(tokens.refresh_token, tokens.access_token),
|
|
3244
|
-
provider: tokens.provider,
|
|
3245
|
-
issued_at: this.dateTimeProvider.now().unix()
|
|
3246
|
-
};
|
|
3247
|
-
this.log.debug("Tokens refreshed successfully");
|
|
3248
|
-
return newTokens;
|
|
3249
|
-
} catch (e$1) {
|
|
3250
|
-
this.log.warn("Failed to refresh token", e$1);
|
|
3251
|
-
}
|
|
3252
|
-
}
|
|
3253
|
-
return;
|
|
3254
|
-
}
|
|
3255
|
-
}
|
|
3256
|
-
if (!tokens.issued_at && tokens.access_token) return;
|
|
3257
|
-
return tokens;
|
|
3258
|
-
}
|
|
3259
|
-
/**
|
|
3260
|
-
* Get user information.
|
|
3261
|
-
*/
|
|
3262
|
-
userinfo = (0, alepha_server.$route)({
|
|
3263
|
-
path: ReactAuth.path.userinfo,
|
|
3264
|
-
schema: { response: userinfoResponseSchema },
|
|
3265
|
-
handler: async ({ user, headers: headers$1, cookies }) => {
|
|
3266
|
-
const tokens = this.tokens.get({ cookies });
|
|
3267
|
-
if (tokens) {
|
|
3268
|
-
const provider = this.provider(tokens);
|
|
3269
|
-
if (!("realm" in provider.options)) {
|
|
3270
|
-
const user$1 = await provider.user(tokens);
|
|
3271
|
-
return {
|
|
3272
|
-
api: await this.serverLinksProvider.getUserApiLinks({
|
|
3273
|
-
authorization: headers$1.authorization,
|
|
3274
|
-
user: user$1
|
|
3275
|
-
}),
|
|
3276
|
-
user: user$1
|
|
3277
|
-
};
|
|
3278
|
-
}
|
|
3279
|
-
}
|
|
3280
|
-
return {
|
|
3281
|
-
api: await this.serverLinksProvider.getUserApiLinks({
|
|
3282
|
-
authorization: headers$1.authorization,
|
|
3283
|
-
user
|
|
3284
|
-
}),
|
|
3285
|
-
user
|
|
3286
|
-
};
|
|
3287
|
-
}
|
|
3288
|
-
});
|
|
3289
|
-
/**
|
|
3290
|
-
* Refresh a token for internal providers.
|
|
3291
|
-
*/
|
|
3292
|
-
refresh = (0, alepha_server.$route)({
|
|
3293
|
-
path: ReactAuth.path.refresh,
|
|
3294
|
-
method: "POST",
|
|
3295
|
-
schema: {
|
|
3296
|
-
query: alepha.t.object({ provider: alepha.t.text() }),
|
|
3297
|
-
body: alepha.t.object({
|
|
3298
|
-
refresh_token: alepha.t.text({ size: "rich" }),
|
|
3299
|
-
access_token: alepha.t.optional(alepha.t.text({
|
|
3300
|
-
size: "rich",
|
|
3301
|
-
description: "Required if provider has stateless refresh token on credentials mode"
|
|
3302
|
-
}))
|
|
3303
|
-
}),
|
|
3304
|
-
response: tokensSchema
|
|
3305
|
-
},
|
|
3306
|
-
handler: async ({ query, body, cookies }) => {
|
|
3307
|
-
const provider = this.provider(query);
|
|
3308
|
-
const tokens = {
|
|
3309
|
-
provider: query.provider,
|
|
3310
|
-
...await provider.refresh(body.refresh_token, body.access_token)
|
|
3311
|
-
};
|
|
3312
|
-
this.setTokens(tokens, cookies);
|
|
3313
|
-
return tokens;
|
|
3314
|
-
}
|
|
3315
|
-
});
|
|
3316
|
-
/**
|
|
3317
|
-
* Login for local password-based authentication.
|
|
3318
|
-
*/
|
|
3319
|
-
token = (0, alepha_server.$route)({
|
|
3320
|
-
path: ReactAuth.path.token,
|
|
3321
|
-
method: "POST",
|
|
3322
|
-
schema: {
|
|
3323
|
-
query: alepha.t.object({ provider: alepha.t.text() }),
|
|
3324
|
-
body: alepha.t.object({
|
|
3325
|
-
username: alepha.t.text(),
|
|
3326
|
-
password: alepha.t.text()
|
|
3327
|
-
}),
|
|
3328
|
-
response: tokenResponseSchema
|
|
3329
|
-
},
|
|
3330
|
-
handler: async ({ query, body, cookies }) => {
|
|
3331
|
-
const provider = this.provider(query);
|
|
3332
|
-
const realm = "realm" in provider.options && provider.options.realm;
|
|
3333
|
-
if (!realm) throw new alepha_security.SecurityError(`Auth provider '${query.provider}' does not support password grant`);
|
|
3334
|
-
const credentials = "credentials" in provider.options && provider.options.credentials;
|
|
3335
|
-
if (!credentials) throw new alepha_security.SecurityError(`Auth provider '${query.provider}' does not support password grant`);
|
|
3336
|
-
let user;
|
|
3337
|
-
try {
|
|
3338
|
-
user = await credentials.account(body);
|
|
3339
|
-
} catch (e$1) {
|
|
3340
|
-
throw new alepha_server.UnauthorizedError(`Failed to authenticate user`, { cause: e$1 });
|
|
3341
|
-
}
|
|
3342
|
-
const tokens = {
|
|
3343
|
-
provider: query.provider,
|
|
3344
|
-
...await realm.createToken(user)
|
|
3345
|
-
};
|
|
3346
|
-
this.setTokens(tokens, cookies);
|
|
3347
|
-
const api = await this.serverLinksProvider.getUserApiLinks({ user });
|
|
3348
|
-
return {
|
|
3349
|
-
...tokens,
|
|
3350
|
-
user,
|
|
3351
|
-
api
|
|
3352
|
-
};
|
|
3353
|
-
}
|
|
3354
|
-
});
|
|
3355
|
-
/**
|
|
3356
|
-
* Oauth2/OIDC login route.
|
|
3357
|
-
*/
|
|
3358
|
-
login = (0, alepha_server.$route)({
|
|
3359
|
-
path: ReactAuth.path.login,
|
|
3360
|
-
schema: { query: alepha.t.object({
|
|
3361
|
-
provider: alepha.t.text(),
|
|
3362
|
-
redirect_uri: alepha.t.optional(alepha.t.text({ size: "rich" }))
|
|
3363
|
-
}) },
|
|
3364
|
-
handler: async ({ query, url, reply }) => {
|
|
3365
|
-
const provider = this.provider(query);
|
|
3366
|
-
const oauth = provider.oauth;
|
|
3367
|
-
if (!oauth) throw new alepha_security.SecurityError(`Auth provider '${query.provider}' does not support OAuth2`);
|
|
3368
|
-
const scope = provider.scope;
|
|
3369
|
-
let redirect_uri = provider.redirect_uri || ReactAuth.path.callback;
|
|
3370
|
-
if (redirect_uri.startsWith("/")) redirect_uri = `${url.protocol}//${url.host}${redirect_uri}`;
|
|
3371
|
-
const oidc = "oidc" in provider.options && provider.options.oidc;
|
|
3372
|
-
if (!oauth.serverMetadata().supportsPKCE()) {
|
|
3373
|
-
const state = randomState();
|
|
3374
|
-
const parameters$1 = {
|
|
3375
|
-
redirect_uri,
|
|
3376
|
-
state
|
|
3377
|
-
};
|
|
3378
|
-
if (oidc) parameters$1.nonce = randomState();
|
|
3379
|
-
if (scope) parameters$1.scope = scope;
|
|
3380
|
-
this.authorizationCode.set({
|
|
3381
|
-
state,
|
|
3382
|
-
nonce: parameters$1.nonce,
|
|
3383
|
-
redirectUri: query.redirect_uri ?? "/",
|
|
3384
|
-
provider: query.provider
|
|
3385
|
-
});
|
|
3386
|
-
reply.redirect(buildAuthorizationUrl(oauth, parameters$1).toString());
|
|
3387
|
-
return;
|
|
3388
|
-
}
|
|
3389
|
-
const codeVerifier = randomPKCECodeVerifier();
|
|
3390
|
-
const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);
|
|
3391
|
-
const parameters = {
|
|
3392
|
-
redirect_uri,
|
|
3393
|
-
code_challenge: codeChallenge,
|
|
3394
|
-
code_challenge_method: "S256"
|
|
3395
|
-
};
|
|
3396
|
-
if (scope) parameters.scope = scope;
|
|
3397
|
-
this.authorizationCode.set({
|
|
3398
|
-
codeVerifier,
|
|
3399
|
-
redirectUri: query.redirect_uri ?? "/",
|
|
3400
|
-
provider: query.provider
|
|
3401
|
-
});
|
|
3402
|
-
reply.redirect(buildAuthorizationUrl(oauth, parameters).toString());
|
|
3403
|
-
}
|
|
3404
|
-
});
|
|
3405
|
-
/**
|
|
3406
|
-
* Callback for OAuth2/OIDC providers.
|
|
3407
|
-
* It handles the authorization code flow and retrieves the access token.
|
|
3408
|
-
*/
|
|
3409
|
-
callback = (0, alepha_server.$route)({
|
|
3410
|
-
path: ReactAuth.path.callback,
|
|
3411
|
-
handler: async ({ url, reply, cookies }) => {
|
|
3412
|
-
const authorizationCode = this.authorizationCode.get({ cookies });
|
|
3413
|
-
if (!authorizationCode) throw new alepha_server.BadRequestError("Missing code verifier");
|
|
3414
|
-
const provider = this.provider(authorizationCode);
|
|
3415
|
-
const oauth = provider.oauth;
|
|
3416
|
-
if (!oauth) throw new alepha_security.SecurityError(`Auth provider '${provider.name}' does not support OAuth2`);
|
|
3417
|
-
const redirectUri = authorizationCode.redirectUri ?? "/";
|
|
3418
|
-
const externalTokens = await authorizationCodeGrant(oauth, url, {
|
|
3419
|
-
pkceCodeVerifier: authorizationCode.codeVerifier,
|
|
3420
|
-
expectedState: authorizationCode.state,
|
|
3421
|
-
expectedNonce: authorizationCode.nonce
|
|
3422
|
-
}).then((tokens$1) => ({
|
|
3423
|
-
issued_at: this.dateTimeProvider.now().unix(),
|
|
3424
|
-
provider: provider.name,
|
|
3425
|
-
...tokens$1
|
|
3426
|
-
})).catch((e$1) => {
|
|
3427
|
-
this.log.error("Failed to get access token", e$1);
|
|
3428
|
-
throw new alepha_security.SecurityError("Failed to get access token", { cause: e$1 });
|
|
3429
|
-
});
|
|
3430
|
-
this.authorizationCode.del({ cookies });
|
|
3431
|
-
const realm = "realm" in provider.options && provider.options.realm;
|
|
3432
|
-
if (!realm) {
|
|
3433
|
-
this.setTokens(externalTokens, cookies);
|
|
3434
|
-
reply.redirect(redirectUri);
|
|
3435
|
-
return;
|
|
3436
|
-
}
|
|
3437
|
-
const user = await provider.user(externalTokens);
|
|
3438
|
-
const tokens = await realm.createToken(user);
|
|
3439
|
-
this.setTokens({
|
|
3440
|
-
...tokens,
|
|
3441
|
-
issued_at: this.dateTimeProvider.now().unix(),
|
|
3442
|
-
provider: provider.name
|
|
3443
|
-
}, cookies);
|
|
3444
|
-
reply.redirect(redirectUri);
|
|
3445
|
-
}
|
|
3446
|
-
});
|
|
3447
|
-
/**
|
|
3448
|
-
* Logout route for OAuth2/OIDC providers.
|
|
3449
|
-
*/
|
|
3450
|
-
logout = (0, alepha_server.$route)({
|
|
3451
|
-
path: ReactAuth.path.logout,
|
|
3452
|
-
method: "GET",
|
|
3453
|
-
schema: { query: alepha.t.object({ post_logout_redirect_uri: alepha.t.optional(alepha.t.text()) }) },
|
|
3454
|
-
handler: async ({ query, reply, cookies }) => {
|
|
3455
|
-
const redirect = query.post_logout_redirect_uri ?? "/";
|
|
3456
|
-
const tokens = this.tokens.get({ cookies });
|
|
3457
|
-
if (!tokens) {
|
|
3458
|
-
reply.redirect(redirect);
|
|
3459
|
-
return;
|
|
3460
|
-
}
|
|
3461
|
-
const provider = this.provider(tokens.provider);
|
|
3462
|
-
this.tokens.del({ cookies });
|
|
3463
|
-
if ("realm" in provider.options && tokens.refresh_token) {
|
|
3464
|
-
const onDeleteSession = provider.options.realm.options.settings?.onDeleteSession;
|
|
3465
|
-
if (onDeleteSession) try {
|
|
3466
|
-
await onDeleteSession(tokens.refresh_token);
|
|
3467
|
-
} catch (e$1) {
|
|
3468
|
-
this.log.error("Failed to delete session", e$1);
|
|
3469
|
-
}
|
|
3470
|
-
}
|
|
3471
|
-
const oauth = provider.oauth;
|
|
3472
|
-
if (!oauth) {
|
|
3473
|
-
reply.redirect(redirect);
|
|
3474
|
-
return;
|
|
3475
|
-
}
|
|
3476
|
-
const params = new URLSearchParams();
|
|
3477
|
-
const idToken = tokens?.id_token;
|
|
3478
|
-
params.set("post_logout_redirect_uri", redirect);
|
|
3479
|
-
if (idToken) params.set("id_token_hint", idToken);
|
|
3480
|
-
const customLogoutUri = "oidc" in provider.options ? provider.options.oidc?.logoutUri : void 0;
|
|
3481
|
-
if (customLogoutUri) {
|
|
3482
|
-
reply.redirect(`${customLogoutUri}?${params}`);
|
|
3483
|
-
return;
|
|
3484
|
-
}
|
|
3485
|
-
if (!oauth.serverMetadata().end_session_endpoint) {
|
|
3486
|
-
reply.redirect(redirect);
|
|
3487
|
-
return;
|
|
3488
|
-
}
|
|
3489
|
-
reply.redirect(buildEndSessionUrl(oauth, params).toString());
|
|
3490
|
-
}
|
|
3491
|
-
});
|
|
3492
|
-
provider(opts) {
|
|
3493
|
-
const name = typeof opts === "string" ? opts : opts.provider;
|
|
3494
|
-
const identity = this.identities.find((identity$1) => identity$1.name === name);
|
|
3495
|
-
if (!identity) throw new alepha_security.SecurityError(`Auth provider '${name}' not found`);
|
|
3496
|
-
return identity;
|
|
3497
|
-
}
|
|
3498
|
-
setTokens(tokens, cookies) {
|
|
3499
|
-
const exp = tokens.refresh_token_expires_in || tokens.refresh_expires_in || tokens.expires_in;
|
|
3500
|
-
const ttl = exp ? this.dateTimeProvider.duration(exp, "seconds") : void 0;
|
|
3501
|
-
this.tokens.set(tokens, {
|
|
3502
|
-
cookies,
|
|
3503
|
-
ttl
|
|
3504
|
-
});
|
|
3505
|
-
}
|
|
3506
|
-
};
|
|
3507
|
-
|
|
3508
|
-
//#endregion
|
|
3509
|
-
//#region src/auth/descriptors/$authGithub.ts
|
|
3510
|
-
/**
|
|
3511
|
-
* Already configured GitHub authentication descriptor.
|
|
3512
|
-
*
|
|
3513
|
-
* Uses OAuth2 to authenticate users via their GitHub accounts.
|
|
3514
|
-
* Upon successful authentication, it links the GitHub account to a user session.
|
|
3515
|
-
*
|
|
3516
|
-
* Environment Variables:
|
|
3517
|
-
* - `GITHUB_CLIENT_ID`: The client ID obtained from the GitHub Developer Settings.
|
|
3518
|
-
* - `GITHUB_CLIENT_SECRET`: The client secret obtained from the GitHub Developer Settings.
|
|
3519
|
-
*/
|
|
3520
|
-
const $authGithub = (realm, options) => {
|
|
3521
|
-
const { alepha: alepha$1 } = (0, alepha.$context)();
|
|
3522
|
-
const env = alepha$1.parseEnv(alepha.t.object({
|
|
3523
|
-
GITHUB_CLIENT_ID: alepha.t.string(),
|
|
3524
|
-
GITHUB_CLIENT_SECRET: alepha.t.string()
|
|
3525
|
-
}));
|
|
3526
|
-
return $auth({
|
|
3527
|
-
realm,
|
|
3528
|
-
name: "github",
|
|
3529
|
-
oauth: {
|
|
3530
|
-
clientId: env.GITHUB_CLIENT_ID,
|
|
3531
|
-
clientSecret: env.GITHUB_CLIENT_SECRET,
|
|
3532
|
-
authorization: "https://github.com/login/oauth/authorize",
|
|
3533
|
-
token: "https://github.com/login/oauth/access_token",
|
|
3534
|
-
scope: "read:user user:email",
|
|
3535
|
-
userinfo: async (tokens) => {
|
|
3536
|
-
const BASE_URL = "https://api.github.com";
|
|
3537
|
-
const res = await fetch(`${BASE_URL}/user`, { headers: {
|
|
3538
|
-
Authorization: `Bearer ${tokens.access_token}`,
|
|
3539
|
-
"User-Agent": "Alepha"
|
|
3540
|
-
} }).then((res$1) => res$1.json());
|
|
3541
|
-
const user = { sub: res.id.toString() };
|
|
3542
|
-
if (res.email) user.email = res.email;
|
|
3543
|
-
if (res.name) user.name = res.name.trim();
|
|
3544
|
-
if (res.avatar_url) user.picture = res.avatar_url;
|
|
3545
|
-
if (!user.email) {
|
|
3546
|
-
const res$1 = await fetch(`${BASE_URL}/user/emails`, { headers: {
|
|
3547
|
-
Authorization: `Bearer ${tokens.access_token}`,
|
|
3548
|
-
"User-Agent": "Alepha"
|
|
3549
|
-
} });
|
|
3550
|
-
if (res$1.ok) {
|
|
3551
|
-
const emails = await res$1.json();
|
|
3552
|
-
user.email = (emails.find((e$1) => e$1.primary) ?? emails[0]).email;
|
|
3553
|
-
}
|
|
3554
|
-
}
|
|
3555
|
-
return user;
|
|
3556
|
-
},
|
|
3557
|
-
...options
|
|
3558
|
-
}
|
|
3559
|
-
});
|
|
3560
|
-
};
|
|
3561
|
-
|
|
3562
|
-
//#endregion
|
|
3563
|
-
//#region src/auth/descriptors/$authGoogle.ts
|
|
3564
|
-
/**
|
|
3565
|
-
* Already configured Google authentication descriptor.
|
|
3566
|
-
*
|
|
3567
|
-
* Uses OpenID Connect (OIDC) to authenticate users via their Google accounts.
|
|
3568
|
-
* Upon successful authentication, it links the Google account to a user session.
|
|
3569
|
-
*
|
|
3570
|
-
* Environment Variables:
|
|
3571
|
-
* - `GOOGLE_CLIENT_ID`: The client ID obtained from the Google Developer Console.
|
|
3572
|
-
* - `GOOGLE_CLIENT_SECRET`: The client secret obtained from the Google Developer Console.
|
|
3573
|
-
*/
|
|
3574
|
-
const $authGoogle = (realm, options) => {
|
|
3575
|
-
const { alepha: alepha$1 } = (0, alepha.$context)();
|
|
3576
|
-
const env = alepha$1.parseEnv(alepha.t.object({
|
|
3577
|
-
GOOGLE_CLIENT_ID: alepha.t.string(),
|
|
3578
|
-
GOOGLE_CLIENT_SECRET: alepha.t.string()
|
|
3579
|
-
}));
|
|
3580
|
-
return $auth({
|
|
3581
|
-
realm,
|
|
3582
|
-
name: "google",
|
|
3583
|
-
oidc: {
|
|
3584
|
-
issuer: "https://accounts.google.com",
|
|
3585
|
-
clientId: env.GOOGLE_CLIENT_ID,
|
|
3586
|
-
clientSecret: env.GOOGLE_CLIENT_SECRET,
|
|
3587
|
-
...options
|
|
3588
|
-
}
|
|
3589
|
-
});
|
|
3590
|
-
};
|
|
3591
|
-
|
|
3592
|
-
//#endregion
|
|
3593
|
-
//#region src/auth/errors/SessionExpiredError.ts
|
|
3594
|
-
var SessionExpiredError = class extends alepha.AlephaError {
|
|
3595
|
-
name = "SessionExpiredError";
|
|
3596
|
-
status = 401;
|
|
3597
1754
|
};
|
|
3598
1755
|
|
|
3599
1756
|
//#endregion
|
|
@@ -3625,23 +1782,19 @@ const useAuth = () => {
|
|
|
3625
1782
|
*/
|
|
3626
1783
|
const AlephaReactAuth = (0, alepha.$module)({
|
|
3627
1784
|
name: "alepha.react.auth",
|
|
3628
|
-
descriptors: [
|
|
1785
|
+
descriptors: [alepha_server_auth.$auth],
|
|
3629
1786
|
services: [
|
|
3630
1787
|
AlephaReact,
|
|
3631
|
-
|
|
1788
|
+
alepha_server_links.AlephaServerLinks,
|
|
1789
|
+
alepha_server_auth.AlephaServerAuth,
|
|
3632
1790
|
ReactAuthProvider,
|
|
3633
1791
|
ReactAuth
|
|
3634
1792
|
]
|
|
3635
1793
|
});
|
|
3636
1794
|
|
|
3637
1795
|
//#endregion
|
|
3638
|
-
exports.$auth = $auth;
|
|
3639
|
-
exports.$authGithub = $authGithub;
|
|
3640
|
-
exports.$authGoogle = $authGoogle;
|
|
3641
1796
|
exports.AlephaReactAuth = AlephaReactAuth;
|
|
3642
|
-
exports.AuthDescriptor = AuthDescriptor;
|
|
3643
1797
|
exports.ReactAuth = ReactAuth;
|
|
3644
1798
|
exports.ReactAuthProvider = ReactAuthProvider;
|
|
3645
|
-
exports.SessionExpiredError = SessionExpiredError;
|
|
3646
1799
|
exports.useAuth = useAuth;
|
|
3647
1800
|
//# sourceMappingURL=index.cjs.map
|