@civic/auth 0.2.5-alpha.3 → 0.3.0-alpha.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/CHANGELOG.md +0 -3
- package/dist/cjs/constants.d.ts +1 -2
- package/dist/cjs/constants.d.ts.map +1 -1
- package/dist/cjs/constants.js +1 -3
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/nextjs/GetUser.d.ts +6 -0
- package/dist/cjs/nextjs/GetUser.d.ts.map +1 -0
- package/dist/cjs/nextjs/GetUser.js +11 -0
- package/dist/cjs/nextjs/GetUser.js.map +1 -0
- package/dist/cjs/nextjs/config.d.ts.map +1 -1
- package/dist/cjs/nextjs/config.js +8 -1
- package/dist/cjs/nextjs/config.js.map +1 -1
- package/dist/cjs/nextjs/cookies.d.ts.map +1 -1
- package/dist/cjs/nextjs/cookies.js +2 -43
- package/dist/cjs/nextjs/cookies.js.map +1 -1
- package/dist/cjs/nextjs/index.d.ts +3 -1
- package/dist/cjs/nextjs/index.d.ts.map +1 -1
- package/dist/cjs/nextjs/index.js +8 -3
- package/dist/cjs/nextjs/index.js.map +1 -1
- package/dist/cjs/nextjs/routeHandler.d.ts.map +1 -1
- package/dist/cjs/nextjs/routeHandler.js +9 -10
- package/dist/cjs/nextjs/routeHandler.js.map +1 -1
- package/dist/cjs/reactjs/hooks/useAuth.d.ts +3 -0
- package/dist/cjs/reactjs/hooks/useAuth.d.ts.map +1 -0
- package/dist/cjs/reactjs/hooks/useAuth.js +15 -0
- package/dist/cjs/reactjs/hooks/useAuth.js.map +1 -0
- package/dist/cjs/reactjs/hooks/useSignIn.d.ts +6 -0
- package/dist/cjs/reactjs/hooks/useSignIn.d.ts.map +1 -0
- package/dist/cjs/reactjs/hooks/useSignIn.js +38 -0
- package/dist/cjs/reactjs/hooks/useSignIn.js.map +1 -0
- package/dist/cjs/server/index.d.ts +1 -1
- package/dist/cjs/server/index.d.ts.map +1 -1
- package/dist/cjs/server/index.js +3 -1
- package/dist/cjs/server/index.js.map +1 -1
- package/dist/cjs/services/AuthenticationService.d.ts.map +1 -1
- package/dist/cjs/services/AuthenticationService.js +12 -20
- package/dist/cjs/services/AuthenticationService.js.map +1 -1
- package/dist/cjs/services/UserinfoService.d.ts +5 -0
- package/dist/cjs/services/UserinfoService.d.ts.map +1 -0
- package/dist/cjs/services/UserinfoService.js +15 -0
- package/dist/cjs/services/UserinfoService.js.map +1 -0
- package/dist/cjs/shared/hooks/useClientTokenExchangeSession.d.ts +3 -0
- package/dist/cjs/shared/hooks/useClientTokenExchangeSession.d.ts.map +1 -0
- package/dist/cjs/shared/hooks/useClientTokenExchangeSession.js +16 -0
- package/dist/cjs/shared/hooks/useClientTokenExchangeSession.js.map +1 -0
- package/dist/cjs/shared/lib/BrowserCookieStorage.d.ts.map +1 -1
- package/dist/cjs/shared/lib/BrowserCookieStorage.js +8 -7
- package/dist/cjs/shared/lib/BrowserCookieStorage.js.map +1 -1
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.d.ts.map +1 -1
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.js +6 -6
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.js.map +1 -1
- package/dist/cjs/shared/lib/session.d.ts +8 -1
- package/dist/cjs/shared/lib/session.d.ts.map +1 -1
- package/dist/cjs/shared/lib/session.js +45 -5
- package/dist/cjs/shared/lib/session.js.map +1 -1
- package/dist/cjs/shared/lib/types.d.ts +2 -2
- package/dist/cjs/shared/lib/types.d.ts.map +1 -1
- package/dist/cjs/shared/lib/types.js +3 -3
- package/dist/cjs/shared/lib/types.js.map +1 -1
- package/dist/cjs/shared/lib/util.d.ts +1 -3
- package/dist/cjs/shared/lib/util.d.ts.map +1 -1
- package/dist/cjs/shared/lib/util.js +11 -28
- package/dist/cjs/shared/lib/util.js.map +1 -1
- package/dist/cjs/shared/providers/AuthProvider.d.ts +22 -0
- package/dist/cjs/shared/providers/AuthProvider.d.ts.map +1 -0
- package/dist/cjs/shared/providers/AuthProvider.js +108 -0
- package/dist/cjs/shared/providers/AuthProvider.js.map +1 -0
- package/dist/cjs/shared/providers/CivicAuthProvider.d.ts +6 -0
- package/dist/cjs/shared/providers/CivicAuthProvider.d.ts.map +1 -0
- package/dist/cjs/shared/providers/CivicAuthProvider.js +38 -0
- package/dist/cjs/shared/providers/CivicAuthProvider.js.map +1 -0
- package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.d.ts +17 -0
- package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -0
- package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.js +168 -0
- package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.js.map +1 -0
- package/dist/cjs/shared/version.d.ts +1 -1
- package/dist/cjs/shared/version.js +1 -1
- package/dist/cjs/shared/version.js.map +1 -1
- package/dist/cjs/types.d.ts +3 -2
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/constants.d.ts +1 -2
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +1 -2
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/nextjs/GetUser.d.ts +6 -0
- package/dist/esm/nextjs/GetUser.d.ts.map +1 -0
- package/dist/esm/nextjs/GetUser.js +7 -0
- package/dist/esm/nextjs/GetUser.js.map +1 -0
- package/dist/esm/nextjs/config.d.ts.map +1 -1
- package/dist/esm/nextjs/config.js +8 -1
- package/dist/esm/nextjs/config.js.map +1 -1
- package/dist/esm/nextjs/cookies.d.ts.map +1 -1
- package/dist/esm/nextjs/cookies.js +3 -11
- package/dist/esm/nextjs/cookies.js.map +1 -1
- package/dist/esm/nextjs/index.d.ts +3 -1
- package/dist/esm/nextjs/index.d.ts.map +1 -1
- package/dist/esm/nextjs/index.js +7 -3
- package/dist/esm/nextjs/index.js.map +1 -1
- package/dist/esm/nextjs/routeHandler.d.ts.map +1 -1
- package/dist/esm/nextjs/routeHandler.js +10 -11
- package/dist/esm/nextjs/routeHandler.js.map +1 -1
- package/dist/esm/reactjs/hooks/useAuth.d.ts +3 -0
- package/dist/esm/reactjs/hooks/useAuth.d.ts.map +1 -0
- package/dist/esm/reactjs/hooks/useAuth.js +12 -0
- package/dist/esm/reactjs/hooks/useAuth.js.map +1 -0
- package/dist/esm/reactjs/hooks/useSignIn.d.ts +6 -0
- package/dist/esm/reactjs/hooks/useSignIn.d.ts.map +1 -0
- package/dist/esm/reactjs/hooks/useSignIn.js +34 -0
- package/dist/esm/reactjs/hooks/useSignIn.js.map +1 -0
- package/dist/esm/server/index.d.ts +1 -1
- package/dist/esm/server/index.d.ts.map +1 -1
- package/dist/esm/server/index.js +1 -1
- package/dist/esm/server/index.js.map +1 -1
- package/dist/esm/services/AuthenticationService.d.ts.map +1 -1
- package/dist/esm/services/AuthenticationService.js +13 -20
- package/dist/esm/services/AuthenticationService.js.map +1 -1
- package/dist/esm/shared/hooks/useClientTokenExchangeSession.d.ts +3 -0
- package/dist/esm/shared/hooks/useClientTokenExchangeSession.d.ts.map +1 -0
- package/dist/esm/shared/hooks/useClientTokenExchangeSession.js +13 -0
- package/dist/esm/shared/hooks/useClientTokenExchangeSession.js.map +1 -0
- package/dist/esm/shared/lib/BrowserCookieStorage.d.ts.map +1 -1
- package/dist/esm/shared/lib/BrowserCookieStorage.js +8 -7
- package/dist/esm/shared/lib/BrowserCookieStorage.js.map +1 -1
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.d.ts.map +1 -1
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.js +7 -7
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.js.map +1 -1
- package/dist/esm/shared/lib/session.d.ts +8 -1
- package/dist/esm/shared/lib/session.d.ts.map +1 -1
- package/dist/esm/shared/lib/session.js +42 -5
- package/dist/esm/shared/lib/session.js.map +1 -1
- package/dist/esm/shared/lib/types.d.ts +2 -2
- package/dist/esm/shared/lib/types.d.ts.map +1 -1
- package/dist/esm/shared/lib/types.js +2 -2
- package/dist/esm/shared/lib/types.js.map +1 -1
- package/dist/esm/shared/lib/util.d.ts +1 -3
- package/dist/esm/shared/lib/util.d.ts.map +1 -1
- package/dist/esm/shared/lib/util.js +11 -26
- package/dist/esm/shared/lib/util.js.map +1 -1
- package/dist/esm/shared/providers/AuthProvider.d.ts +22 -0
- package/dist/esm/shared/providers/AuthProvider.d.ts.map +1 -0
- package/dist/esm/shared/providers/AuthProvider.js +72 -0
- package/dist/esm/shared/providers/AuthProvider.js.map +1 -0
- package/dist/esm/shared/providers/CivicAuthProvider.d.ts +6 -0
- package/dist/esm/shared/providers/CivicAuthProvider.d.ts.map +1 -0
- package/dist/esm/shared/providers/CivicAuthProvider.js +32 -0
- package/dist/esm/shared/providers/CivicAuthProvider.js.map +1 -0
- package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.d.ts +17 -0
- package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -0
- package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.js +131 -0
- package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.js.map +1 -0
- package/dist/esm/shared/version.d.ts +1 -1
- package/dist/esm/shared/version.js +1 -1
- package/dist/esm/shared/version.js.map +1 -1
- package/dist/esm/types.d.ts +3 -2
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +19 -29
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrowserCookieStorage.js","sourceRoot":"","sources":["../../../../src/shared/lib/BrowserCookieStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,GAEd,MAAM,yBAAyB,CAAC;AAEjC,4CAA4C;AAC5C,SAAS,WAAW;IAClB,IAAI,OAAO,UAAU,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC,QAAQ,CAAC;IACzE,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;IAChC,MAAM,IAAI,KAAK,CACb,gDAAgD,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CACzE,CAAC;AACJ,CAAC;AAED,MAAM,
|
|
1
|
+
{"version":3,"file":"BrowserCookieStorage.js","sourceRoot":"","sources":["../../../../src/shared/lib/BrowserCookieStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,GAEd,MAAM,yBAAyB,CAAC;AAEjC,4CAA4C;AAC5C,SAAS,WAAW;IAClB,IAAI,OAAO,UAAU,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC,QAAQ,CAAC;IACzE,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;IAChC,MAAM,IAAI,KAAK,CACb,gDAAgD,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CACzE,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,oBAAqB,SAAQ,aAAa;IACrD,YAAY,SAAyC,EAAE;QACrD,KAAK,CAAC;YACJ,4BAA4B;YAC5B,MAAM,EAAE,KAAK;YACb,QAAQ,EAAE,KAAK;YACf,GAAG,MAAM;SACV,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,CACL,WAAW,EAAE;aACV,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;aACjB,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnD,IAAI,SAAS,EAAE,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBAC9B,OAAO,WAAW,CAAC;YACrB,CAAC;QACH,CAAC,CAAC,IAAI,IAAI,CACb,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,cAAc,GAAG,EAAE,CAAC;QAExB,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAClB,cAAc,IAAI,QAAQ,QAAQ,CAAC,IAAI,IAAI,CAAC;QAC9C,CAAC;QACD,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,cAAc,IAAI,WAAW,QAAQ,CAAC,OAAO,IAAI,CAAC;QACpD,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,cAAc,IAAI,UAAU,CAAC;QAC/B,CAAC;QACD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,qFAAqF;YACrF,OAAO,CAAC,IAAI,CACV,uEAAuE,CACxE,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,cAAc,IAAI,YAAY,QAAQ,CAAC,QAAQ,IAAI,CAAC;QACtD,CAAC;QAED,WAAW,EAAE,CAAC,MAAM,GAAG,GAAG,GAAG,IAAI,KAAK,KAAK,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;IACrE,CAAC;CACF","sourcesContent":["import {\n CookieStorage,\n type CookieStorageSettings,\n} from \"@/shared/lib/storage.js\";\n\n// Ensure only runs in a browser environment\nfunction documentObj() {\n if (typeof globalThis.window !== \"undefined\") return globalThis.document;\n const stack = new Error().stack;\n throw new Error(\n \"Document is not available in this environment:\" + JSON.stringify(stack),\n );\n}\n\nexport class BrowserCookieStorage extends CookieStorage {\n constructor(config: Partial<CookieStorageSettings> = {}) {\n super({\n // sensible browser defaults\n secure: false,\n httpOnly: false,\n ...config,\n });\n }\n\n async get(key: string): Promise<string | null> {\n return (\n documentObj()\n .cookie.split(\";\")\n .find((cookie) => {\n const [cookieKey, cookieValue] = cookie.split(\"=\");\n if (cookieKey?.trim() === key) {\n return cookieValue;\n }\n }) ?? null\n );\n }\n\n async set(key: string, value: string): Promise<void> {\n const settings = this.settings;\n let cookieSettings = \"\";\n\n if (settings.path) {\n cookieSettings += `Path=${settings.path}; `;\n }\n if (settings.expires) {\n cookieSettings += `Expires=${settings.expires}; `;\n }\n if (settings.secure) {\n cookieSettings += `Secure; `;\n }\n if (settings.httpOnly) {\n // HttpOnly cannot be set from client-side JavaScript, so this clause can be omitted.\n console.warn(\n \"HttpOnly cannot be set on client-side cookies. Ignoring this setting.\",\n );\n }\n if (settings.sameSite) {\n cookieSettings += `SameSite=${settings.sameSite}; `;\n }\n\n documentObj().cookie = `${key}=${value}; ${cookieSettings.trim()}`;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GenericAuthenticationRefresher.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/GenericAuthenticationRefresher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"GenericAuthenticationRefresher.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/GenericAuthenticationRefresher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAErE,8BAAsB,8BACpB,YAAW,uBAAuB;IAElC,OAAO,CAAC,cAAc,CAA6B;IACnD,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7C,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IAE3C,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,QAAQ,CAAC,kBAAkB,CACzB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,qBAAqB,CAAC;IAE3B,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAQlC,aAAa;YAIL,aAAa;IASrB,gBAAgB;IAmBtB,gBAAgB;CAKjB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_AUTH_SERVER } from "../../constants.js";
|
|
2
|
-
import {
|
|
2
|
+
import { retrieveTokenExpiration, retrieveTokens } from "../../shared/lib/util.js";
|
|
3
3
|
export class GenericAuthenticationRefresher {
|
|
4
4
|
refreshTimeout;
|
|
5
5
|
authConfig;
|
|
@@ -25,7 +25,6 @@ export class GenericAuthenticationRefresher {
|
|
|
25
25
|
}
|
|
26
26
|
catch (error) {
|
|
27
27
|
console.error("Failed to refresh tokens:", error);
|
|
28
|
-
// TODO detect if refresh token has expired and if yes then logout
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
async setupAutorefresh() {
|
|
@@ -34,14 +33,15 @@ export class GenericAuthenticationRefresher {
|
|
|
34
33
|
// Clear any existing timeout
|
|
35
34
|
this.clearAutorefresh();
|
|
36
35
|
// get expires_in
|
|
37
|
-
const
|
|
38
|
-
const
|
|
36
|
+
const expiration = await retrieveTokenExpiration(this.storage);
|
|
37
|
+
const expires_in = Number(expiration) || 60;
|
|
39
38
|
// Calculate time until expiry (subtract 30 seconds as buffer)
|
|
40
|
-
const
|
|
41
|
-
const
|
|
39
|
+
const bufferTimeMs = 30 * 1000; // 30 seconds in milliseconds
|
|
40
|
+
const expiresInMs = expires_in * 1000; // Convert to milliseconds
|
|
41
|
+
const refreshTimeMs = Math.max(0, expiresInMs - bufferTimeMs);
|
|
42
42
|
this.refreshTimeout = setTimeout(() => {
|
|
43
43
|
this.handleRefresh();
|
|
44
|
-
},
|
|
44
|
+
}, refreshTimeMs);
|
|
45
45
|
}
|
|
46
46
|
clearAutorefresh() {
|
|
47
47
|
if (this.refreshTimeout) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GenericAuthenticationRefresher.js","sourceRoot":"","sources":["../../../../src/shared/lib/GenericAuthenticationRefresher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,
|
|
1
|
+
{"version":3,"file":"GenericAuthenticationRefresher.js","sourceRoot":"","sources":["../../../../src/shared/lib/GenericAuthenticationRefresher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG/E,MAAM,OAAgB,8BAA8B;IAG1C,cAAc,CAA6B;IACzC,UAAU,CAAyB;IACnC,OAAO,CAA0B;IAE3C,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,UAAU,EAAE,WAAW,IAAI,mBAAmB,CAAC;IAC7D,CAAC;IAMD,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAE3D,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,EAAE,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC1E,OAAO,MAAM,CAAC,aAAa,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,6CAA6C;QAC9E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC3D,6BAA6B;QAC7B,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAExB,iBAAiB;QACjB,MAAM,UAAU,GAAG,MAAM,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAE5C,8DAA8D;QAC9D,MAAM,YAAY,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,6BAA6B;QAC7D,MAAM,WAAW,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC,0BAA0B;QACjE,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,YAAY,CAAC,CAAC;QAE9D,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC,EAAE,aAAa,CAAC,CAAC;IACpB,CAAC;IAED,gBAAgB;QACd,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;CACF","sourcesContent":["import { DEFAULT_AUTH_SERVER } from \"@/constants.js\";\nimport type { AuthConfig } from \"@/server/config.js\";\nimport type { AuthenticationRefresher } from \"@/services/types.js\";\nimport { retrieveTokenExpiration, retrieveTokens } from \"@/shared/lib/util.js\";\nimport type { AuthStorage, OIDCTokenResponseBody } from \"@/types.js\";\n\nexport abstract class GenericAuthenticationRefresher\n implements AuthenticationRefresher\n{\n private refreshTimeout: NodeJS.Timeout | undefined;\n protected authConfig: AuthConfig | undefined;\n protected storage: AuthStorage | undefined;\n\n get oauthServer(): string {\n return this.authConfig?.oauthServer || DEFAULT_AUTH_SERVER;\n }\n\n abstract refreshAccessToken(\n refreshToken?: string,\n ): Promise<OIDCTokenResponseBody>;\n\n async getRefreshToken(): Promise<string> {\n if (!this.storage) throw new Error(\"No storage available\");\n\n const tokens = await retrieveTokens(this.storage);\n if (!tokens?.refresh_token) throw new Error(\"No refresh token available\");\n return tokens.refresh_token;\n }\n\n async refreshTokens() {\n return this.refreshAccessToken();\n }\n\n private async handleRefresh() {\n try {\n await this.refreshTokens();\n await this.setupAutorefresh(); // Reset the timeout after successful refresh\n } catch (error) {\n console.error(\"Failed to refresh tokens:\", error);\n }\n }\n\n async setupAutorefresh() {\n if (!this.storage) throw new Error(\"No storage available\");\n // Clear any existing timeout\n this.clearAutorefresh();\n\n // get expires_in\n const expiration = await retrieveTokenExpiration(this.storage);\n const expires_in = Number(expiration) || 60;\n\n // Calculate time until expiry (subtract 30 seconds as buffer)\n const bufferTimeMs = 30 * 1000; // 30 seconds in milliseconds\n const expiresInMs = expires_in * 1000; // Convert to milliseconds\n const refreshTimeMs = Math.max(0, expiresInMs - bufferTimeMs);\n\n this.refreshTimeout = setTimeout(() => {\n this.handleRefresh();\n }, refreshTimeMs);\n }\n\n clearAutorefresh() {\n if (this.refreshTimeout) {\n clearTimeout(this.refreshTimeout);\n }\n }\n}\n"]}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { type AuthStorage, type OAuthTokens, type User } from "../../types.js";
|
|
2
|
-
export
|
|
2
|
+
export type ClaimOptions = {
|
|
3
|
+
allClaims: boolean;
|
|
4
|
+
localOnly: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare const defaultClaimOptions: ClaimOptions;
|
|
7
|
+
export declare function getClaim(storage: AuthStorage, claimName: string, options?: ClaimOptions, userinfoEndpoint?: string): Promise<string | null>;
|
|
8
|
+
export declare function getUser(storage: AuthStorage, options?: ClaimOptions, userinfoEndpoint?: string): Promise<User | null>;
|
|
9
|
+
export declare function getUserInfo(storage: AuthStorage, options: ClaimOptions | undefined, userinfoEndpoint: string): Promise<object | null>;
|
|
3
10
|
export declare function getTokens(storage: AuthStorage): Promise<OAuthTokens | null>;
|
|
4
11
|
//# sourceMappingURL=session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,IAAI,EACV,MAAM,YAAY,CAAC;AAcpB,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,IAAI,EACV,MAAM,YAAY,CAAC;AAcpB,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AACF,eAAO,MAAM,mBAAmB,EAAE,YAGjC,CAAC;AAEF,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,YAAkC,EAC3C,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMxB;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,YAAkC,EAC3C,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAatB;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,YAAY,YAAsB,EAC3C,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBxB;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAS7B"}
|
|
@@ -9,14 +9,51 @@ const omitKeys = (keys, obj) => {
|
|
|
9
9
|
});
|
|
10
10
|
return result;
|
|
11
11
|
};
|
|
12
|
-
export
|
|
12
|
+
export const defaultClaimOptions = {
|
|
13
|
+
allClaims: true,
|
|
14
|
+
localOnly: true,
|
|
15
|
+
};
|
|
16
|
+
export async function getClaim(storage, claimName, options = defaultClaimOptions, userinfoEndpoint) {
|
|
17
|
+
const tokens = await retrieveTokens(storage);
|
|
18
|
+
if (!tokens)
|
|
19
|
+
return null;
|
|
20
|
+
const user = await getUser(storage, options, userinfoEndpoint);
|
|
21
|
+
return user && user[claimName] ? user[claimName] : null;
|
|
22
|
+
}
|
|
23
|
+
export async function getUser(storage, options = defaultClaimOptions, userinfoEndpoint) {
|
|
13
24
|
const tokens = await retrieveTokens(storage);
|
|
14
25
|
if (!tokens)
|
|
15
26
|
return null;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
27
|
+
const idTokenClaims = parseJWT(tokens.id_token)?.payload;
|
|
28
|
+
if (!options.allClaims) {
|
|
29
|
+
return idTokenClaims ? omitKeys(tokenKeys, idTokenClaims) : null;
|
|
30
|
+
}
|
|
31
|
+
const userinfoClaims = userinfoEndpoint
|
|
32
|
+
? await getUserInfo(storage, options, userinfoEndpoint)
|
|
33
|
+
: {};
|
|
34
|
+
return { ...idTokenClaims, ...userinfoClaims };
|
|
35
|
+
}
|
|
36
|
+
export async function getUserInfo(storage, options = defaultClaimOptions, userinfoEndpoint) {
|
|
37
|
+
// load userinfo from cache
|
|
38
|
+
const userinfoString = await storage.get("userinfo");
|
|
39
|
+
let userinfo = userinfoString && JSON.parse(userinfoString);
|
|
40
|
+
if (options.localOnly) {
|
|
41
|
+
return userinfo;
|
|
42
|
+
}
|
|
43
|
+
// retrieve tokens
|
|
44
|
+
const tokens = await retrieveTokens(storage);
|
|
45
|
+
if (!tokens)
|
|
46
|
+
return null;
|
|
47
|
+
// query userinfo from endpoint
|
|
48
|
+
const response = await fetch(userinfoEndpoint, {
|
|
49
|
+
headers: {
|
|
50
|
+
Authorization: `Bearer ${tokens.access_token}`,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
userinfo = await response.json();
|
|
54
|
+
// store userinfo to cache
|
|
55
|
+
await storage.set("userinfo", userinfo);
|
|
56
|
+
return userinfo;
|
|
20
57
|
}
|
|
21
58
|
export async function getTokens(storage) {
|
|
22
59
|
const storageData = await retrieveTokens(storage);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../../src/shared/lib/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EACL,SAAS,GAIV,MAAM,YAAY,CAAC;AAEpB,uCAAuC;AACvC,MAAM,QAAQ,GAAG,CACf,IAAS,EACT,GAAM,EACM,EAAE;IACd,MAAM,MAAM,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAC1B,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACnB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAoB;
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../../src/shared/lib/session.ts"],"names":[],"mappings":"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","sourcesContent":["import { retrieveTokens } from \"@/shared/lib/util.js\";\nimport { parseJWT } from \"oslo/jwt\";\nimport {\n tokenKeys,\n type AuthStorage,\n type OAuthTokens,\n type User,\n} from \"@/types.js\";\n\n// Function to omit keys from an object\nconst omitKeys = <K extends keyof T, T extends Record<string, unknown>>(\n keys: K[],\n obj: T,\n): Omit<T, K> => {\n const result = { ...obj };\n keys.forEach((key) => {\n delete result[key];\n });\n return result;\n};\n\nexport type ClaimOptions = {\n allClaims: boolean; // query additional userinfo claims\n localOnly: boolean; // only\n};\nexport const defaultClaimOptions: ClaimOptions = {\n allClaims: true,\n localOnly: true,\n};\n\nexport async function getClaim(\n storage: AuthStorage,\n claimName: string,\n options: ClaimOptions = defaultClaimOptions,\n userinfoEndpoint?: string,\n): Promise<string | null> {\n const tokens = await retrieveTokens(storage);\n if (!tokens) return null;\n\n const user = await getUser(storage, options, userinfoEndpoint);\n return user && user[claimName] ? user[claimName] : null;\n}\n\nexport async function getUser(\n storage: AuthStorage,\n options: ClaimOptions = defaultClaimOptions,\n userinfoEndpoint?: string,\n): Promise<User | null> {\n const tokens = await retrieveTokens(storage);\n if (!tokens) return null;\n\n const idTokenClaims = parseJWT(tokens.id_token)?.payload as User;\n if (!options.allClaims) {\n return idTokenClaims ? (omitKeys(tokenKeys, idTokenClaims) as User) : null;\n }\n\n const userinfoClaims = userinfoEndpoint\n ? await getUserInfo(storage, options, userinfoEndpoint)\n : {};\n return { ...idTokenClaims, ...userinfoClaims };\n}\n\nexport async function getUserInfo(\n storage: AuthStorage,\n options: ClaimOptions = defaultClaimOptions,\n userinfoEndpoint: string,\n): Promise<object | null> {\n // load userinfo from cache\n const userinfoString = await storage.get(\"userinfo\");\n let userinfo = userinfoString && JSON.parse(userinfoString);\n if (options.localOnly) {\n return userinfo;\n }\n\n // retrieve tokens\n const tokens = await retrieveTokens(storage);\n if (!tokens) return null;\n\n // query userinfo from endpoint\n const response = await fetch(userinfoEndpoint, {\n headers: {\n Authorization: `Bearer ${tokens.access_token}`,\n },\n });\n userinfo = await response.json();\n\n // store userinfo to cache\n await storage.set(\"userinfo\", userinfo);\n\n return userinfo;\n}\n\nexport async function getTokens(\n storage: AuthStorage,\n): Promise<OAuthTokens | null> {\n const storageData = await retrieveTokens(storage);\n if (!storageData) return null;\n\n return {\n idToken: storageData.id_token,\n accessToken: storageData.access_token,\n refreshToken: storageData.refresh_token,\n };\n}\n"]}
|
|
@@ -3,9 +3,9 @@ export declare enum OAuthTokens {
|
|
|
3
3
|
ID_TOKEN = "id_token",
|
|
4
4
|
ACCESS_TOKEN = "access_token",
|
|
5
5
|
REFRESH_TOKEN = "refresh_token",
|
|
6
|
-
|
|
6
|
+
EXPIRES_IN = "expires_in",
|
|
7
|
+
TIMESTAMP = "timestamp"
|
|
7
8
|
}
|
|
8
|
-
export declare const AUTH_SERVER_SESSION = "_session";
|
|
9
9
|
export declare enum CodeVerifier {
|
|
10
10
|
COOKIE_NAME = "code_verifier",
|
|
11
11
|
APP_URL = "app_url"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,oBAAY,WAAW;IACrB,QAAQ,aAAa;IACrB,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;IAC/B,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,oBAAY,WAAW;IACrB,QAAQ,aAAa;IACrB,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;IAC/B,UAAU,eAAe;IACzB,SAAS,cAAc;CACxB;AAED,oBAAY,YAAY;IACtB,WAAW,kBAAkB;IAC7B,OAAO,YAAY;CACpB;AACD,oBAAY,WAAW;IACrB,IAAI,SAAS;CACd;AACD,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,CACrC,WAAW,GAAG,YAAY,EAC1B,YAAY,CACb,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC"}
|
|
@@ -3,9 +3,9 @@ export var OAuthTokens;
|
|
|
3
3
|
OAuthTokens["ID_TOKEN"] = "id_token";
|
|
4
4
|
OAuthTokens["ACCESS_TOKEN"] = "access_token";
|
|
5
5
|
OAuthTokens["REFRESH_TOKEN"] = "refresh_token";
|
|
6
|
-
OAuthTokens["
|
|
6
|
+
OAuthTokens["EXPIRES_IN"] = "expires_in";
|
|
7
|
+
OAuthTokens["TIMESTAMP"] = "timestamp";
|
|
7
8
|
})(OAuthTokens || (OAuthTokens = {}));
|
|
8
|
-
export const AUTH_SERVER_SESSION = "_session";
|
|
9
9
|
export var CodeVerifier;
|
|
10
10
|
(function (CodeVerifier) {
|
|
11
11
|
CodeVerifier["COOKIE_NAME"] = "code_verifier";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/shared/lib/types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/shared/lib/types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,oCAAqB,CAAA;IACrB,4CAA6B,CAAA;IAC7B,8CAA+B,CAAA;IAC/B,wCAAyB,CAAA;IACzB,sCAAuB,CAAA;AACzB,CAAC,EANW,WAAW,KAAX,WAAW,QAMtB;AAED,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,6CAA6B,CAAA;IAC7B,mCAAmB,CAAA;AACrB,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB;AACD,MAAM,CAAN,IAAY,WAEX;AAFD,WAAY,WAAW;IACrB,4BAAa,CAAA;AACf,CAAC,EAFW,WAAW,KAAX,WAAW,QAEtB","sourcesContent":["import type { Endpoints } from \"@/types.js\";\n\nexport enum OAuthTokens {\n ID_TOKEN = \"id_token\",\n ACCESS_TOKEN = \"access_token\",\n REFRESH_TOKEN = \"refresh_token\",\n EXPIRES_IN = \"expires_in\",\n TIMESTAMP = \"timestamp\",\n}\n\nexport enum CodeVerifier {\n COOKIE_NAME = \"code_verifier\",\n APP_URL = \"app_url\",\n}\nexport enum UserStorage {\n USER = \"user\",\n}\nexport interface CookieConfig {\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n domain?: string;\n path?: string;\n maxAge?: number;\n httpOnly?: boolean;\n}\n\nexport type TokensCookieConfig = Record<\n OAuthTokens | CodeVerifier,\n CookieConfig\n>;\n\nexport type CivicAuthConfig = null | {\n clientId: string;\n redirectUrl: string;\n logoutRedirectUrl: string;\n oauthServer: string;\n endpoints: Endpoints;\n scopes: string[];\n nonce?: string;\n challengeUrl?: string;\n refrershUrl?: string;\n logoutUrl?: string;\n};\n"]}
|
|
@@ -26,12 +26,10 @@ export declare function generateOauthLogoutUrl(config: {
|
|
|
26
26
|
}): Promise<URL>;
|
|
27
27
|
export declare function buildOauth2Client(clientId: string, redirectUri: string, endpoints: Endpoints): OAuth2Client;
|
|
28
28
|
export declare function exchangeTokens(code: string, state: string, pkceProducer: PKCEProducer, oauth2Client: OAuth2Client, oauthServer: string, endpoints: Endpoints): Promise<OIDCTokenResponseBody>;
|
|
29
|
-
export declare function setAccessTokenExpiresAt(storage: AuthStorage, tokens: OIDCTokenResponseBody): Promise<void>;
|
|
30
29
|
export declare function storeTokens(storage: AuthStorage, tokens: OIDCTokenResponseBody): Promise<void>;
|
|
31
30
|
export declare function clearTokens(storage: AuthStorage): Promise<void>;
|
|
32
|
-
export declare function clearAuthServerSession(storage: AuthStorage): Promise<void>;
|
|
33
31
|
export declare function clearUser(storage: AuthStorage): Promise<void>;
|
|
34
32
|
export declare function retrieveTokens(storage: AuthStorage): Promise<OIDCTokenResponseBody | null>;
|
|
35
|
-
export declare function
|
|
33
|
+
export declare function retrieveTokenExpiration(storage: AuthStorage): Promise<string | null>;
|
|
36
34
|
export declare function validateOauth2Tokens(tokens: OIDCTokenResponseBody, endpoints: Endpoints, oauth2Client: OAuth2Client, issuer: string): Promise<ParsedTokens>;
|
|
37
35
|
//# sourceMappingURL=util.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/util.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAET,qBAAqB,EACrB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/util.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAET,qBAAqB,EACrB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGtE;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,MAAM,EACpB,MAAM,GAAE,OAAO,GAAG,MAAe,GAChC,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,iBAAiB,GAAE,OAAO,CAAC,SAAS,CAAM,GACzC,OAAO,CAAC,SAAS,CAAC,CAMpB;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAEvC,YAAY,EAAE,YAAY,CAAC;CAC5B,GAAG,OAAO,CAAC,GAAG,CAAC,CA2Bf;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;CACxC,GAAG,OAAO,CAAC,GAAG,CAAC,CAcf;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,SAAS,GACnB,YAAY,CAId;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,SAAS,kCAoBrB;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,qBAAqB,iBAY9B;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,iBAKrD;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,WAAW,iBAGnD;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAgBvC;AAED,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,WAAW,0BAEjE;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,qBAAqB,EAC7B,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,YAAY,CAAC,CA2BvB"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OAuthTokens } from "./types.js";
|
|
2
2
|
import { OAuth2Client } from "oslo/oauth2";
|
|
3
3
|
import { getIssuerVariations, getOauthEndpoints } from "../../lib/oauth.js";
|
|
4
4
|
import * as jose from "jose";
|
|
5
5
|
import { withoutUndefined } from "../../utils.js";
|
|
6
6
|
import { GenericUserSession } from "../../shared/lib/UserSession.js";
|
|
7
|
-
import { parseJWT } from "oslo/jwt";
|
|
8
7
|
/**
|
|
9
8
|
* Given a PKCE code verifier, derive the code challenge using SHA
|
|
10
9
|
*/
|
|
@@ -79,20 +78,6 @@ export async function exchangeTokens(code, state, pkceProducer, oauth2Client, oa
|
|
|
79
78
|
}
|
|
80
79
|
return tokens;
|
|
81
80
|
}
|
|
82
|
-
export async function setAccessTokenExpiresAt(storage, tokens) {
|
|
83
|
-
// try to extract absolut expiry time from access token but fallback to calculation if not possible
|
|
84
|
-
const parsedAccessToken = parseJWT(tokens.access_token);
|
|
85
|
-
if (parsedAccessToken && parsedAccessToken?.expiresAt) {
|
|
86
|
-
await storage.set(OAuthTokens.ACCESS_TOKEN_EXPIRES_AT, parsedAccessToken.expiresAt?.getTime().toString());
|
|
87
|
-
}
|
|
88
|
-
else if (tokens.expires_in) {
|
|
89
|
-
const now = Math.floor(new Date().getTime() / 1000);
|
|
90
|
-
await storage.set(OAuthTokens.ACCESS_TOKEN_EXPIRES_AT, (now + tokens.expires_in).toString());
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
throw new Error("Cannot determine access token expiry!");
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
81
|
export async function storeTokens(storage, tokens) {
|
|
97
82
|
// store tokens in storage ( TODO we should probably store them against the state to allow multiple logins )
|
|
98
83
|
await storage.set(OAuthTokens.ID_TOKEN, tokens.id_token);
|
|
@@ -100,7 +85,10 @@ export async function storeTokens(storage, tokens) {
|
|
|
100
85
|
if (tokens.refresh_token) {
|
|
101
86
|
await storage.set(OAuthTokens.REFRESH_TOKEN, tokens.refresh_token);
|
|
102
87
|
}
|
|
103
|
-
|
|
88
|
+
if (tokens.expires_in) {
|
|
89
|
+
await storage.set(OAuthTokens.EXPIRES_IN, tokens.expires_in.toString());
|
|
90
|
+
await storage.set(OAuthTokens.TIMESTAMP, new Date().getTime().toString());
|
|
91
|
+
}
|
|
104
92
|
}
|
|
105
93
|
export async function clearTokens(storage) {
|
|
106
94
|
const clearOAuthPromises = Object.values(OAuthTokens).map(async (key) => {
|
|
@@ -108,9 +96,6 @@ export async function clearTokens(storage) {
|
|
|
108
96
|
});
|
|
109
97
|
await Promise.all([...clearOAuthPromises]);
|
|
110
98
|
}
|
|
111
|
-
export async function clearAuthServerSession(storage) {
|
|
112
|
-
await storage.set(AUTH_SERVER_SESSION, "");
|
|
113
|
-
}
|
|
114
99
|
export async function clearUser(storage) {
|
|
115
100
|
const userSession = new GenericUserSession(storage);
|
|
116
101
|
await userSession.set(null);
|
|
@@ -119,20 +104,20 @@ export async function retrieveTokens(storage) {
|
|
|
119
104
|
const idToken = await storage.get(OAuthTokens.ID_TOKEN);
|
|
120
105
|
const accessToken = await storage.get(OAuthTokens.ACCESS_TOKEN);
|
|
121
106
|
const refreshToken = await storage.get(OAuthTokens.REFRESH_TOKEN);
|
|
122
|
-
const
|
|
107
|
+
const expiresIn = await storage.get(OAuthTokens.EXPIRES_IN);
|
|
108
|
+
const timestamp = await storage.get(OAuthTokens.TIMESTAMP);
|
|
123
109
|
if (!idToken || !accessToken)
|
|
124
110
|
return null;
|
|
125
111
|
return {
|
|
126
112
|
id_token: idToken,
|
|
127
113
|
access_token: accessToken,
|
|
128
114
|
refresh_token: refreshToken ?? undefined,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
: undefined, // Convert string to number
|
|
115
|
+
expires_in: expiresIn ? parseInt(expiresIn, 10) : undefined, // Convert string to number
|
|
116
|
+
timestamp: timestamp ? parseInt(timestamp, 10) : undefined, // Convert string to number
|
|
132
117
|
};
|
|
133
118
|
}
|
|
134
|
-
export async function
|
|
135
|
-
return
|
|
119
|
+
export async function retrieveTokenExpiration(storage) {
|
|
120
|
+
return await storage.get(OAuthTokens.EXPIRES_IN);
|
|
136
121
|
}
|
|
137
122
|
export async function validateOauth2Tokens(tokens, endpoints, oauth2Client, issuer) {
|
|
138
123
|
const JWKS = jose.createRemoteJWKSet(new URL(endpoints.jwks));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../../src/shared/lib/util.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,YAAoB,EACpB,SAA2B,MAAM;IAEjC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QAC3D,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;SACxD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,WAAmB,EACnB,oBAAwC,EAAE;IAE1C,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACvD,OAAO;QACL,GAAG,SAAS;QACZ,GAAG,iBAAiB;KACrB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAU3C;IACC,MAAM,SAAS,GAAG,MAAM,yBAAyB,CAC/C,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,iBAAiB,CACzB,CAAC;IACF,MAAM,YAAY,GAAG,iBAAiB,CACpC,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,WAAW,EAClB,SAAS,CACV,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC;IAC/D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,sBAAsB,CAAC;QACzD,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CAAC;IACH,yGAAyG;IACzG,yEAAyE;IACzE,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;IAC1D,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,uDAAuD;QACvD,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC;IACD,uDAAuD;IACvD,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAElD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,MAO5C;IACC,MAAM,SAAS,GAAG,MAAM,yBAAyB,CAC/C,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,iBAAiB,CACzB,CAAC;IACF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACpD,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACnE,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACzD,aAAa,CAAC,YAAY,CAAC,MAAM,CAC/B,0BAA0B,EAC1B,MAAM,CAAC,WAAW,CACnB,CAAC;IACF,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,WAAmB,EACnB,SAAoB;IAEpB,OAAO,IAAI,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE;QACjE,WAAW,EAAE,WAAW;KACzB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,KAAa,EACb,YAA0B,EAC1B,YAA0B,EAC1B,WAAmB,EACnB,SAAoB;IAEpB,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,CAAC;IAC1D,IAAI,CAAC,YAAY;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAEvE,MAAM,MAAM,GACV,MAAM,YAAY,CAAC,yBAAyB,CAAwB,IAAI,EAAE;QACxE,YAAY;KACb,CAAC,CAAC;IAEL,2BAA2B;IAC3B,IAAI,CAAC;QACH,MAAM,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAC3E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,kCAAmC,KAAe,CAAC,OAAO,EAAE,CAC7D,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAoB,EACpB,MAA6B;IAE7B,mGAAmG;IACnG,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACxD,IAAI,iBAAiB,IAAI,iBAAiB,EAAE,SAAS,EAAE,CAAC;QACtD,MAAM,OAAO,CAAC,GAAG,CACf,WAAW,CAAC,uBAAuB,EACnC,iBAAiB,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,CAClD,CAAC;IACJ,CAAC;SAAM,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;QACpD,MAAM,OAAO,CAAC,GAAG,CACf,WAAW,CAAC,uBAAuB,EACnC,CAAC,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CACrC,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAoB,EACpB,MAA6B;IAE7B,4GAA4G;IAC5G,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACzB,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,uBAAuB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtE,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAoB;IAC/D,MAAM,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAoB;IAClD,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAoB;IAEpB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IAClE,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,GAAG,CAC5C,WAAW,CAAC,uBAAuB,CACpC,CAAC;IAEF,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAE1C,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,YAAY,EAAE,WAAW;QACzB,aAAa,EAAE,YAAY,IAAI,SAAS;QACxC,uBAAuB,EACrB,oBAAoB,KAAK,IAAI;YAC3B,CAAC,CAAC,QAAQ,CAAC,oBAAoB,EAAE,EAAE,CAAC;YACpC,CAAC,CAAC,SAAS,EAAE,2BAA2B;KAC7C,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,OAAoB;IAEpB,OAAO,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAA6B,EAC7B,SAAoB,EACpB,YAA0B,EAC1B,MAAc;IAEd,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAE9D,wBAAwB;IACxB,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,SAAS,CAC1C,MAAM,CAAC,QAAQ,EACf,IAAI,EACJ;QACE,MAAM,EAAE,mBAAmB,CAAC,MAAM,CAAC;QACnC,QAAQ,EAAE,YAAY,CAAC,QAAQ;KAChC,CACF,CAAC;IAEF,4BAA4B;IAC5B,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,SAAS,CAC9C,MAAM,CAAC,YAAY,EACnB,IAAI,EACJ;QACE,MAAM,EAAE,mBAAmB,CAAC,MAAM,CAAC;KACpC,CACF,CAAC;IAEF,OAAO,gBAAgB,CAAC;QACtB,QAAQ,EAAE,eAAe,CAAC,OAAO;QACjC,YAAY,EAAE,mBAAmB,CAAC,OAAO;QACzC,aAAa,EAAE,MAAM,CAAC,aAAa;KACpC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Utility functions shared by auth server and client integrations\n// Typically these functions should be used inside AuthenticationInitiator and AuthenticationResolver implementations\nimport type {\n AuthStorage,\n Endpoints,\n JWTPayload,\n OIDCTokenResponseBody,\n ParsedTokens,\n} from \"@/types.js\";\nimport { AUTH_SERVER_SESSION, OAuthTokens } from \"./types.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport { getIssuerVariations, getOauthEndpoints } from \"@/lib/oauth.js\";\nimport * as jose from \"jose\";\nimport { withoutUndefined } from \"@/utils.js\";\nimport type { PKCEConsumer, PKCEProducer } from \"@/services/types.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\nimport { parseJWT } from \"oslo/jwt\";\n\n/**\n * Given a PKCE code verifier, derive the code challenge using SHA\n */\nexport async function deriveCodeChallenge(\n codeVerifier: string,\n method: \"Plain\" | \"S256\" = \"S256\",\n): Promise<string> {\n if (method === \"Plain\") {\n console.warn(\"Using insecure plain code challenge method\");\n return codeVerifier;\n }\n\n const encoder = new TextEncoder();\n const data = encoder.encode(codeVerifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return btoa(String.fromCharCode(...new Uint8Array(digest)))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nexport async function getEndpointsWithOverrides(\n oauthServer: string,\n endpointOverrides: Partial<Endpoints> = {},\n): Promise<Endpoints> {\n const endpoints = await getOauthEndpoints(oauthServer);\n return {\n ...endpoints,\n ...endpointOverrides,\n };\n}\n\nexport async function generateOauthLoginUrl(config: {\n clientId: string;\n scopes: string[];\n state: string;\n redirectUrl: string;\n oauthServer: string;\n nonce?: string;\n endpointOverrides?: Partial<Endpoints>;\n // used to get the PKCE challenge\n pkceConsumer: PKCEConsumer;\n}): Promise<URL> {\n const endpoints = await getEndpointsWithOverrides(\n config.oauthServer,\n config.endpointOverrides,\n );\n const oauth2Client = buildOauth2Client(\n config.clientId,\n config.redirectUrl,\n endpoints,\n );\n const challenge = await config.pkceConsumer.getCodeChallenge();\n const oAuthUrl = await oauth2Client.createAuthorizationURL({\n state: config.state,\n scopes: config.scopes,\n });\n // The OAuth2 client supports PKCE, but does not allow passing in a code challenge from some other source\n // It only allows passing in a code verifier which it then hashes itself.\n oAuthUrl.searchParams.append(\"code_challenge\", challenge);\n oAuthUrl.searchParams.append(\"code_challenge_method\", \"S256\");\n if (config.nonce) {\n // nonce isn't supported by oslo, so we add it manually\n oAuthUrl.searchParams.append(\"nonce\", config.nonce);\n }\n // Required by the auth server for offline_access scope\n oAuthUrl.searchParams.append(\"prompt\", \"consent\");\n\n return oAuthUrl;\n}\n\nexport async function generateOauthLogoutUrl(config: {\n clientId: string;\n redirectUrl: string;\n idToken: string;\n state: string;\n oauthServer: string;\n endpointOverrides?: Partial<Endpoints>;\n}): Promise<URL> {\n const endpoints = await getEndpointsWithOverrides(\n config.oauthServer,\n config.endpointOverrides,\n );\n const endSessionUrl = new URL(endpoints.endsession);\n endSessionUrl.searchParams.append(\"client_id\", config.clientId);\n endSessionUrl.searchParams.append(\"id_token_hint\", config.idToken);\n endSessionUrl.searchParams.append(\"state\", config.state);\n endSessionUrl.searchParams.append(\n \"post_logout_redirect_uri\",\n config.redirectUrl,\n );\n return endSessionUrl;\n}\n\nexport function buildOauth2Client(\n clientId: string,\n redirectUri: string,\n endpoints: Endpoints,\n): OAuth2Client {\n return new OAuth2Client(clientId, endpoints.auth, endpoints.token, {\n redirectURI: redirectUri,\n });\n}\n\nexport async function exchangeTokens(\n code: string,\n state: string,\n pkceProducer: PKCEProducer,\n oauth2Client: OAuth2Client,\n oauthServer: string,\n endpoints: Endpoints,\n) {\n const codeVerifier = await pkceProducer.getCodeVerifier();\n if (!codeVerifier) throw new Error(\"Code verifier not found in state\");\n\n const tokens =\n await oauth2Client.validateAuthorizationCode<OIDCTokenResponseBody>(code, {\n codeVerifier,\n });\n\n // Validate relevant tokens\n try {\n await validateOauth2Tokens(tokens, endpoints, oauth2Client, oauthServer);\n } catch (error) {\n console.error(\"tokenExchange error\", { error, tokens });\n throw new Error(\n `OIDC tokens validation failed: ${(error as Error).message}`,\n );\n }\n return tokens;\n}\n\nexport async function setAccessTokenExpiresAt(\n storage: AuthStorage,\n tokens: OIDCTokenResponseBody,\n) {\n // try to extract absolut expiry time from access token but fallback to calculation if not possible\n const parsedAccessToken = parseJWT(tokens.access_token);\n if (parsedAccessToken && parsedAccessToken?.expiresAt) {\n await storage.set(\n OAuthTokens.ACCESS_TOKEN_EXPIRES_AT,\n parsedAccessToken.expiresAt?.getTime().toString(),\n );\n } else if (tokens.expires_in) {\n const now = Math.floor(new Date().getTime() / 1000);\n await storage.set(\n OAuthTokens.ACCESS_TOKEN_EXPIRES_AT,\n (now + tokens.expires_in).toString(),\n );\n } else {\n throw new Error(\"Cannot determine access token expiry!\");\n }\n}\n\nexport async function storeTokens(\n storage: AuthStorage,\n tokens: OIDCTokenResponseBody,\n) {\n // store tokens in storage ( TODO we should probably store them against the state to allow multiple logins )\n await storage.set(OAuthTokens.ID_TOKEN, tokens.id_token);\n await storage.set(OAuthTokens.ACCESS_TOKEN, tokens.access_token);\n if (tokens.refresh_token) {\n await storage.set(OAuthTokens.REFRESH_TOKEN, tokens.refresh_token);\n }\n await setAccessTokenExpiresAt(storage, tokens);\n}\n\nexport async function clearTokens(storage: AuthStorage) {\n const clearOAuthPromises = Object.values(OAuthTokens).map(async (key) => {\n await storage.set(key, \"\");\n });\n await Promise.all([...clearOAuthPromises]);\n}\n\nexport async function clearAuthServerSession(storage: AuthStorage) {\n await storage.set(AUTH_SERVER_SESSION, \"\");\n}\n\nexport async function clearUser(storage: AuthStorage) {\n const userSession = new GenericUserSession(storage);\n await userSession.set(null);\n}\n\nexport async function retrieveTokens(\n storage: AuthStorage,\n): Promise<OIDCTokenResponseBody | null> {\n const idToken = await storage.get(OAuthTokens.ID_TOKEN);\n const accessToken = await storage.get(OAuthTokens.ACCESS_TOKEN);\n const refreshToken = await storage.get(OAuthTokens.REFRESH_TOKEN);\n const accessTokenExpiresAt = await storage.get(\n OAuthTokens.ACCESS_TOKEN_EXPIRES_AT,\n );\n\n if (!idToken || !accessToken) return null;\n\n return {\n id_token: idToken,\n access_token: accessToken,\n refresh_token: refreshToken ?? undefined,\n access_token_expires_at:\n accessTokenExpiresAt !== null\n ? parseInt(accessTokenExpiresAt, 10)\n : undefined, // Convert string to number\n };\n}\n\nexport async function retrieveAccessTokenExpiresAt(\n storage: AuthStorage,\n): Promise<number> {\n return Number(await storage.get(OAuthTokens.ACCESS_TOKEN_EXPIRES_AT));\n}\n\nexport async function validateOauth2Tokens(\n tokens: OIDCTokenResponseBody,\n endpoints: Endpoints,\n oauth2Client: OAuth2Client,\n issuer: string,\n): Promise<ParsedTokens> {\n const JWKS = jose.createRemoteJWKSet(new URL(endpoints.jwks));\n\n // validate the ID token\n const idTokenResponse = await jose.jwtVerify<JWTPayload>(\n tokens.id_token,\n JWKS,\n {\n issuer: getIssuerVariations(issuer),\n audience: oauth2Client.clientId,\n },\n );\n\n // validate the access token\n const accessTokenResponse = await jose.jwtVerify<JWTPayload>(\n tokens.access_token,\n JWKS,\n {\n issuer: getIssuerVariations(issuer),\n },\n );\n\n return withoutUndefined({\n id_token: idTokenResponse.payload,\n access_token: accessTokenResponse.payload,\n refresh_token: tokens.refresh_token,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../../src/shared/lib/util.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEjE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,YAAoB,EACpB,SAA2B,MAAM;IAEjC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QAC3D,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;SACxD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,WAAmB,EACnB,oBAAwC,EAAE;IAE1C,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACvD,OAAO;QACL,GAAG,SAAS;QACZ,GAAG,iBAAiB;KACrB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAU3C;IACC,MAAM,SAAS,GAAG,MAAM,yBAAyB,CAC/C,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,iBAAiB,CACzB,CAAC;IACF,MAAM,YAAY,GAAG,iBAAiB,CACpC,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,WAAW,EAClB,SAAS,CACV,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC;IAC/D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,sBAAsB,CAAC;QACzD,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CAAC;IACH,yGAAyG;IACzG,yEAAyE;IACzE,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;IAC1D,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,uDAAuD;QACvD,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC;IACD,uDAAuD;IACvD,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAElD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,MAO5C;IACC,MAAM,SAAS,GAAG,MAAM,yBAAyB,CAC/C,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,iBAAiB,CACzB,CAAC;IACF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACpD,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACnE,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACzD,aAAa,CAAC,YAAY,CAAC,MAAM,CAC/B,0BAA0B,EAC1B,MAAM,CAAC,WAAW,CACnB,CAAC;IACF,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,WAAmB,EACnB,SAAoB;IAEpB,OAAO,IAAI,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE;QACjE,WAAW,EAAE,WAAW;KACzB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,KAAa,EACb,YAA0B,EAC1B,YAA0B,EAC1B,WAAmB,EACnB,SAAoB;IAEpB,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,CAAC;IAC1D,IAAI,CAAC,YAAY;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAEvE,MAAM,MAAM,GACV,MAAM,YAAY,CAAC,yBAAyB,CAAwB,IAAI,EAAE;QACxE,YAAY;KACb,CAAC,CAAC;IAEL,2BAA2B;IAC3B,IAAI,CAAC;QACH,MAAM,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAC3E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,kCAAmC,KAAe,CAAC,OAAO,EAAE,CAC7D,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAoB,EACpB,MAA6B;IAE7B,4GAA4G;IAC5G,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACzB,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtE,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAoB;IAClD,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAoB;IAEpB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IAClE,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAE3D,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAE1C,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,YAAY,EAAE,WAAW;QACzB,aAAa,EAAE,YAAY,IAAI,SAAS;QACxC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,2BAA2B;QACxF,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,2BAA2B;KACxF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,OAAoB;IAChE,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAA6B,EAC7B,SAAoB,EACpB,YAA0B,EAC1B,MAAc;IAEd,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAE9D,wBAAwB;IACxB,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,SAAS,CAC1C,MAAM,CAAC,QAAQ,EACf,IAAI,EACJ;QACE,MAAM,EAAE,mBAAmB,CAAC,MAAM,CAAC;QACnC,QAAQ,EAAE,YAAY,CAAC,QAAQ;KAChC,CACF,CAAC;IAEF,4BAA4B;IAC5B,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,SAAS,CAC9C,MAAM,CAAC,YAAY,EACnB,IAAI,EACJ;QACE,MAAM,EAAE,mBAAmB,CAAC,MAAM,CAAC;KACpC,CACF,CAAC;IAEF,OAAO,gBAAgB,CAAC;QACtB,QAAQ,EAAE,eAAe,CAAC,OAAO;QACjC,YAAY,EAAE,mBAAmB,CAAC,OAAO;QACzC,aAAa,EAAE,MAAM,CAAC,aAAa;KACpC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Utility functions shared by auth server and client integrations\n// Typically these functions should be used inside AuthenticationInitiator and AuthenticationResolver implementations\nimport type {\n AuthStorage,\n Endpoints,\n JWTPayload,\n OIDCTokenResponseBody,\n ParsedTokens,\n} from \"@/types.js\";\nimport { OAuthTokens } from \"./types.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport { getIssuerVariations, getOauthEndpoints } from \"@/lib/oauth.js\";\nimport * as jose from \"jose\";\nimport { withoutUndefined } from \"@/utils.js\";\nimport type { PKCEConsumer, PKCEProducer } from \"@/services/types.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\n\n/**\n * Given a PKCE code verifier, derive the code challenge using SHA\n */\nexport async function deriveCodeChallenge(\n codeVerifier: string,\n method: \"Plain\" | \"S256\" = \"S256\",\n): Promise<string> {\n if (method === \"Plain\") {\n console.warn(\"Using insecure plain code challenge method\");\n return codeVerifier;\n }\n\n const encoder = new TextEncoder();\n const data = encoder.encode(codeVerifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return btoa(String.fromCharCode(...new Uint8Array(digest)))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nexport async function getEndpointsWithOverrides(\n oauthServer: string,\n endpointOverrides: Partial<Endpoints> = {},\n): Promise<Endpoints> {\n const endpoints = await getOauthEndpoints(oauthServer);\n return {\n ...endpoints,\n ...endpointOverrides,\n };\n}\n\nexport async function generateOauthLoginUrl(config: {\n clientId: string;\n scopes: string[];\n state: string;\n redirectUrl: string;\n oauthServer: string;\n nonce?: string;\n endpointOverrides?: Partial<Endpoints>;\n // used to get the PKCE challenge\n pkceConsumer: PKCEConsumer;\n}): Promise<URL> {\n const endpoints = await getEndpointsWithOverrides(\n config.oauthServer,\n config.endpointOverrides,\n );\n const oauth2Client = buildOauth2Client(\n config.clientId,\n config.redirectUrl,\n endpoints,\n );\n const challenge = await config.pkceConsumer.getCodeChallenge();\n const oAuthUrl = await oauth2Client.createAuthorizationURL({\n state: config.state,\n scopes: config.scopes,\n });\n // The OAuth2 client supports PKCE, but does not allow passing in a code challenge from some other source\n // It only allows passing in a code verifier which it then hashes itself.\n oAuthUrl.searchParams.append(\"code_challenge\", challenge);\n oAuthUrl.searchParams.append(\"code_challenge_method\", \"S256\");\n if (config.nonce) {\n // nonce isn't supported by oslo, so we add it manually\n oAuthUrl.searchParams.append(\"nonce\", config.nonce);\n }\n // Required by the auth server for offline_access scope\n oAuthUrl.searchParams.append(\"prompt\", \"consent\");\n\n return oAuthUrl;\n}\n\nexport async function generateOauthLogoutUrl(config: {\n clientId: string;\n redirectUrl: string;\n idToken: string;\n state: string;\n oauthServer: string;\n endpointOverrides?: Partial<Endpoints>;\n}): Promise<URL> {\n const endpoints = await getEndpointsWithOverrides(\n config.oauthServer,\n config.endpointOverrides,\n );\n const endSessionUrl = new URL(endpoints.endsession);\n endSessionUrl.searchParams.append(\"client_id\", config.clientId);\n endSessionUrl.searchParams.append(\"id_token_hint\", config.idToken);\n endSessionUrl.searchParams.append(\"state\", config.state);\n endSessionUrl.searchParams.append(\n \"post_logout_redirect_uri\",\n config.redirectUrl,\n );\n return endSessionUrl;\n}\n\nexport function buildOauth2Client(\n clientId: string,\n redirectUri: string,\n endpoints: Endpoints,\n): OAuth2Client {\n return new OAuth2Client(clientId, endpoints.auth, endpoints.token, {\n redirectURI: redirectUri,\n });\n}\n\nexport async function exchangeTokens(\n code: string,\n state: string,\n pkceProducer: PKCEProducer,\n oauth2Client: OAuth2Client,\n oauthServer: string,\n endpoints: Endpoints,\n) {\n const codeVerifier = await pkceProducer.getCodeVerifier();\n if (!codeVerifier) throw new Error(\"Code verifier not found in state\");\n\n const tokens =\n await oauth2Client.validateAuthorizationCode<OIDCTokenResponseBody>(code, {\n codeVerifier,\n });\n\n // Validate relevant tokens\n try {\n await validateOauth2Tokens(tokens, endpoints, oauth2Client, oauthServer);\n } catch (error) {\n console.error(\"tokenExchange error\", { error, tokens });\n throw new Error(\n `OIDC tokens validation failed: ${(error as Error).message}`,\n );\n }\n return tokens;\n}\n\nexport async function storeTokens(\n storage: AuthStorage,\n tokens: OIDCTokenResponseBody,\n) {\n // store tokens in storage ( TODO we should probably store them against the state to allow multiple logins )\n await storage.set(OAuthTokens.ID_TOKEN, tokens.id_token);\n await storage.set(OAuthTokens.ACCESS_TOKEN, tokens.access_token);\n if (tokens.refresh_token) {\n await storage.set(OAuthTokens.REFRESH_TOKEN, tokens.refresh_token);\n }\n if (tokens.expires_in) {\n await storage.set(OAuthTokens.EXPIRES_IN, tokens.expires_in.toString());\n await storage.set(OAuthTokens.TIMESTAMP, new Date().getTime().toString());\n }\n}\n\nexport async function clearTokens(storage: AuthStorage) {\n const clearOAuthPromises = Object.values(OAuthTokens).map(async (key) => {\n await storage.set(key, \"\");\n });\n await Promise.all([...clearOAuthPromises]);\n}\n\nexport async function clearUser(storage: AuthStorage) {\n const userSession = new GenericUserSession(storage);\n await userSession.set(null);\n}\n\nexport async function retrieveTokens(\n storage: AuthStorage,\n): Promise<OIDCTokenResponseBody | null> {\n const idToken = await storage.get(OAuthTokens.ID_TOKEN);\n const accessToken = await storage.get(OAuthTokens.ACCESS_TOKEN);\n const refreshToken = await storage.get(OAuthTokens.REFRESH_TOKEN);\n const expiresIn = await storage.get(OAuthTokens.EXPIRES_IN);\n const timestamp = await storage.get(OAuthTokens.TIMESTAMP);\n\n if (!idToken || !accessToken) return null;\n\n return {\n id_token: idToken,\n access_token: accessToken,\n refresh_token: refreshToken ?? undefined,\n expires_in: expiresIn ? parseInt(expiresIn, 10) : undefined, // Convert string to number\n timestamp: timestamp ? parseInt(timestamp, 10) : undefined, // Convert string to number\n };\n}\n\nexport async function retrieveTokenExpiration(storage: AuthStorage) {\n return await storage.get(OAuthTokens.EXPIRES_IN);\n}\n\nexport async function validateOauth2Tokens(\n tokens: OIDCTokenResponseBody,\n endpoints: Endpoints,\n oauth2Client: OAuth2Client,\n issuer: string,\n): Promise<ParsedTokens> {\n const JWKS = jose.createRemoteJWKSet(new URL(endpoints.jwks));\n\n // validate the ID token\n const idTokenResponse = await jose.jwtVerify<JWTPayload>(\n tokens.id_token,\n JWKS,\n {\n issuer: getIssuerVariations(issuer),\n audience: oauth2Client.clientId,\n },\n );\n\n // validate the access token\n const accessTokenResponse = await jose.jwtVerify<JWTPayload>(\n tokens.access_token,\n JWKS,\n {\n issuer: getIssuerVariations(issuer),\n },\n );\n\n return withoutUndefined({\n id_token: idTokenResponse.payload,\n access_token: accessTokenResponse.payload,\n refresh_token: tokens.refresh_token,\n });\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
import type { Config, DisplayMode, SessionData } from "../../types.js";
|
|
3
|
+
import type { PKCEConsumer } from "../../services/types.js";
|
|
4
|
+
export type IframeMode = "embedded" | "modal";
|
|
5
|
+
export type AuthProviderProps = {
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
clientId: string;
|
|
8
|
+
nonce?: string;
|
|
9
|
+
onSignIn?: (error?: Error) => void;
|
|
10
|
+
onSignOut?: () => Promise<void>;
|
|
11
|
+
iframeMode?: IframeMode;
|
|
12
|
+
config?: Config;
|
|
13
|
+
redirectUrl?: string;
|
|
14
|
+
displayMode?: DisplayMode;
|
|
15
|
+
};
|
|
16
|
+
export type InternalAuthProviderProps = AuthProviderProps & {
|
|
17
|
+
sessionData?: SessionData;
|
|
18
|
+
pkceConsumer?: PKCEConsumer;
|
|
19
|
+
};
|
|
20
|
+
declare const AuthProvider: ({ children, onSignIn, onSignOut, pkceConsumer, iframeMode, displayMode, }: InternalAuthProviderProps) => React.JSX.Element;
|
|
21
|
+
export { AuthProvider };
|
|
22
|
+
//# sourceMappingURL=AuthProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/AuthProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAgC,MAAM,OAAO,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAkBxD,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;AAC9C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,iBAAiB,GAAG;IAC1D,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF,QAAA,MAAM,YAAY,8EAOf,yBAAyB,sBAsE3B,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { AuthContext } from "../../shared/providers/AuthContext.js";
|
|
4
|
+
import { useSignIn } from "../../shared/hooks/useSignIn.js";
|
|
5
|
+
import { useIframe } from "../../shared/hooks/useIframe.js";
|
|
6
|
+
import { useCivicAuthConfig } from "../../shared/hooks/useCivicAuthConfig.js";
|
|
7
|
+
import { useSession } from "../../shared/hooks/useSession.js";
|
|
8
|
+
import { IFrameAndLoading } from "../../shared/components/IFrameAndLoading.js";
|
|
9
|
+
// Global this object setup
|
|
10
|
+
let globalThisObject;
|
|
11
|
+
if (typeof window !== "undefined") {
|
|
12
|
+
globalThisObject = window;
|
|
13
|
+
}
|
|
14
|
+
else if (typeof global !== "undefined") {
|
|
15
|
+
globalThisObject = global;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
globalThisObject = Function("return this")();
|
|
19
|
+
}
|
|
20
|
+
globalThisObject.globalThis = globalThisObject;
|
|
21
|
+
const AuthProvider = ({ children, onSignIn, onSignOut, pkceConsumer, iframeMode = "modal", displayMode = "iframe", }) => {
|
|
22
|
+
const authConfig = useCivicAuthConfig();
|
|
23
|
+
const { redirectUrl } = authConfig || {};
|
|
24
|
+
const { iframeRef } = useIframe();
|
|
25
|
+
const { signIn, signOut } = useSignIn({
|
|
26
|
+
preSignOut: onSignOut,
|
|
27
|
+
pkceConsumer,
|
|
28
|
+
displayMode: displayMode,
|
|
29
|
+
});
|
|
30
|
+
const [localSessionData, setLocalSessionData] = useState();
|
|
31
|
+
const { data: session, error: tokenExchangeError, isLoading: tokenExchangeInProgress, } = useSession();
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (session) {
|
|
34
|
+
setLocalSessionData(session);
|
|
35
|
+
if (session.authenticated) {
|
|
36
|
+
onSignIn?.();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}, [onSignIn, session]);
|
|
40
|
+
const isAuthenticated = useMemo(() => {
|
|
41
|
+
return !!localSessionData?.idToken;
|
|
42
|
+
}, [localSessionData]);
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (iframeMode === "embedded" &&
|
|
45
|
+
redirectUrl &&
|
|
46
|
+
!isAuthenticated &&
|
|
47
|
+
iframeRef?.current) {
|
|
48
|
+
signIn();
|
|
49
|
+
}
|
|
50
|
+
}, [iframeMode, redirectUrl, isAuthenticated, iframeRef, signIn]);
|
|
51
|
+
const isLoading = tokenExchangeInProgress || !authConfig;
|
|
52
|
+
const value = useMemo(() => ({
|
|
53
|
+
isLoading,
|
|
54
|
+
error: tokenExchangeError,
|
|
55
|
+
signOut,
|
|
56
|
+
isAuthenticated,
|
|
57
|
+
signIn,
|
|
58
|
+
displayMode,
|
|
59
|
+
}), [
|
|
60
|
+
isLoading,
|
|
61
|
+
tokenExchangeError,
|
|
62
|
+
isAuthenticated,
|
|
63
|
+
signIn,
|
|
64
|
+
signOut,
|
|
65
|
+
displayMode,
|
|
66
|
+
]);
|
|
67
|
+
return (React.createElement(AuthContext.Provider, { value: value },
|
|
68
|
+
React.createElement(IFrameAndLoading, { error: tokenExchangeError, isLoading: isLoading }),
|
|
69
|
+
children));
|
|
70
|
+
};
|
|
71
|
+
export { AuthProvider };
|
|
72
|
+
//# sourceMappingURL=AuthProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthProvider.js","sourceRoot":"","sources":["../../../../src/shared/providers/AuthProvider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport React, { type ReactNode, useEffect, useMemo, useState } from \"react\";\nimport type { Config, DisplayMode, SessionData } from \"@/types.js\";\nimport { AuthContext } from \"@/shared/providers/AuthContext.js\";\nimport type { PKCEConsumer } from \"@/services/types.js\";\nimport { useSignIn } from \"@/shared/hooks/useSignIn.js\";\nimport { useIframe } from \"@/shared/hooks/useIframe.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/useCivicAuthConfig.js\";\nimport { useSession } from \"@/shared/hooks/useSession.js\";\nimport { IFrameAndLoading } from \"@/shared/components/IFrameAndLoading.js\";\n\n// Global this object setup\nlet globalThisObject;\nif (typeof window !== \"undefined\") {\n globalThisObject = window;\n} else if (typeof global !== \"undefined\") {\n globalThisObject = global;\n} else {\n globalThisObject = Function(\"return this\")();\n}\nglobalThisObject.globalThis = globalThisObject;\n\nexport type IframeMode = \"embedded\" | \"modal\";\nexport type AuthProviderProps = {\n children: ReactNode;\n clientId: string;\n nonce?: string;\n onSignIn?: (error?: Error) => void;\n onSignOut?: () => Promise<void>;\n iframeMode?: IframeMode;\n config?: Config;\n redirectUrl?: string;\n displayMode?: DisplayMode;\n};\n\nexport type InternalAuthProviderProps = AuthProviderProps & {\n sessionData?: SessionData;\n pkceConsumer?: PKCEConsumer;\n};\n\nconst AuthProvider = ({\n children,\n onSignIn,\n onSignOut,\n pkceConsumer,\n iframeMode = \"modal\",\n displayMode = \"iframe\",\n}: InternalAuthProviderProps) => {\n const authConfig = useCivicAuthConfig();\n const { redirectUrl } = authConfig || {};\n const { iframeRef } = useIframe();\n\n const { signIn, signOut } = useSignIn({\n preSignOut: onSignOut,\n pkceConsumer,\n displayMode: displayMode,\n });\n\n const [localSessionData, setLocalSessionData] =\n useState<SessionData | null>();\n\n const {\n data: session,\n error: tokenExchangeError,\n isLoading: tokenExchangeInProgress,\n } = useSession();\n\n useEffect(() => {\n if (session) {\n setLocalSessionData(session);\n if (session.authenticated) {\n onSignIn?.();\n }\n }\n }, [onSignIn, session]);\n\n const isAuthenticated = useMemo(() => {\n return !!localSessionData?.idToken;\n }, [localSessionData]);\n\n useEffect(() => {\n if (\n iframeMode === \"embedded\" &&\n redirectUrl &&\n !isAuthenticated &&\n iframeRef?.current\n ) {\n signIn();\n }\n }, [iframeMode, redirectUrl, isAuthenticated, iframeRef, signIn]);\n\n const isLoading = tokenExchangeInProgress || !authConfig;\n const value = useMemo(\n () => ({\n isLoading,\n error: tokenExchangeError as Error | null,\n signOut,\n isAuthenticated,\n signIn,\n displayMode,\n }),\n [\n isLoading,\n tokenExchangeError,\n isAuthenticated,\n signIn,\n signOut,\n displayMode,\n ],\n );\n\n return (\n <AuthContext.Provider value={value}>\n <IFrameAndLoading error={tokenExchangeError} isLoading={isLoading} />\n {children}\n </AuthContext.Provider>\n );\n};\n\nexport { AuthProvider };\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type AuthProviderProps } from "../../shared/providers/AuthProvider.js";
|
|
3
|
+
type CivicAuthProviderProps = Omit<AuthProviderProps, "pkceConsumer">;
|
|
4
|
+
declare const CivicAuthProvider: ({ children, ...props }: CivicAuthProviderProps) => React.JSX.Element;
|
|
5
|
+
export { CivicAuthProvider, type CivicAuthProviderProps };
|
|
6
|
+
//# sourceMappingURL=CivicAuthProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CivicAuthProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/CivicAuthProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,oCAAoC,CAAC;AAY5C,KAAK,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;AAmCtE,QAAA,MAAM,iBAAiB,2BAA4B,sBAAsB,sBAexE,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { AuthProvider, } from "../../shared/providers/AuthProvider.js";
|
|
4
|
+
import { BrowserPublicClientPKCEProducer } from "../../services/PKCE.js";
|
|
5
|
+
import { UserProvider } from "../../shared/providers/UserProvider.js";
|
|
6
|
+
import { LocalStorageAdapter } from "../../browser/storage.js";
|
|
7
|
+
import { CivicAuthConfigProvider } from "../../shared/providers/CivicAuthConfigContext.js";
|
|
8
|
+
import { IframeProvider } from "../../shared/providers/IframeProvider.js";
|
|
9
|
+
import { ClientTokenExchangeSessionProvider } from "../../shared/providers/ClientTokenExchangeSessionProvider.js";
|
|
10
|
+
import { SessionProvider } from "../../shared/providers/SessionProvider.js";
|
|
11
|
+
import { useClientTokenExchangeSession } from "../../shared/hooks/useClientTokenExchangeSession.js";
|
|
12
|
+
import { TokenProvider } from "../../shared/providers/TokenProvider.js";
|
|
13
|
+
import { useAuth } from "../../shared/hooks/useAuth.js";
|
|
14
|
+
const WrapperUserProvider = ({ children }) => {
|
|
15
|
+
const { signIn, signOut, displayMode } = useAuth();
|
|
16
|
+
return (React.createElement(UserProvider, { storage: new LocalStorageAdapter(), signIn: signIn, signOut: signOut, displayMode: displayMode }, children));
|
|
17
|
+
};
|
|
18
|
+
const WrapperSessionAuthProvider = ({ children, ...props }) => {
|
|
19
|
+
const sessionData = useClientTokenExchangeSession();
|
|
20
|
+
return (React.createElement(SessionProvider, { ...sessionData },
|
|
21
|
+
React.createElement(IframeProvider, { iframeMode: props.iframeMode },
|
|
22
|
+
React.createElement(AuthProvider, { ...props, pkceConsumer: new BrowserPublicClientPKCEProducer() },
|
|
23
|
+
React.createElement(TokenProvider, null,
|
|
24
|
+
React.createElement(WrapperUserProvider, null, children))))));
|
|
25
|
+
};
|
|
26
|
+
const CivicAuthProvider = ({ children, ...props }) => {
|
|
27
|
+
return (React.createElement(CivicAuthConfigProvider, { oauthServer: props?.config?.oauthServer, clientId: props?.clientId, redirectUrl: props?.redirectUrl, nonce: props?.nonce },
|
|
28
|
+
React.createElement(ClientTokenExchangeSessionProvider, null,
|
|
29
|
+
React.createElement(WrapperSessionAuthProvider, { ...props }, children))));
|
|
30
|
+
};
|
|
31
|
+
export { CivicAuthProvider };
|
|
32
|
+
//# sourceMappingURL=CivicAuthProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CivicAuthProvider.js","sourceRoot":"","sources":["../../../../src/shared/providers/CivicAuthProvider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EACL,YAAY,GAEb,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,kCAAkC,EAAE,MAAM,0DAA0D,CAAC;AAC9G,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,iDAAiD,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAIpD,MAAM,mBAAmB,GAAG,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE;IAC1E,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,CAAC;IACnD,OAAO,CACL,oBAAC,YAAY,IACX,OAAO,EAAE,IAAI,mBAAmB,EAAE,EAClC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,IAEvB,QAAQ,CACI,CAChB,CAAC;AACJ,CAAC,CAAC;AACF,MAAM,0BAA0B,GAAG,CAAC,EAClC,QAAQ,EACR,GAAG,KAAK,EACe,EAAE,EAAE;IAC3B,MAAM,WAAW,GAAG,6BAA6B,EAAE,CAAC;IACpD,OAAO,CACL,oBAAC,eAAe,OAAK,WAAW;QAC9B,oBAAC,cAAc,IAAC,UAAU,EAAE,KAAK,CAAC,UAAU;YAC1C,oBAAC,YAAY,OACP,KAAK,EACT,YAAY,EAAE,IAAI,+BAA+B,EAAE;gBAEnD,oBAAC,aAAa;oBACZ,oBAAC,mBAAmB,QAAE,QAAQ,CAAuB,CACvC,CACH,CACA,CACD,CACnB,CAAC;AACJ,CAAC,CAAC;AACF,MAAM,iBAAiB,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAA0B,EAAE,EAAE;IAC3E,OAAO,CACL,oBAAC,uBAAuB,IACtB,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EACvC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EACzB,WAAW,EAAE,KAAK,EAAE,WAAW,EAC/B,KAAK,EAAE,KAAK,EAAE,KAAK;QAEnB,oBAAC,kCAAkC;YACjC,oBAAC,0BAA0B,OAAK,KAAK,IAClC,QAAQ,CACkB,CACM,CACb,CAC3B,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAA+B,CAAC","sourcesContent":["\"use client\";\nimport React from \"react\";\nimport {\n AuthProvider,\n type AuthProviderProps,\n} from \"@/shared/providers/AuthProvider.js\";\nimport { BrowserPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { UserProvider } from \"@/shared/providers/UserProvider.js\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\nimport { CivicAuthConfigProvider } from \"@/shared/providers/CivicAuthConfigContext.js\";\nimport { IframeProvider } from \"@/shared/providers/IframeProvider.js\";\nimport { ClientTokenExchangeSessionProvider } from \"@/shared/providers/ClientTokenExchangeSessionProvider.js\";\nimport { SessionProvider } from \"@/shared/providers/SessionProvider.js\";\nimport { useClientTokenExchangeSession } from \"@/shared/hooks/useClientTokenExchangeSession.js\";\nimport { TokenProvider } from \"@/shared/providers/TokenProvider.js\";\nimport { useAuth } from \"@/shared/hooks/useAuth.js\";\n\ntype CivicAuthProviderProps = Omit<AuthProviderProps, \"pkceConsumer\">;\n\nconst WrapperUserProvider = ({ children }: { children: React.ReactNode }) => {\n const { signIn, signOut, displayMode } = useAuth();\n return (\n <UserProvider\n storage={new LocalStorageAdapter()}\n signIn={signIn}\n signOut={signOut}\n displayMode={displayMode}\n >\n {children}\n </UserProvider>\n );\n};\nconst WrapperSessionAuthProvider = ({\n children,\n ...props\n}: CivicAuthProviderProps) => {\n const sessionData = useClientTokenExchangeSession();\n return (\n <SessionProvider {...sessionData}>\n <IframeProvider iframeMode={props.iframeMode}>\n <AuthProvider\n {...props}\n pkceConsumer={new BrowserPublicClientPKCEProducer()}\n >\n <TokenProvider>\n <WrapperUserProvider>{children}</WrapperUserProvider>\n </TokenProvider>\n </AuthProvider>\n </IframeProvider>\n </SessionProvider>\n );\n};\nconst CivicAuthProvider = ({ children, ...props }: CivicAuthProviderProps) => {\n return (\n <CivicAuthConfigProvider\n oauthServer={props?.config?.oauthServer}\n clientId={props?.clientId}\n redirectUrl={props?.redirectUrl}\n nonce={props?.nonce}\n >\n <ClientTokenExchangeSessionProvider>\n <WrapperSessionAuthProvider {...props}>\n {children}\n </WrapperSessionAuthProvider>\n </ClientTokenExchangeSessionProvider>\n </CivicAuthConfigProvider>\n );\n};\n\nexport { CivicAuthProvider, type CivicAuthProviderProps };\n"]}
|