@civic/auth 0.1.6-beta.4 → 0.1.6-beta.5
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/cjs/shared/lib/AuthenticationRefresherImpl.d.ts.map +1 -1
- package/dist/cjs/shared/lib/AuthenticationRefresherImpl.js +3 -0
- package/dist/cjs/shared/lib/AuthenticationRefresherImpl.js.map +1 -1
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.d.ts.map +1 -1
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.js +3 -7
- package/dist/cjs/shared/lib/GenericAuthenticationRefresher.js.map +1 -1
- package/dist/cjs/shared/lib/util.d.ts +1 -0
- package/dist/cjs/shared/lib/util.d.ts.map +1 -1
- package/dist/cjs/shared/lib/util.js +4 -0
- package/dist/cjs/shared/lib/util.js.map +1 -1
- 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/esm/shared/lib/AuthenticationRefresherImpl.d.ts.map +1 -1
- package/dist/esm/shared/lib/AuthenticationRefresherImpl.js +4 -1
- package/dist/esm/shared/lib/AuthenticationRefresherImpl.js.map +1 -1
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.d.ts.map +1 -1
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.js +4 -8
- package/dist/esm/shared/lib/GenericAuthenticationRefresher.js.map +1 -1
- package/dist/esm/shared/lib/util.d.ts +1 -0
- package/dist/esm/shared/lib/util.d.ts.map +1 -1
- package/dist/esm/shared/lib/util.js +3 -0
- package/dist/esm/shared/lib/util.js.map +1 -1
- 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/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationRefresherImpl.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthenticationRefresherImpl.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAMrD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAErF,qBAAa,2BAA4B,SAAQ,8BAA8B;IAM3E,OAAO,CAAC,iBAAiB,CAAC;IAL5B,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO;IAWD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WAmBd,KAAK,CAChB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,WAAW,EACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GACrC,OAAO,CAAC,2BAA2B,CAAC;IAWjC,kBAAkB,IAAI,OAAO,CAAC,qBAAqB,CAAC;CAoB3D"}
|
|
@@ -31,12 +31,15 @@ class AuthenticationRefresherImpl extends GenericAuthenticationRefresher_js_1.Ge
|
|
|
31
31
|
return refresher;
|
|
32
32
|
}
|
|
33
33
|
async refreshAccessToken() {
|
|
34
|
+
if (!this.storage)
|
|
35
|
+
throw new Error("No storage available");
|
|
34
36
|
const refreshToken = await this.getRefreshToken();
|
|
35
37
|
if (!this.oauth2client)
|
|
36
38
|
this.init();
|
|
37
39
|
const oauth2Client = this.oauth2client;
|
|
38
40
|
const tokenResponseBody = await oauth2Client.refreshAccessToken(refreshToken);
|
|
39
41
|
await (0, util_js_1.validateOauth2Tokens)(tokenResponseBody, this.endpoints, oauth2Client, this.oauthServer);
|
|
42
|
+
await (0, util_js_1.storeTokens)(this.storage, tokenResponseBody);
|
|
40
43
|
return tokenResponseBody;
|
|
41
44
|
}
|
|
42
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationRefresherImpl.js","sourceRoot":"","sources":["../../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":";;;AACA,
|
|
1
|
+
{"version":3,"file":"AuthenticationRefresherImpl.js","sourceRoot":"","sources":["../../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":";;;AACA,kDAI8B;AAE9B,wCAA2C;AAC3C,2FAAqF;AAErF,MAAa,2BAA4B,SAAQ,kEAA8B;IAMnE;IALF,SAAS,CAAwB;IACjC,YAAY,CAA2B;IAC/C,YACE,UAAsB,EACtB,OAAoB,EACZ,iBAAsC;QAE9C,KAAK,EAAE,CAAC;QAFA,sBAAiB,GAAjB,iBAAiB,CAAqB;QAG9C,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAClE,uBAAuB;QACvB,IAAI,CAAC,SAAS,GAAG,MAAM,IAAA,mCAAyB,EAC9C,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,iBAAiB,CACvB,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,IAAI,qBAAY,CAClC,IAAI,CAAC,UAAU,CAAC,QAAQ,EACxB,IAAI,CAAC,SAAS,CAAC,IAAI,EACnB,IAAI,CAAC,SAAS,CAAC,KAAK,EACpB;YACE,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW;SACzC,CACF,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,KAAK,CAChB,UAAsB,EACtB,OAAoB,EACpB,iBAAsC;QAEtC,MAAM,SAAS,GAAG,IAAI,2BAA2B,CAC/C,UAAU,EACV,OAAO,EACP,iBAAiB,CAClB,CAAC;QACF,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;QAEvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC3D,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAElD,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAa,CAAC;QACxC,MAAM,iBAAiB,GACrB,MAAM,YAAY,CAAC,kBAAkB,CACnC,YAAY,CACb,CAAC;QACJ,MAAM,IAAA,8BAAoB,EACxB,iBAAiB,EACjB,IAAI,CAAC,SAAU,EACf,YAAY,EACZ,IAAI,CAAC,WAAW,CACjB,CAAC;QAEF,MAAM,IAAA,qBAAW,EAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;QACnD,OAAO,iBAAiB,CAAC;IAC3B,CAAC;CACF;AApED,kEAoEC","sourcesContent":["import type { AuthConfig } from \"@/server/config.js\";\nimport {\n getEndpointsWithOverrides,\n storeTokens,\n validateOauth2Tokens,\n} from \"@/shared/lib/util.js\";\nimport type { AuthStorage, Endpoints, OIDCTokenResponseBody } from \"@/types.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport { GenericAuthenticationRefresher } from \"./GenericAuthenticationRefresher.js\";\n\nexport class AuthenticationRefresherImpl extends GenericAuthenticationRefresher {\n private endpoints: Endpoints | undefined;\n private oauth2client: OAuth2Client | undefined;\n private constructor(\n authConfig: AuthConfig,\n storage: AuthStorage,\n private endpointOverrides?: Partial<Endpoints>,\n ) {\n super();\n this.authConfig = authConfig;\n this.storage = storage;\n this.init();\n }\n\n async init(): Promise<this> {\n if (!this.authConfig) throw new Error(\"No auth config available\");\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.oauthServer,\n this.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.authConfig.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.authConfig.redirectUrl,\n },\n );\n\n return this;\n }\n\n static async build(\n authConfig: AuthConfig,\n storage: AuthStorage,\n endpointOverrides?: Partial<Endpoints>,\n ): Promise<AuthenticationRefresherImpl> {\n const refresher = new AuthenticationRefresherImpl(\n authConfig,\n storage,\n endpointOverrides,\n );\n await refresher.init();\n\n return refresher;\n }\n\n async refreshAccessToken(): Promise<OIDCTokenResponseBody> {\n if (!this.storage) throw new Error(\"No storage available\");\n const refreshToken = await this.getRefreshToken();\n\n if (!this.oauth2client) this.init();\n const oauth2Client = this.oauth2client!;\n const tokenResponseBody =\n await oauth2Client.refreshAccessToken<OIDCTokenResponseBody>(\n refreshToken,\n );\n await validateOauth2Tokens(\n tokenResponseBody,\n this.endpoints!,\n oauth2Client,\n this.oauthServer,\n );\n\n await storeTokens(this.storage, tokenResponseBody);\n return tokenResponseBody;\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;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;
|
|
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;IAWrB,gBAAgB;IAmBtB,gBAAgB;CAKjB"}
|
|
@@ -19,11 +19,7 @@ class GenericAuthenticationRefresher {
|
|
|
19
19
|
return tokens.refresh_token;
|
|
20
20
|
}
|
|
21
21
|
async refreshTokens() {
|
|
22
|
-
|
|
23
|
-
throw new Error("No storage available");
|
|
24
|
-
const refreshedTokens = await this.refreshAccessToken();
|
|
25
|
-
await (0, util_js_1.storeTokens)(this.storage, refreshedTokens);
|
|
26
|
-
return refreshedTokens;
|
|
22
|
+
return this.refreshAccessToken();
|
|
27
23
|
}
|
|
28
24
|
async handleRefresh() {
|
|
29
25
|
try {
|
|
@@ -41,8 +37,8 @@ class GenericAuthenticationRefresher {
|
|
|
41
37
|
// Clear any existing timeout
|
|
42
38
|
this.clearAutorefresh();
|
|
43
39
|
// get expires_in
|
|
44
|
-
const
|
|
45
|
-
const expires_in =
|
|
40
|
+
const expiration = await (0, util_js_1.retrieveTokenExpiration)(this.storage);
|
|
41
|
+
const expires_in = Number(expiration) || 60;
|
|
46
42
|
// Calculate time until expiry (subtract 30 seconds as buffer)
|
|
47
43
|
const bufferTimeMs = 30 * 1000; // 30 seconds in milliseconds
|
|
48
44
|
const expiresInMs = expires_in * 1000; // Convert to milliseconds
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GenericAuthenticationRefresher.js","sourceRoot":"","sources":["../../../../src/shared/lib/GenericAuthenticationRefresher.ts"],"names":[],"mappings":";;;AAAA,iDAAqD;AAGrD,
|
|
1
|
+
{"version":3,"file":"GenericAuthenticationRefresher.js","sourceRoot":"","sources":["../../../../src/shared/lib/GenericAuthenticationRefresher.ts"],"names":[],"mappings":";;;AAAA,iDAAqD;AAGrD,kDAA+E;AAG/E,MAAsB,8BAA8B;IAG1C,cAAc,CAA6B;IACzC,UAAU,CAAyB;IACnC,OAAO,CAA0B;IAE3C,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,UAAU,EAAE,WAAW,IAAI,kCAAmB,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,IAAA,wBAAc,EAAC,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;YAE5E,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QACtC,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,IAAA,iCAAuB,EAAC,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;AA9DD,wEA8DC","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\n console.log(\"Autorefreshed tokens\");\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"]}
|
|
@@ -30,5 +30,6 @@ export declare function storeTokens(storage: AuthStorage, tokens: OIDCTokenRespo
|
|
|
30
30
|
export declare function clearTokens(storage: AuthStorage): Promise<void>;
|
|
31
31
|
export declare function clearUser(storage: AuthStorage): Promise<void>;
|
|
32
32
|
export declare function retrieveTokens(storage: AuthStorage): Promise<OIDCTokenResponseBody | null>;
|
|
33
|
+
export declare function retrieveTokenExpiration(storage: AuthStorage): Promise<string | null>;
|
|
33
34
|
export declare function validateOauth2Tokens(tokens: OIDCTokenResponseBody, endpoints: Endpoints, oauth2Client: OAuth2Client, issuer: string): Promise<ParsedTokens>;
|
|
34
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;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,iBAInD;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAgBvC;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
|
+
{"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,iBAInD;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"}
|
|
@@ -43,6 +43,7 @@ exports.storeTokens = storeTokens;
|
|
|
43
43
|
exports.clearTokens = clearTokens;
|
|
44
44
|
exports.clearUser = clearUser;
|
|
45
45
|
exports.retrieveTokens = retrieveTokens;
|
|
46
|
+
exports.retrieveTokenExpiration = retrieveTokenExpiration;
|
|
46
47
|
exports.validateOauth2Tokens = validateOauth2Tokens;
|
|
47
48
|
const types_js_1 = require("./types.js");
|
|
48
49
|
const oauth2_1 = require("oslo/oauth2");
|
|
@@ -163,6 +164,9 @@ async function retrieveTokens(storage) {
|
|
|
163
164
|
timestamp: timestamp ? parseInt(timestamp, 10) : undefined, // Convert string to number
|
|
164
165
|
};
|
|
165
166
|
}
|
|
167
|
+
async function retrieveTokenExpiration(storage) {
|
|
168
|
+
return await storage.get(types_js_1.OAuthTokens.EXPIRES_IN);
|
|
169
|
+
}
|
|
166
170
|
async function validateOauth2Tokens(tokens, endpoints, oauth2Client, issuer) {
|
|
167
171
|
const JWKS = jose.createRemoteJWKSet(new URL(endpoints.jwks));
|
|
168
172
|
// validate the ID token
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../../src/shared/lib/util.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,kDAgBC;AAED,8DASC;AAED,sDAqCC;AAED,wDAqBC;AAED,8CAQC;AAED,wCA0BC;AAED,kCAcC;AAED,kCAKC;AAED,8BAIC;AAED,wCAkBC;AAED,oDAgCC;AA7ND,yCAAyC;AACzC,wCAA2C;AAC3C,6CAAwE;AACxE,2CAA6B;AAC7B,yCAA8C;AAE9C,gEAAiE;AAEjE;;GAEG;AACI,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;AAEM,KAAK,UAAU,yBAAyB,CAC7C,WAAmB,EACnB,oBAAwC,EAAE;IAE1C,MAAM,SAAS,GAAG,MAAM,IAAA,4BAAiB,EAAC,WAAW,CAAC,CAAC;IACvD,OAAO;QACL,GAAG,SAAS;QACZ,GAAG,iBAAiB;KACrB,CAAC;AACJ,CAAC;AAEM,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;AAEM,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,SAAgB,iBAAiB,CAC/B,QAAgB,EAChB,WAAmB,EACnB,SAAoB;IAEpB,OAAO,IAAI,qBAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE;QACjE,WAAW,EAAE,WAAW;KACzB,CAAC,CAAC;AACL,CAAC;AAEM,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;AAEM,KAAK,UAAU,WAAW,CAC/B,OAAoB,EACpB,MAA6B;IAE7B,4GAA4G;IAC5G,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,CAAC,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACzB,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,CAAC,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,CAAC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,sBAAW,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;AAEM,KAAK,UAAU,SAAS,CAAC,OAAoB;IAClD,MAAM,WAAW,GAAG,IAAI,mCAAkB,CAAC,OAAO,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACzB,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAEM,KAAK,UAAU,cAAc,CAClC,OAAoB;IAEpB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,CAAC,YAAY,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,CAAC,aAAa,CAAC,CAAC;IAClE,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,CAAC,UAAU,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAW,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;AAEM,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,IAAA,8BAAmB,EAAC,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,IAAA,8BAAmB,EAAC,MAAM,CAAC;KACpC,CACF,CAAC;IAEF,OAAO,IAAA,2BAAgB,EAAC;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 console.log(\"clearUser\");\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 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":"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","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 console.log(\"clearUser\");\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"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "@civic/auth:0.1.6-beta.
|
|
1
|
+
export declare const VERSION = "@civic/auth:0.1.6-beta.5";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
// This is an auto-generated file. Do not edit.
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.VERSION = void 0;
|
|
5
|
-
exports.VERSION = "@civic/auth:0.1.6-beta.
|
|
5
|
+
exports.VERSION = "@civic/auth:0.1.6-beta.5";
|
|
6
6
|
//# sourceMappingURL=version.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/shared/version.ts"],"names":[],"mappings":";AAAA,+CAA+C;;;AAElC,QAAA,OAAO,GAAG,0BAA0B,CAAC","sourcesContent":["// This is an auto-generated file. Do not edit.\n\nexport const VERSION = \"@civic/auth:0.1.6-beta.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/shared/version.ts"],"names":[],"mappings":";AAAA,+CAA+C;;;AAElC,QAAA,OAAO,GAAG,0BAA0B,CAAC","sourcesContent":["// This is an auto-generated file. Do not edit.\n\nexport const VERSION = \"@civic/auth:0.1.6-beta.5\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationRefresherImpl.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthenticationRefresherImpl.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAMrD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAErF,qBAAa,2BAA4B,SAAQ,8BAA8B;IAM3E,OAAO,CAAC,iBAAiB,CAAC;IAL5B,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO;IAWD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WAmBd,KAAK,CAChB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,WAAW,EACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GACrC,OAAO,CAAC,2BAA2B,CAAC;IAWjC,kBAAkB,IAAI,OAAO,CAAC,qBAAqB,CAAC;CAoB3D"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getEndpointsWithOverrides, validateOauth2Tokens, } from "../../shared/lib/util.js";
|
|
1
|
+
import { getEndpointsWithOverrides, storeTokens, validateOauth2Tokens, } from "../../shared/lib/util.js";
|
|
2
2
|
import { OAuth2Client } from "oslo/oauth2";
|
|
3
3
|
import { GenericAuthenticationRefresher } from "./GenericAuthenticationRefresher.js";
|
|
4
4
|
export class AuthenticationRefresherImpl extends GenericAuthenticationRefresher {
|
|
@@ -28,12 +28,15 @@ export class AuthenticationRefresherImpl extends GenericAuthenticationRefresher
|
|
|
28
28
|
return refresher;
|
|
29
29
|
}
|
|
30
30
|
async refreshAccessToken() {
|
|
31
|
+
if (!this.storage)
|
|
32
|
+
throw new Error("No storage available");
|
|
31
33
|
const refreshToken = await this.getRefreshToken();
|
|
32
34
|
if (!this.oauth2client)
|
|
33
35
|
this.init();
|
|
34
36
|
const oauth2Client = this.oauth2client;
|
|
35
37
|
const tokenResponseBody = await oauth2Client.refreshAccessToken(refreshToken);
|
|
36
38
|
await validateOauth2Tokens(tokenResponseBody, this.endpoints, oauth2Client, this.oauthServer);
|
|
39
|
+
await storeTokens(this.storage, tokenResponseBody);
|
|
37
40
|
return tokenResponseBody;
|
|
38
41
|
}
|
|
39
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationRefresherImpl.js","sourceRoot":"","sources":["../../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAErF,MAAM,OAAO,2BAA4B,SAAQ,8BAA8B;IAMnE;IALF,SAAS,CAAwB;IACjC,YAAY,CAA2B;IAC/C,YACE,UAAsB,EACtB,OAAoB,EACZ,iBAAsC;QAE9C,KAAK,EAAE,CAAC;QAFA,sBAAiB,GAAjB,iBAAiB,CAAqB;QAG9C,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAClE,uBAAuB;QACvB,IAAI,CAAC,SAAS,GAAG,MAAM,yBAAyB,CAC9C,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,iBAAiB,CACvB,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAClC,IAAI,CAAC,UAAU,CAAC,QAAQ,EACxB,IAAI,CAAC,SAAS,CAAC,IAAI,EACnB,IAAI,CAAC,SAAS,CAAC,KAAK,EACpB;YACE,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW;SACzC,CACF,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,KAAK,CAChB,UAAsB,EACtB,OAAoB,EACpB,iBAAsC;QAEtC,MAAM,SAAS,GAAG,IAAI,2BAA2B,CAC/C,UAAU,EACV,OAAO,EACP,iBAAiB,CAClB,CAAC;QACF,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;QAEvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAElD,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAa,CAAC;QACxC,MAAM,iBAAiB,GACrB,MAAM,YAAY,CAAC,kBAAkB,CACnC,YAAY,CACb,CAAC;QACJ,MAAM,oBAAoB,CACxB,iBAAiB,EACjB,IAAI,CAAC,SAAU,EACf,YAAY,EACZ,IAAI,CAAC,WAAW,CACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthenticationRefresherImpl.js","sourceRoot":"","sources":["../../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,EACzB,WAAW,EACX,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAErF,MAAM,OAAO,2BAA4B,SAAQ,8BAA8B;IAMnE;IALF,SAAS,CAAwB;IACjC,YAAY,CAA2B;IAC/C,YACE,UAAsB,EACtB,OAAoB,EACZ,iBAAsC;QAE9C,KAAK,EAAE,CAAC;QAFA,sBAAiB,GAAjB,iBAAiB,CAAqB;QAG9C,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAClE,uBAAuB;QACvB,IAAI,CAAC,SAAS,GAAG,MAAM,yBAAyB,CAC9C,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,iBAAiB,CACvB,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAClC,IAAI,CAAC,UAAU,CAAC,QAAQ,EACxB,IAAI,CAAC,SAAS,CAAC,IAAI,EACnB,IAAI,CAAC,SAAS,CAAC,KAAK,EACpB;YACE,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW;SACzC,CACF,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,KAAK,CAChB,UAAsB,EACtB,OAAoB,EACpB,iBAAsC;QAEtC,MAAM,SAAS,GAAG,IAAI,2BAA2B,CAC/C,UAAU,EACV,OAAO,EACP,iBAAiB,CAClB,CAAC;QACF,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;QAEvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC3D,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAElD,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAa,CAAC;QACxC,MAAM,iBAAiB,GACrB,MAAM,YAAY,CAAC,kBAAkB,CACnC,YAAY,CACb,CAAC;QACJ,MAAM,oBAAoB,CACxB,iBAAiB,EACjB,IAAI,CAAC,SAAU,EACf,YAAY,EACZ,IAAI,CAAC,WAAW,CACjB,CAAC;QAEF,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;QACnD,OAAO,iBAAiB,CAAC;IAC3B,CAAC;CACF","sourcesContent":["import type { AuthConfig } from \"@/server/config.js\";\nimport {\n getEndpointsWithOverrides,\n storeTokens,\n validateOauth2Tokens,\n} from \"@/shared/lib/util.js\";\nimport type { AuthStorage, Endpoints, OIDCTokenResponseBody } from \"@/types.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport { GenericAuthenticationRefresher } from \"./GenericAuthenticationRefresher.js\";\n\nexport class AuthenticationRefresherImpl extends GenericAuthenticationRefresher {\n private endpoints: Endpoints | undefined;\n private oauth2client: OAuth2Client | undefined;\n private constructor(\n authConfig: AuthConfig,\n storage: AuthStorage,\n private endpointOverrides?: Partial<Endpoints>,\n ) {\n super();\n this.authConfig = authConfig;\n this.storage = storage;\n this.init();\n }\n\n async init(): Promise<this> {\n if (!this.authConfig) throw new Error(\"No auth config available\");\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.oauthServer,\n this.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.authConfig.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.authConfig.redirectUrl,\n },\n );\n\n return this;\n }\n\n static async build(\n authConfig: AuthConfig,\n storage: AuthStorage,\n endpointOverrides?: Partial<Endpoints>,\n ): Promise<AuthenticationRefresherImpl> {\n const refresher = new AuthenticationRefresherImpl(\n authConfig,\n storage,\n endpointOverrides,\n );\n await refresher.init();\n\n return refresher;\n }\n\n async refreshAccessToken(): Promise<OIDCTokenResponseBody> {\n if (!this.storage) throw new Error(\"No storage available\");\n const refreshToken = await this.getRefreshToken();\n\n if (!this.oauth2client) this.init();\n const oauth2Client = this.oauth2client!;\n const tokenResponseBody =\n await oauth2Client.refreshAccessToken<OIDCTokenResponseBody>(\n refreshToken,\n );\n await validateOauth2Tokens(\n tokenResponseBody,\n this.endpoints!,\n oauth2Client,\n this.oauthServer,\n );\n\n await storeTokens(this.storage, tokenResponseBody);\n return tokenResponseBody;\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;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;
|
|
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;IAWrB,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;
|
|
@@ -16,11 +16,7 @@ export class GenericAuthenticationRefresher {
|
|
|
16
16
|
return tokens.refresh_token;
|
|
17
17
|
}
|
|
18
18
|
async refreshTokens() {
|
|
19
|
-
|
|
20
|
-
throw new Error("No storage available");
|
|
21
|
-
const refreshedTokens = await this.refreshAccessToken();
|
|
22
|
-
await storeTokens(this.storage, refreshedTokens);
|
|
23
|
-
return refreshedTokens;
|
|
19
|
+
return this.refreshAccessToken();
|
|
24
20
|
}
|
|
25
21
|
async handleRefresh() {
|
|
26
22
|
try {
|
|
@@ -38,8 +34,8 @@ export class GenericAuthenticationRefresher {
|
|
|
38
34
|
// Clear any existing timeout
|
|
39
35
|
this.clearAutorefresh();
|
|
40
36
|
// get expires_in
|
|
41
|
-
const
|
|
42
|
-
const expires_in =
|
|
37
|
+
const expiration = await retrieveTokenExpiration(this.storage);
|
|
38
|
+
const expires_in = Number(expiration) || 60;
|
|
43
39
|
// Calculate time until expiry (subtract 30 seconds as buffer)
|
|
44
40
|
const bufferTimeMs = 30 * 1000; // 30 seconds in milliseconds
|
|
45
41
|
const expiresInMs = expires_in * 1000; // Convert to milliseconds
|
|
@@ -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,EAAE,
|
|
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;YAE5E,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QACtC,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\n console.log(\"Autorefreshed tokens\");\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"]}
|
|
@@ -30,5 +30,6 @@ export declare function storeTokens(storage: AuthStorage, tokens: OIDCTokenRespo
|
|
|
30
30
|
export declare function clearTokens(storage: AuthStorage): Promise<void>;
|
|
31
31
|
export declare function clearUser(storage: AuthStorage): Promise<void>;
|
|
32
32
|
export declare function retrieveTokens(storage: AuthStorage): Promise<OIDCTokenResponseBody | null>;
|
|
33
|
+
export declare function retrieveTokenExpiration(storage: AuthStorage): Promise<string | null>;
|
|
33
34
|
export declare function validateOauth2Tokens(tokens: OIDCTokenResponseBody, endpoints: Endpoints, oauth2Client: OAuth2Client, issuer: string): Promise<ParsedTokens>;
|
|
34
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;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,iBAInD;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAgBvC;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
|
+
{"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,iBAInD;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"}
|
|
@@ -117,6 +117,9 @@ export async function retrieveTokens(storage) {
|
|
|
117
117
|
timestamp: timestamp ? parseInt(timestamp, 10) : undefined, // Convert string to number
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
|
+
export async function retrieveTokenExpiration(storage) {
|
|
121
|
+
return await storage.get(OAuthTokens.EXPIRES_IN);
|
|
122
|
+
}
|
|
120
123
|
export async function validateOauth2Tokens(tokens, endpoints, oauth2Client, issuer) {
|
|
121
124
|
const JWKS = jose.createRemoteJWKSet(new URL(endpoints.jwks));
|
|
122
125
|
// validate the ID token
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../../src/shared/lib/util.ts"],"names":[],"mappings":"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","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 console.log(\"clearUser\");\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 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":"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","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 console.log(\"clearUser\");\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"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "@civic/auth:0.1.6-beta.
|
|
1
|
+
export declare const VERSION = "@civic/auth:0.1.6-beta.5";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/shared/version.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,MAAM,CAAC,MAAM,OAAO,GAAG,0BAA0B,CAAC","sourcesContent":["// This is an auto-generated file. Do not edit.\n\nexport const VERSION = \"@civic/auth:0.1.6-beta.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/shared/version.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,MAAM,CAAC,MAAM,OAAO,GAAG,0BAA0B,CAAC","sourcesContent":["// This is an auto-generated file. Do not edit.\n\nexport const VERSION = \"@civic/auth:0.1.6-beta.5\";\n"]}
|