@logto/client 1.0.0-beta.2 → 1.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -0
- package/lib/index.d.ts +10 -12
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +75 -72
- package/lib/index.js.map +1 -1
- package/lib/module.js +75 -72
- package/lib/module.js.map +1 -1
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Logto Client SDK
|
|
2
|
+
[](https://www.npmjs.com/package/@logto/client)
|
|
3
|
+
[](https://github.com/logto-io/js/actions/workflows/main.yml)
|
|
4
|
+
[](https://app.codecov.io/gh/logto-io/js?branch=master)
|
|
5
|
+
|
|
6
|
+
The Logto JavaScript Client SDK written in TypeScript. Check out our [docs](https://docs.logto.io/sdk/JavaScript/client/) for more information.
|
|
7
|
+
|
|
8
|
+
We also provide [文档](https://docs.logto.io/zh-cn/sdk/JavaScript/sdk/client/) in Simplified Chinese.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
### Using npm
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @logto/client
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Using yarn
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
yarn add @logto/client
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Using pnpm
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm add @logto/client
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## What is this and how does it work?
|
|
31
|
+
|
|
32
|
+
Logto JavaScript Client SDK is platformless, and is the foundation of the other platform's SDKs (Browser, Next.js, React, Vue, etc.). Usually you are not expected to use it directly in your application, as we have released a set of official SDKs to help you integrate Logto with your favorite JavaScript frameworks. [Check this out](https://docs.logto.io/docs/recipes/integrate-logto/) and get started!
|
|
33
|
+
|
|
34
|
+
If Logto does not support your framework and you want to contribute by building a new SDK, we recommend checking out our [Browser SDK](https://github.com/logto-io/js/tree/master/packages/browser) and [Node.js SDK](https://github.com/logto-io/js/tree/master/packages/node) and start from there.
|
|
35
|
+
|
|
36
|
+
### Adapters
|
|
37
|
+
|
|
38
|
+
To implement a platform-specific SDK, you should implement the following adapters:
|
|
39
|
+
|
|
40
|
+
1. requester: send http requests.
|
|
41
|
+
2. storage: save tokens and other info.
|
|
42
|
+
3. navigate: handle redirect.
|
|
43
|
+
4. generateState: generate state.
|
|
44
|
+
5. generateCodeVerifier: generate code verifier.
|
|
45
|
+
6. generateCodeChallenge: generate code challenge.
|
|
46
|
+
|
|
47
|
+
See the [adapters.ts](./src/adapter.ts) for more information.
|
|
48
|
+
|
|
49
|
+
## Resources
|
|
50
|
+
|
|
51
|
+
[](https://logto.io/)
|
|
52
|
+
[](https://docs.logto.io/sdk/JavaScript/js/)
|
|
53
|
+
[](https://discord.gg/UEPaF3j5e6)
|
package/lib/index.d.ts
CHANGED
|
@@ -3,9 +3,9 @@ import { Nullable, NormalizeKeyPaths } from "@silverhand/essentials";
|
|
|
3
3
|
import { Infer } from "superstruct";
|
|
4
4
|
export type StorageKey = 'idToken' | 'refreshToken' | 'accessToken' | 'signInSession';
|
|
5
5
|
export interface Storage {
|
|
6
|
-
getItem(key: StorageKey): Nullable<string
|
|
7
|
-
setItem(key: StorageKey, value: string): void
|
|
8
|
-
removeItem(key: StorageKey): void
|
|
6
|
+
getItem(key: StorageKey): Promise<Nullable<string>>;
|
|
7
|
+
setItem(key: StorageKey, value: string): Promise<void>;
|
|
8
|
+
removeItem(key: StorageKey): Promise<void>;
|
|
9
9
|
}
|
|
10
10
|
type Navigate = (url: string) => void;
|
|
11
11
|
export type ClientAdapter = {
|
|
@@ -79,19 +79,17 @@ export default class LogtoClient {
|
|
|
79
79
|
expiresAt: number;
|
|
80
80
|
}>;
|
|
81
81
|
constructor(logtoConfig: LogtoConfig, adapter: ClientAdapter);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
get refreshToken(): Nullable<string>;
|
|
86
|
-
private set refreshToken(value);
|
|
87
|
-
get idToken(): Nullable<string>;
|
|
88
|
-
private set idToken(value);
|
|
82
|
+
isAuthenticated(): Promise<boolean>;
|
|
83
|
+
getRefreshToken(): Promise<Nullable<string>>;
|
|
84
|
+
getIdToken(): Promise<Nullable<string>>;
|
|
89
85
|
getAccessToken(resource?: string): Promise<string>;
|
|
90
|
-
getIdTokenClaims(): IdTokenClaims
|
|
86
|
+
getIdTokenClaims(): Promise<IdTokenClaims>;
|
|
91
87
|
signIn(redirectUri: string): Promise<void>;
|
|
92
|
-
isSignInRedirected(url: string): boolean
|
|
88
|
+
isSignInRedirected(url: string): Promise<boolean>;
|
|
93
89
|
handleSignInCallback(callbackUri: string): Promise<void>;
|
|
94
90
|
signOut(postLogoutRedirectUri?: string): Promise<void>;
|
|
91
|
+
protected getSignInSession(): Promise<Nullable<LogtoSignInSessionItem>>;
|
|
92
|
+
protected setSignInSession(logtoSignInSessionItem: Nullable<LogtoSignInSessionItem>): Promise<void>;
|
|
95
93
|
}
|
|
96
94
|
|
|
97
95
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/client/src/src/adapter.ts","packages/client/src/src/errors.ts","packages/client/src/src/types/index.ts","packages/client/src/src/utils/requester.ts","packages/client/src/src/utils/index.ts","packages/client/src/src/index.ts","packages/client/src/index.ts"],"sourcesContent":[null,null,null,null,null,null,"import {\n CodeTokenResponse,\n decodeIdToken,\n fetchOidcConfig,\n fetchTokenByAuthorizationCode,\n fetchTokenByRefreshToken,\n generateSignInUri,\n generateSignOutUri,\n IdTokenClaims,\n Prompt,\n revoke,\n verifyAndParseCodeFromCallbackUri,\n verifyIdToken,\n withReservedScopes,\n} from '@logto/js';\nimport { Nullable } from '@silverhand/essentials';\nimport { createRemoteJWKSet } from 'jose';\nimport once from 'lodash.once';\nimport { assert } from 'superstruct';\n\nimport { ClientAdapter } from './adapter';\nimport { LogtoClientError } from './errors';\nimport {\n AccessToken,\n LogtoAccessTokenMapSchema,\n LogtoConfig,\n LogtoSignInSessionItem,\n LogtoSignInSessionItemSchema,\n} from './types';\nimport { buildAccessTokenKey, getDiscoveryEndpoint } from './utils';\n\nexport type { IdTokenClaims, LogtoErrorCode } from '@logto/js';\nexport { LogtoError, OidcError, Prompt, LogtoRequestError } from '@logto/js';\nexport * from './errors';\nexport type { Storage, StorageKey, ClientAdapter } from './adapter';\nexport { createRequester } from './utils';\nexport * from './types';\n\nexport default class LogtoClient {\n protected readonly logtoConfig: LogtoConfig;\n protected readonly getOidcConfig = once(this._getOidcConfig);\n protected readonly getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);\n\n protected readonly adapter: ClientAdapter;\n\n protected readonly accessTokenMap = new Map<string, AccessToken>();\n\n private readonly getAccessTokenPromiseMap = new Map<string, Promise<string>>();\n private _idToken: Nullable<string>;\n\n constructor(logtoConfig: LogtoConfig, adapter: ClientAdapter) {\n this.logtoConfig = {\n ...logtoConfig,\n prompt: logtoConfig.prompt ?? Prompt.Consent,\n scopes: withReservedScopes(logtoConfig.scopes).split(' '),\n };\n this.adapter = adapter;\n this._idToken = this.adapter.storage.getItem('idToken');\n\n if (this.logtoConfig.persistAccessToken) {\n this.loadAccessTokenMap();\n }\n }\n\n public get isAuthenticated() {\n return Boolean(this.idToken);\n }\n\n protected get signInSession(): Nullable<LogtoSignInSessionItem> {\n const jsonItem = this.adapter.storage.getItem('signInSession');\n\n if (!jsonItem) {\n return null;\n }\n\n try {\n const item: unknown = JSON.parse(jsonItem);\n assert(item, LogtoSignInSessionItemSchema);\n\n return item;\n } catch (error: unknown) {\n throw new LogtoClientError('sign_in_session.invalid', error);\n }\n }\n\n protected set signInSession(logtoSignInSessionItem: Nullable<LogtoSignInSessionItem>) {\n if (!logtoSignInSessionItem) {\n this.adapter.storage.removeItem('signInSession');\n\n return;\n }\n\n const jsonItem = JSON.stringify(logtoSignInSessionItem);\n this.adapter.storage.setItem('signInSession', jsonItem);\n }\n\n get refreshToken() {\n return this.adapter.storage.getItem('refreshToken');\n }\n\n private set refreshToken(refreshToken: Nullable<string>) {\n if (!refreshToken) {\n this.adapter.storage.removeItem('refreshToken');\n\n return;\n }\n\n this.adapter.storage.setItem('refreshToken', refreshToken);\n }\n\n get idToken() {\n return this._idToken;\n }\n\n private set idToken(idToken: Nullable<string>) {\n this._idToken = idToken;\n\n if (!idToken) {\n this.adapter.storage.removeItem('idToken');\n\n return;\n }\n\n this.adapter.storage.setItem('idToken', idToken);\n }\n\n // eslint-disable-next-line complexity\n public async getAccessToken(resource?: string): Promise<string> {\n if (!this.idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const accessTokenKey = buildAccessTokenKey(resource);\n const accessToken = this.accessTokenMap.get(accessTokenKey);\n\n if (accessToken && accessToken.expiresAt > Date.now() / 1000) {\n return accessToken.token;\n }\n\n // Since the access token has expired, delete it from the map.\n if (accessToken) {\n this.accessTokenMap.delete(accessTokenKey);\n }\n\n /**\n * Need to fetch a new access token using refresh token.\n * Reuse the cached promise if exists.\n */\n const cachedPromise = this.getAccessTokenPromiseMap.get(accessTokenKey);\n\n if (cachedPromise) {\n return cachedPromise;\n }\n\n /**\n * Create a new promise and cache in map to avoid race condition.\n * Since we enable \"refresh token rotation\" by default,\n * it will be problematic when calling multiple `getAccessToken()` closely.\n */\n const promise = this.getAccessTokenByRefreshToken(resource);\n this.getAccessTokenPromiseMap.set(accessTokenKey, promise);\n\n const token = await promise;\n this.getAccessTokenPromiseMap.delete(accessTokenKey);\n\n return token;\n }\n\n public getIdTokenClaims(): IdTokenClaims {\n if (!this.idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n return decodeIdToken(this.idToken);\n }\n\n public async signIn(redirectUri: string) {\n const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;\n const { authorizationEndpoint } = await this.getOidcConfig();\n const codeVerifier = this.adapter.generateCodeVerifier();\n const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);\n const state = this.adapter.generateState();\n\n const signInUri = generateSignInUri({\n authorizationEndpoint,\n clientId,\n redirectUri,\n codeChallenge,\n state,\n scopes,\n resources,\n prompt,\n });\n\n this.signInSession = { redirectUri, codeVerifier, state };\n this.refreshToken = null;\n this.idToken = null;\n\n this.adapter.navigate(signInUri);\n }\n\n public isSignInRedirected(url: string): boolean {\n const { signInSession } = this;\n\n if (!signInSession) {\n return false;\n }\n const { redirectUri } = signInSession;\n const { origin, pathname } = new URL(url);\n\n return `${origin}${pathname}` === redirectUri;\n }\n\n public async handleSignInCallback(callbackUri: string) {\n const { signInSession, logtoConfig, adapter } = this;\n const { requester } = adapter;\n\n if (!signInSession) {\n throw new LogtoClientError('sign_in_session.not_found');\n }\n\n const { redirectUri, state, codeVerifier } = signInSession;\n const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);\n\n const { appId: clientId } = logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const codeTokenResponse = await fetchTokenByAuthorizationCode(\n {\n clientId,\n tokenEndpoint,\n redirectUri,\n codeVerifier,\n code,\n },\n requester\n );\n\n await this.verifyIdToken(codeTokenResponse.idToken);\n\n this.saveCodeToken(codeTokenResponse);\n this.signInSession = null;\n }\n\n public async signOut(postLogoutRedirectUri?: string) {\n if (!this.idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const { appId: clientId } = this.logtoConfig;\n const { endSessionEndpoint, revocationEndpoint } = await this.getOidcConfig();\n\n if (this.refreshToken) {\n try {\n await revoke(revocationEndpoint, clientId, this.refreshToken, this.adapter.requester);\n } catch {\n // Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed\n }\n }\n\n const url = generateSignOutUri({\n endSessionEndpoint,\n postLogoutRedirectUri,\n idToken: this.idToken,\n });\n\n this.accessTokenMap.clear();\n this.refreshToken = null;\n this.idToken = null;\n\n this.adapter.navigate(url);\n }\n\n private async getAccessTokenByRefreshToken(resource?: string): Promise<string> {\n if (!this.refreshToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n try {\n const accessTokenKey = buildAccessTokenKey(resource);\n const { appId: clientId } = this.logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const { accessToken, refreshToken, idToken, scope, expiresIn } =\n await fetchTokenByRefreshToken(\n {\n clientId,\n tokenEndpoint,\n refreshToken: this.refreshToken,\n resource,\n scopes: resource ? ['offline_access'] : undefined, // Force remove openid scope from the request\n },\n this.adapter.requester\n );\n\n this.accessTokenMap.set(accessTokenKey, {\n token: accessToken,\n scope,\n expiresAt: Math.round(Date.now() / 1000) + expiresIn,\n });\n this.saveAccessTokenMap();\n\n this.refreshToken = refreshToken;\n\n if (idToken) {\n await this.verifyIdToken(idToken);\n this.idToken = idToken;\n }\n\n return accessToken;\n } catch (error: unknown) {\n throw new LogtoClientError('get_access_token_by_refresh_token_failed', error);\n }\n }\n\n private async _getOidcConfig() {\n const { endpoint } = this.logtoConfig;\n const discoveryEndpoint = getDiscoveryEndpoint(endpoint);\n\n return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);\n }\n\n private async _getJwtVerifyGetKey() {\n const { jwksUri } = await this.getOidcConfig();\n\n return createRemoteJWKSet(new URL(jwksUri));\n }\n\n private async verifyIdToken(idToken: string) {\n const { appId } = this.logtoConfig;\n const { issuer } = await this.getOidcConfig();\n const jwtVerifyGetKey = await this.getJwtVerifyGetKey();\n\n try {\n await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);\n } catch (error: unknown) {\n throw new LogtoClientError('invalid_id_token', error);\n }\n }\n\n private saveCodeToken({\n refreshToken,\n idToken,\n scope,\n accessToken,\n expiresIn,\n }: CodeTokenResponse) {\n this.refreshToken = refreshToken ?? null;\n this.idToken = idToken;\n\n // NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)\n const accessTokenKey = buildAccessTokenKey();\n const expiresAt = Date.now() / 1000 + expiresIn;\n this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });\n this.saveAccessTokenMap();\n }\n\n private saveAccessTokenMap() {\n if (!this.logtoConfig.persistAccessToken) {\n return;\n }\n\n const data: Record<string, AccessToken> = {};\n\n for (const [key, accessToken] of this.accessTokenMap.entries()) {\n // eslint-disable-next-line @silverhand/fp/no-mutation\n data[key] = accessToken;\n }\n\n this.adapter.storage.setItem('accessToken', JSON.stringify(data));\n }\n\n private loadAccessTokenMap() {\n const raw = this.adapter.storage.getItem('accessToken');\n\n if (!raw) {\n return;\n }\n\n try {\n const json: unknown = JSON.parse(raw);\n assert(json, LogtoAccessTokenMapSchema);\n this.accessTokenMap.clear();\n\n for (const [key, accessToken] of Object.entries(json)) {\n this.accessTokenMap.set(key, accessToken);\n }\n } catch {}\n }\n}\n"],"names":[],"version":3,"file":"index.d.ts.map"}
|
|
1
|
+
{"mappings":";;;AAGA,yBAAyB,SAAS,GAAG,cAAc,GAAG,aAAa,GAAG,eAAe,CAAC;AAEtF;IACE,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,MAAM,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C;AAED,gBAAuB,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAE7C,4BAA4B;IAC1B,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,MAAM,CAAC;IACnC,qBAAqB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAClE,CAAC;ACjBF,QAAA,MAAM;;;;;;;;EAQJ,CAAC;AAEH,mCAAmC,kBAAkB,4BAA4B,CAAC,CAAC;AAanF,6BAA8B,SAAQ,KAAK;IACzC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;gBAEF,IAAI,EAAE,oBAAoB,EAAE,IAAI,CAAC,EAAE,OAAO;CAKvD;AChCD,0BAA0B;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,OAAO,MAAM;;;;;;;;EAIX,CAAC;AAEH,0BAA0B,MAAM,wBAAwB,CAAC,CAAC;AAE1D,OAAO,MAAM;;;;;;;;EAIX,CAAC;AAEH,OAAO,MAAM;;;;SAA+D,CAAC;AAE7E,qCAAqC,MAAM,mCAAmC,CAAC,CAAC;AC3BhF,OAAO,MAAM,iCAAkC,YAAY,KAAG,SAkB7D,CAAC;AEWF,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAM7E;IACE,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAC5C,SAAS,CAAC,QAAQ,CAAC,aAAa,mHAA6B;IAC7D,SAAS,CAAC,QAAQ,CAAC,kBAAkB,sIAAkC;IACvE,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAC1C,SAAS,CAAC,QAAQ,CAAC,cAAc;;;;OAAkC;gBAIvD,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa;IAatD,eAAe;IAIf,eAAe;IAIf,UAAU;IAKV,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAyClD,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC;IAU1C,MAAM,CAAC,WAAW,EAAE,MAAM;IAyB1B,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjD,oBAAoB,CAAC,WAAW,EAAE,MAAM;IA8BxC,OAAO,CAAC,qBAAqB,CAAC,EAAE,MAAM;cAgC5B,gBAAgB,IAAI,OAAO,CAAC,SAAS,sBAAsB,CAAC,CAAC;cAiB7D,gBAAgB,CAAC,sBAAsB,EAAE,SAAS,sBAAsB,CAAC;CAoJ1F","sources":["packages/client/src/src/adapter.ts","packages/client/src/src/errors.ts","packages/client/src/src/types/index.ts","packages/client/src/src/utils/requester.ts","packages/client/src/src/utils/index.ts","packages/client/src/src/index.ts","packages/client/src/index.ts"],"sourcesContent":[null,null,null,null,null,null,"import {\n CodeTokenResponse,\n decodeIdToken,\n fetchOidcConfig,\n fetchTokenByAuthorizationCode,\n fetchTokenByRefreshToken,\n generateSignInUri,\n generateSignOutUri,\n IdTokenClaims,\n Prompt,\n revoke,\n verifyAndParseCodeFromCallbackUri,\n verifyIdToken,\n withReservedScopes,\n} from '@logto/js';\nimport { Nullable } from '@silverhand/essentials';\nimport { createRemoteJWKSet } from 'jose';\nimport once from 'lodash.once';\nimport { assert } from 'superstruct';\n\nimport { ClientAdapter } from './adapter';\nimport { LogtoClientError } from './errors';\nimport {\n AccessToken,\n LogtoAccessTokenMapSchema,\n LogtoConfig,\n LogtoSignInSessionItem,\n LogtoSignInSessionItemSchema,\n} from './types';\nimport { buildAccessTokenKey, getDiscoveryEndpoint } from './utils';\n\nexport type { IdTokenClaims, LogtoErrorCode } from '@logto/js';\nexport { LogtoError, OidcError, Prompt, LogtoRequestError } from '@logto/js';\nexport * from './errors';\nexport type { Storage, StorageKey, ClientAdapter } from './adapter';\nexport { createRequester } from './utils';\nexport * from './types';\n\nexport default class LogtoClient {\n protected readonly logtoConfig: LogtoConfig;\n protected readonly getOidcConfig = once(this._getOidcConfig);\n protected readonly getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);\n protected readonly adapter: ClientAdapter;\n protected readonly accessTokenMap = new Map<string, AccessToken>();\n\n private readonly getAccessTokenPromiseMap = new Map<string, Promise<string>>();\n\n constructor(logtoConfig: LogtoConfig, adapter: ClientAdapter) {\n this.logtoConfig = {\n ...logtoConfig,\n prompt: logtoConfig.prompt ?? Prompt.Consent,\n scopes: withReservedScopes(logtoConfig.scopes).split(' '),\n };\n this.adapter = adapter;\n\n if (this.logtoConfig.persistAccessToken) {\n void this.loadAccessTokenMap();\n }\n }\n\n async isAuthenticated() {\n return Boolean(await this.getIdToken());\n }\n\n async getRefreshToken() {\n return this.adapter.storage.getItem('refreshToken');\n }\n\n async getIdToken() {\n return this.adapter.storage.getItem('idToken');\n }\n\n // eslint-disable-next-line complexity\n async getAccessToken(resource?: string): Promise<string> {\n if (!(await this.getIdToken())) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const accessTokenKey = buildAccessTokenKey(resource);\n const accessToken = this.accessTokenMap.get(accessTokenKey);\n\n if (accessToken && accessToken.expiresAt > Date.now() / 1000) {\n return accessToken.token;\n }\n\n // Since the access token has expired, delete it from the map.\n if (accessToken) {\n this.accessTokenMap.delete(accessTokenKey);\n }\n\n /**\n * Need to fetch a new access token using refresh token.\n * Reuse the cached promise if exists.\n */\n const cachedPromise = this.getAccessTokenPromiseMap.get(accessTokenKey);\n\n if (cachedPromise) {\n return cachedPromise;\n }\n\n /**\n * Create a new promise and cache in map to avoid race condition.\n * Since we enable \"refresh token rotation\" by default,\n * it will be problematic when calling multiple `getAccessToken()` closely.\n */\n const promise = this.getAccessTokenByRefreshToken(resource);\n this.getAccessTokenPromiseMap.set(accessTokenKey, promise);\n\n const token = await promise;\n this.getAccessTokenPromiseMap.delete(accessTokenKey);\n\n return token;\n }\n\n async getIdTokenClaims(): Promise<IdTokenClaims> {\n const idToken = await this.getIdToken();\n\n if (!idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n return decodeIdToken(idToken);\n }\n\n async signIn(redirectUri: string) {\n const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;\n const { authorizationEndpoint } = await this.getOidcConfig();\n const codeVerifier = this.adapter.generateCodeVerifier();\n const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);\n const state = this.adapter.generateState();\n\n const signInUri = generateSignInUri({\n authorizationEndpoint,\n clientId,\n redirectUri,\n codeChallenge,\n state,\n scopes,\n resources,\n prompt,\n });\n\n await this.setSignInSession({ redirectUri, codeVerifier, state });\n await this.setRefreshToken(null);\n await this.setIdToken(null);\n\n this.adapter.navigate(signInUri);\n }\n\n async isSignInRedirected(url: string): Promise<boolean> {\n const signInSession = await this.getSignInSession();\n\n if (!signInSession) {\n return false;\n }\n const { redirectUri } = signInSession;\n const { origin, pathname } = new URL(url);\n\n return `${origin}${pathname}` === redirectUri;\n }\n\n async handleSignInCallback(callbackUri: string) {\n const { logtoConfig, adapter } = this;\n const { requester } = adapter;\n const signInSession = await this.getSignInSession();\n\n if (!signInSession) {\n throw new LogtoClientError('sign_in_session.not_found');\n }\n\n const { redirectUri, state, codeVerifier } = signInSession;\n const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);\n\n const { appId: clientId } = logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const codeTokenResponse = await fetchTokenByAuthorizationCode(\n {\n clientId,\n tokenEndpoint,\n redirectUri,\n codeVerifier,\n code,\n },\n requester\n );\n\n await this.verifyIdToken(codeTokenResponse.idToken);\n await this.saveCodeToken(codeTokenResponse);\n await this.setSignInSession(null);\n }\n\n async signOut(postLogoutRedirectUri?: string) {\n const idToken = await this.getIdToken();\n\n if (!idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const { appId: clientId } = this.logtoConfig;\n const { endSessionEndpoint, revocationEndpoint } = await this.getOidcConfig();\n const refreshToken = await this.getRefreshToken();\n\n if (refreshToken) {\n try {\n await revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);\n } catch {\n // Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed\n }\n }\n\n const url = generateSignOutUri({\n endSessionEndpoint,\n postLogoutRedirectUri,\n idToken,\n });\n\n this.accessTokenMap.clear();\n await this.setRefreshToken(null);\n await this.setIdToken(null);\n\n this.adapter.navigate(url);\n }\n\n protected async getSignInSession(): Promise<Nullable<LogtoSignInSessionItem>> {\n const jsonItem = await this.adapter.storage.getItem('signInSession');\n\n if (!jsonItem) {\n return null;\n }\n\n try {\n const item: unknown = JSON.parse(jsonItem);\n assert(item, LogtoSignInSessionItemSchema);\n\n return item;\n } catch (error: unknown) {\n throw new LogtoClientError('sign_in_session.invalid', error);\n }\n }\n\n protected async setSignInSession(logtoSignInSessionItem: Nullable<LogtoSignInSessionItem>) {\n if (!logtoSignInSessionItem) {\n await this.adapter.storage.removeItem('signInSession');\n\n return;\n }\n\n const jsonItem = JSON.stringify(logtoSignInSessionItem);\n await this.adapter.storage.setItem('signInSession', jsonItem);\n }\n\n private async setIdToken(idToken: Nullable<string>) {\n if (!idToken) {\n await this.adapter.storage.removeItem('idToken');\n\n return;\n }\n\n await this.adapter.storage.setItem('idToken', idToken);\n }\n\n private async setRefreshToken(refreshToken: Nullable<string>) {\n if (!refreshToken) {\n await this.adapter.storage.removeItem('refreshToken');\n\n return;\n }\n\n await this.adapter.storage.setItem('refreshToken', refreshToken);\n }\n\n private async getAccessTokenByRefreshToken(resource?: string): Promise<string> {\n const currentRefreshToken = await this.getRefreshToken();\n\n if (!currentRefreshToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n try {\n const accessTokenKey = buildAccessTokenKey(resource);\n const { appId: clientId } = this.logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const { accessToken, refreshToken, idToken, scope, expiresIn } =\n await fetchTokenByRefreshToken(\n {\n clientId,\n tokenEndpoint,\n refreshToken: currentRefreshToken,\n resource,\n scopes: resource ? ['offline_access'] : undefined, // Force remove openid scope from the request\n },\n this.adapter.requester\n );\n\n this.accessTokenMap.set(accessTokenKey, {\n token: accessToken,\n scope,\n expiresAt: Math.round(Date.now() / 1000) + expiresIn,\n });\n\n await this.saveAccessTokenMap();\n await this.setRefreshToken(refreshToken);\n\n if (idToken) {\n await this.verifyIdToken(idToken);\n await this.setIdToken(idToken);\n }\n\n return accessToken;\n } catch (error: unknown) {\n throw new LogtoClientError('get_access_token_by_refresh_token_failed', error);\n }\n }\n\n private async _getOidcConfig() {\n const { endpoint } = this.logtoConfig;\n const discoveryEndpoint = getDiscoveryEndpoint(endpoint);\n\n return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);\n }\n\n private async _getJwtVerifyGetKey() {\n const { jwksUri } = await this.getOidcConfig();\n\n return createRemoteJWKSet(new URL(jwksUri));\n }\n\n private async verifyIdToken(idToken: string) {\n const { appId } = this.logtoConfig;\n const { issuer } = await this.getOidcConfig();\n const jwtVerifyGetKey = await this.getJwtVerifyGetKey();\n\n try {\n await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);\n } catch (error: unknown) {\n throw new LogtoClientError('invalid_id_token', error);\n }\n }\n\n private async saveCodeToken({\n refreshToken,\n idToken,\n scope,\n accessToken,\n expiresIn,\n }: CodeTokenResponse) {\n await this.setRefreshToken(refreshToken ?? null);\n await this.setIdToken(idToken);\n\n // NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)\n const accessTokenKey = buildAccessTokenKey();\n const expiresAt = Date.now() / 1000 + expiresIn;\n this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });\n await this.saveAccessTokenMap();\n }\n\n private async saveAccessTokenMap() {\n if (!this.logtoConfig.persistAccessToken) {\n return;\n }\n\n const data: Record<string, AccessToken> = {};\n\n for (const [key, accessToken] of this.accessTokenMap.entries()) {\n // eslint-disable-next-line @silverhand/fp/no-mutation\n data[key] = accessToken;\n }\n\n await this.adapter.storage.setItem('accessToken', JSON.stringify(data));\n }\n\n private async loadAccessTokenMap() {\n const raw = await this.adapter.storage.getItem('accessToken');\n\n if (!raw) {\n return;\n }\n\n try {\n const json: unknown = JSON.parse(raw);\n assert(json, LogtoAccessTokenMapSchema);\n this.accessTokenMap.clear();\n\n for (const [key, accessToken] of Object.entries(json)) {\n this.accessTokenMap.set(key, accessToken);\n }\n } catch {}\n }\n}\n"],"names":[],"version":3,"file":"index.d.ts.map"}
|
package/lib/index.js
CHANGED
|
@@ -126,55 +126,20 @@ class $f73788ae50447ce9$export$2e2bcd8739ae039 {
|
|
|
126
126
|
scopes: (0, $4R6L3$logtojs.withReservedScopes)(logtoConfig.scopes).split(" ")
|
|
127
127
|
};
|
|
128
128
|
this.adapter = adapter;
|
|
129
|
-
this._idToken = this.adapter.storage.getItem("idToken");
|
|
130
129
|
if (this.logtoConfig.persistAccessToken) this.loadAccessTokenMap();
|
|
131
130
|
}
|
|
132
|
-
|
|
133
|
-
return Boolean(this.
|
|
131
|
+
async isAuthenticated() {
|
|
132
|
+
return Boolean(await this.getIdToken());
|
|
134
133
|
}
|
|
135
|
-
|
|
136
|
-
const jsonItem = this.adapter.storage.getItem("signInSession");
|
|
137
|
-
if (!jsonItem) return null;
|
|
138
|
-
try {
|
|
139
|
-
const item = JSON.parse(jsonItem);
|
|
140
|
-
(0, $4R6L3$superstruct.assert)(item, (0, $6d3989f7f53311af$export$7b65a75f516b80e1));
|
|
141
|
-
return item;
|
|
142
|
-
} catch (error) {
|
|
143
|
-
throw new (0, $9166104b36889c59$export$877962ca249b8fc8)("sign_in_session.invalid", error);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
set signInSession(logtoSignInSessionItem) {
|
|
147
|
-
if (!logtoSignInSessionItem) {
|
|
148
|
-
this.adapter.storage.removeItem("signInSession");
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
const jsonItem = JSON.stringify(logtoSignInSessionItem);
|
|
152
|
-
this.adapter.storage.setItem("signInSession", jsonItem);
|
|
153
|
-
}
|
|
154
|
-
get refreshToken() {
|
|
134
|
+
async getRefreshToken() {
|
|
155
135
|
return this.adapter.storage.getItem("refreshToken");
|
|
156
136
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.adapter.storage.removeItem("refreshToken");
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
this.adapter.storage.setItem("refreshToken", refreshToken);
|
|
163
|
-
}
|
|
164
|
-
get idToken() {
|
|
165
|
-
return this._idToken;
|
|
166
|
-
}
|
|
167
|
-
set idToken(idToken) {
|
|
168
|
-
this._idToken = idToken;
|
|
169
|
-
if (!idToken) {
|
|
170
|
-
this.adapter.storage.removeItem("idToken");
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
this.adapter.storage.setItem("idToken", idToken);
|
|
137
|
+
async getIdToken() {
|
|
138
|
+
return this.adapter.storage.getItem("idToken");
|
|
174
139
|
}
|
|
175
140
|
// eslint-disable-next-line complexity
|
|
176
141
|
async getAccessToken(resource) {
|
|
177
|
-
if (!this.
|
|
142
|
+
if (!await this.getIdToken()) throw new (0, $9166104b36889c59$export$877962ca249b8fc8)("not_authenticated");
|
|
178
143
|
const accessTokenKey = (0, $e2aabdbdb3cc09f0$export$8f595bd2a47bcea6)(resource);
|
|
179
144
|
const accessToken = this.accessTokenMap.get(accessTokenKey);
|
|
180
145
|
if (accessToken && accessToken.expiresAt > Date.now() / 1000) return accessToken.token;
|
|
@@ -195,9 +160,10 @@ class $f73788ae50447ce9$export$2e2bcd8739ae039 {
|
|
|
195
160
|
this.getAccessTokenPromiseMap.delete(accessTokenKey);
|
|
196
161
|
return token;
|
|
197
162
|
}
|
|
198
|
-
getIdTokenClaims() {
|
|
199
|
-
|
|
200
|
-
|
|
163
|
+
async getIdTokenClaims() {
|
|
164
|
+
const idToken = await this.getIdToken();
|
|
165
|
+
if (!idToken) throw new (0, $9166104b36889c59$export$877962ca249b8fc8)("not_authenticated");
|
|
166
|
+
return (0, $4R6L3$logtojs.decodeIdToken)(idToken);
|
|
201
167
|
}
|
|
202
168
|
async signIn(redirectUri) {
|
|
203
169
|
const { appId: clientId , prompt: prompt , resources: resources , scopes: scopes } = this.logtoConfig;
|
|
@@ -215,25 +181,26 @@ class $f73788ae50447ce9$export$2e2bcd8739ae039 {
|
|
|
215
181
|
resources: resources,
|
|
216
182
|
prompt: prompt
|
|
217
183
|
});
|
|
218
|
-
this.
|
|
184
|
+
await this.setSignInSession({
|
|
219
185
|
redirectUri: redirectUri,
|
|
220
186
|
codeVerifier: codeVerifier,
|
|
221
187
|
state: state
|
|
222
|
-
};
|
|
223
|
-
this.
|
|
224
|
-
this.
|
|
188
|
+
});
|
|
189
|
+
await this.setRefreshToken(null);
|
|
190
|
+
await this.setIdToken(null);
|
|
225
191
|
this.adapter.navigate(signInUri);
|
|
226
192
|
}
|
|
227
|
-
isSignInRedirected(url) {
|
|
228
|
-
const
|
|
193
|
+
async isSignInRedirected(url) {
|
|
194
|
+
const signInSession = await this.getSignInSession();
|
|
229
195
|
if (!signInSession) return false;
|
|
230
196
|
const { redirectUri: redirectUri } = signInSession;
|
|
231
197
|
const { origin: origin , pathname: pathname } = new URL(url);
|
|
232
198
|
return `${origin}${pathname}` === redirectUri;
|
|
233
199
|
}
|
|
234
200
|
async handleSignInCallback(callbackUri) {
|
|
235
|
-
const {
|
|
201
|
+
const { logtoConfig: logtoConfig , adapter: adapter } = this;
|
|
236
202
|
const { requester: requester } = adapter;
|
|
203
|
+
const signInSession = await this.getSignInSession();
|
|
237
204
|
if (!signInSession) throw new (0, $9166104b36889c59$export$877962ca249b8fc8)("sign_in_session.not_found");
|
|
238
205
|
const { redirectUri: redirectUri , state: state , codeVerifier: codeVerifier } = signInSession;
|
|
239
206
|
const code = (0, $4R6L3$logtojs.verifyAndParseCodeFromCallbackUri)(callbackUri, redirectUri, state);
|
|
@@ -247,30 +214,66 @@ class $f73788ae50447ce9$export$2e2bcd8739ae039 {
|
|
|
247
214
|
code: code
|
|
248
215
|
}, requester);
|
|
249
216
|
await this.verifyIdToken(codeTokenResponse.idToken);
|
|
250
|
-
this.saveCodeToken(codeTokenResponse);
|
|
251
|
-
this.
|
|
217
|
+
await this.saveCodeToken(codeTokenResponse);
|
|
218
|
+
await this.setSignInSession(null);
|
|
252
219
|
}
|
|
253
220
|
async signOut(postLogoutRedirectUri) {
|
|
254
|
-
|
|
221
|
+
const idToken = await this.getIdToken();
|
|
222
|
+
if (!idToken) throw new (0, $9166104b36889c59$export$877962ca249b8fc8)("not_authenticated");
|
|
255
223
|
const { appId: clientId } = this.logtoConfig;
|
|
256
224
|
const { endSessionEndpoint: endSessionEndpoint , revocationEndpoint: revocationEndpoint } = await this.getOidcConfig();
|
|
257
|
-
|
|
258
|
-
|
|
225
|
+
const refreshToken = await this.getRefreshToken();
|
|
226
|
+
if (refreshToken) try {
|
|
227
|
+
await (0, $4R6L3$logtojs.revoke)(revocationEndpoint, clientId, refreshToken, this.adapter.requester);
|
|
259
228
|
} catch {
|
|
260
229
|
// Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed
|
|
261
230
|
}
|
|
262
231
|
const url = (0, $4R6L3$logtojs.generateSignOutUri)({
|
|
263
232
|
endSessionEndpoint: endSessionEndpoint,
|
|
264
233
|
postLogoutRedirectUri: postLogoutRedirectUri,
|
|
265
|
-
idToken:
|
|
234
|
+
idToken: idToken
|
|
266
235
|
});
|
|
267
236
|
this.accessTokenMap.clear();
|
|
268
|
-
this.
|
|
269
|
-
this.
|
|
237
|
+
await this.setRefreshToken(null);
|
|
238
|
+
await this.setIdToken(null);
|
|
270
239
|
this.adapter.navigate(url);
|
|
271
240
|
}
|
|
241
|
+
async getSignInSession() {
|
|
242
|
+
const jsonItem = await this.adapter.storage.getItem("signInSession");
|
|
243
|
+
if (!jsonItem) return null;
|
|
244
|
+
try {
|
|
245
|
+
const item = JSON.parse(jsonItem);
|
|
246
|
+
(0, $4R6L3$superstruct.assert)(item, (0, $6d3989f7f53311af$export$7b65a75f516b80e1));
|
|
247
|
+
return item;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
throw new (0, $9166104b36889c59$export$877962ca249b8fc8)("sign_in_session.invalid", error);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async setSignInSession(logtoSignInSessionItem) {
|
|
253
|
+
if (!logtoSignInSessionItem) {
|
|
254
|
+
await this.adapter.storage.removeItem("signInSession");
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const jsonItem = JSON.stringify(logtoSignInSessionItem);
|
|
258
|
+
await this.adapter.storage.setItem("signInSession", jsonItem);
|
|
259
|
+
}
|
|
260
|
+
async setIdToken(idToken) {
|
|
261
|
+
if (!idToken) {
|
|
262
|
+
await this.adapter.storage.removeItem("idToken");
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
await this.adapter.storage.setItem("idToken", idToken);
|
|
266
|
+
}
|
|
267
|
+
async setRefreshToken(refreshToken) {
|
|
268
|
+
if (!refreshToken) {
|
|
269
|
+
await this.adapter.storage.removeItem("refreshToken");
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
await this.adapter.storage.setItem("refreshToken", refreshToken);
|
|
273
|
+
}
|
|
272
274
|
async getAccessTokenByRefreshToken(resource) {
|
|
273
|
-
|
|
275
|
+
const currentRefreshToken = await this.getRefreshToken();
|
|
276
|
+
if (!currentRefreshToken) throw new (0, $9166104b36889c59$export$877962ca249b8fc8)("not_authenticated");
|
|
274
277
|
try {
|
|
275
278
|
const accessTokenKey = (0, $e2aabdbdb3cc09f0$export$8f595bd2a47bcea6)(resource);
|
|
276
279
|
const { appId: clientId } = this.logtoConfig;
|
|
@@ -278,7 +281,7 @@ class $f73788ae50447ce9$export$2e2bcd8739ae039 {
|
|
|
278
281
|
const { accessToken: accessToken , refreshToken: refreshToken , idToken: idToken , scope: scope , expiresIn: expiresIn } = await (0, $4R6L3$logtojs.fetchTokenByRefreshToken)({
|
|
279
282
|
clientId: clientId,
|
|
280
283
|
tokenEndpoint: tokenEndpoint,
|
|
281
|
-
refreshToken:
|
|
284
|
+
refreshToken: currentRefreshToken,
|
|
282
285
|
resource: resource,
|
|
283
286
|
scopes: resource ? [
|
|
284
287
|
"offline_access"
|
|
@@ -289,11 +292,11 @@ class $f73788ae50447ce9$export$2e2bcd8739ae039 {
|
|
|
289
292
|
scope: scope,
|
|
290
293
|
expiresAt: Math.round(Date.now() / 1000) + expiresIn
|
|
291
294
|
});
|
|
292
|
-
this.saveAccessTokenMap();
|
|
293
|
-
this.refreshToken
|
|
295
|
+
await this.saveAccessTokenMap();
|
|
296
|
+
await this.setRefreshToken(refreshToken);
|
|
294
297
|
if (idToken) {
|
|
295
298
|
await this.verifyIdToken(idToken);
|
|
296
|
-
this.idToken
|
|
299
|
+
await this.setIdToken(idToken);
|
|
297
300
|
}
|
|
298
301
|
return accessToken;
|
|
299
302
|
} catch (error) {
|
|
@@ -319,9 +322,9 @@ class $f73788ae50447ce9$export$2e2bcd8739ae039 {
|
|
|
319
322
|
throw new (0, $9166104b36889c59$export$877962ca249b8fc8)("invalid_id_token", error);
|
|
320
323
|
}
|
|
321
324
|
}
|
|
322
|
-
saveCodeToken({ refreshToken: refreshToken , idToken: idToken , scope: scope , accessToken: accessToken , expiresIn: expiresIn }) {
|
|
323
|
-
this.refreshToken
|
|
324
|
-
this.idToken
|
|
325
|
+
async saveCodeToken({ refreshToken: refreshToken , idToken: idToken , scope: scope , accessToken: accessToken , expiresIn: expiresIn }) {
|
|
326
|
+
await this.setRefreshToken(refreshToken ?? null);
|
|
327
|
+
await this.setIdToken(idToken);
|
|
325
328
|
// NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)
|
|
326
329
|
const accessTokenKey = (0, $e2aabdbdb3cc09f0$export$8f595bd2a47bcea6)();
|
|
327
330
|
const expiresAt = Date.now() / 1000 + expiresIn;
|
|
@@ -330,17 +333,17 @@ class $f73788ae50447ce9$export$2e2bcd8739ae039 {
|
|
|
330
333
|
scope: scope,
|
|
331
334
|
expiresAt: expiresAt
|
|
332
335
|
});
|
|
333
|
-
this.saveAccessTokenMap();
|
|
336
|
+
await this.saveAccessTokenMap();
|
|
334
337
|
}
|
|
335
|
-
saveAccessTokenMap() {
|
|
338
|
+
async saveAccessTokenMap() {
|
|
336
339
|
if (!this.logtoConfig.persistAccessToken) return;
|
|
337
340
|
const data = {};
|
|
338
341
|
for (const [key, accessToken] of this.accessTokenMap.entries())// eslint-disable-next-line @silverhand/fp/no-mutation
|
|
339
342
|
data[key] = accessToken;
|
|
340
|
-
this.adapter.storage.setItem("accessToken", JSON.stringify(data));
|
|
343
|
+
await this.adapter.storage.setItem("accessToken", JSON.stringify(data));
|
|
341
344
|
}
|
|
342
|
-
loadAccessTokenMap() {
|
|
343
|
-
const raw = this.adapter.storage.getItem("accessToken");
|
|
345
|
+
async loadAccessTokenMap() {
|
|
346
|
+
const raw = await this.adapter.storage.getItem("accessToken");
|
|
344
347
|
if (!raw) return;
|
|
345
348
|
try {
|
|
346
349
|
const json = JSON.parse(raw);
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/client/src/index.ts","packages/client/src/errors.ts","packages/client/src/types/index.ts","packages/client/src/utils/index.ts","packages/client/src/utils/requester.ts"],"sourcesContent":["import {\n CodeTokenResponse,\n decodeIdToken,\n fetchOidcConfig,\n fetchTokenByAuthorizationCode,\n fetchTokenByRefreshToken,\n generateSignInUri,\n generateSignOutUri,\n IdTokenClaims,\n Prompt,\n revoke,\n verifyAndParseCodeFromCallbackUri,\n verifyIdToken,\n withReservedScopes,\n} from '@logto/js';\nimport { Nullable } from '@silverhand/essentials';\nimport { createRemoteJWKSet } from 'jose';\nimport once from 'lodash.once';\nimport { assert } from 'superstruct';\n\nimport { ClientAdapter } from './adapter';\nimport { LogtoClientError } from './errors';\nimport {\n AccessToken,\n LogtoAccessTokenMapSchema,\n LogtoConfig,\n LogtoSignInSessionItem,\n LogtoSignInSessionItemSchema,\n} from './types';\nimport { buildAccessTokenKey, getDiscoveryEndpoint } from './utils';\n\nexport type { IdTokenClaims, LogtoErrorCode } from '@logto/js';\nexport { LogtoError, OidcError, Prompt, LogtoRequestError } from '@logto/js';\nexport * from './errors';\nexport type { Storage, StorageKey, ClientAdapter } from './adapter';\nexport { createRequester } from './utils';\nexport * from './types';\n\nexport default class LogtoClient {\n protected readonly logtoConfig: LogtoConfig;\n protected readonly getOidcConfig = once(this._getOidcConfig);\n protected readonly getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);\n\n protected readonly adapter: ClientAdapter;\n\n protected readonly accessTokenMap = new Map<string, AccessToken>();\n\n private readonly getAccessTokenPromiseMap = new Map<string, Promise<string>>();\n private _idToken: Nullable<string>;\n\n constructor(logtoConfig: LogtoConfig, adapter: ClientAdapter) {\n this.logtoConfig = {\n ...logtoConfig,\n prompt: logtoConfig.prompt ?? Prompt.Consent,\n scopes: withReservedScopes(logtoConfig.scopes).split(' '),\n };\n this.adapter = adapter;\n this._idToken = this.adapter.storage.getItem('idToken');\n\n if (this.logtoConfig.persistAccessToken) {\n this.loadAccessTokenMap();\n }\n }\n\n public get isAuthenticated() {\n return Boolean(this.idToken);\n }\n\n protected get signInSession(): Nullable<LogtoSignInSessionItem> {\n const jsonItem = this.adapter.storage.getItem('signInSession');\n\n if (!jsonItem) {\n return null;\n }\n\n try {\n const item: unknown = JSON.parse(jsonItem);\n assert(item, LogtoSignInSessionItemSchema);\n\n return item;\n } catch (error: unknown) {\n throw new LogtoClientError('sign_in_session.invalid', error);\n }\n }\n\n protected set signInSession(logtoSignInSessionItem: Nullable<LogtoSignInSessionItem>) {\n if (!logtoSignInSessionItem) {\n this.adapter.storage.removeItem('signInSession');\n\n return;\n }\n\n const jsonItem = JSON.stringify(logtoSignInSessionItem);\n this.adapter.storage.setItem('signInSession', jsonItem);\n }\n\n get refreshToken() {\n return this.adapter.storage.getItem('refreshToken');\n }\n\n private set refreshToken(refreshToken: Nullable<string>) {\n if (!refreshToken) {\n this.adapter.storage.removeItem('refreshToken');\n\n return;\n }\n\n this.adapter.storage.setItem('refreshToken', refreshToken);\n }\n\n get idToken() {\n return this._idToken;\n }\n\n private set idToken(idToken: Nullable<string>) {\n this._idToken = idToken;\n\n if (!idToken) {\n this.adapter.storage.removeItem('idToken');\n\n return;\n }\n\n this.adapter.storage.setItem('idToken', idToken);\n }\n\n // eslint-disable-next-line complexity\n public async getAccessToken(resource?: string): Promise<string> {\n if (!this.idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const accessTokenKey = buildAccessTokenKey(resource);\n const accessToken = this.accessTokenMap.get(accessTokenKey);\n\n if (accessToken && accessToken.expiresAt > Date.now() / 1000) {\n return accessToken.token;\n }\n\n // Since the access token has expired, delete it from the map.\n if (accessToken) {\n this.accessTokenMap.delete(accessTokenKey);\n }\n\n /**\n * Need to fetch a new access token using refresh token.\n * Reuse the cached promise if exists.\n */\n const cachedPromise = this.getAccessTokenPromiseMap.get(accessTokenKey);\n\n if (cachedPromise) {\n return cachedPromise;\n }\n\n /**\n * Create a new promise and cache in map to avoid race condition.\n * Since we enable \"refresh token rotation\" by default,\n * it will be problematic when calling multiple `getAccessToken()` closely.\n */\n const promise = this.getAccessTokenByRefreshToken(resource);\n this.getAccessTokenPromiseMap.set(accessTokenKey, promise);\n\n const token = await promise;\n this.getAccessTokenPromiseMap.delete(accessTokenKey);\n\n return token;\n }\n\n public getIdTokenClaims(): IdTokenClaims {\n if (!this.idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n return decodeIdToken(this.idToken);\n }\n\n public async signIn(redirectUri: string) {\n const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;\n const { authorizationEndpoint } = await this.getOidcConfig();\n const codeVerifier = this.adapter.generateCodeVerifier();\n const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);\n const state = this.adapter.generateState();\n\n const signInUri = generateSignInUri({\n authorizationEndpoint,\n clientId,\n redirectUri,\n codeChallenge,\n state,\n scopes,\n resources,\n prompt,\n });\n\n this.signInSession = { redirectUri, codeVerifier, state };\n this.refreshToken = null;\n this.idToken = null;\n\n this.adapter.navigate(signInUri);\n }\n\n public isSignInRedirected(url: string): boolean {\n const { signInSession } = this;\n\n if (!signInSession) {\n return false;\n }\n const { redirectUri } = signInSession;\n const { origin, pathname } = new URL(url);\n\n return `${origin}${pathname}` === redirectUri;\n }\n\n public async handleSignInCallback(callbackUri: string) {\n const { signInSession, logtoConfig, adapter } = this;\n const { requester } = adapter;\n\n if (!signInSession) {\n throw new LogtoClientError('sign_in_session.not_found');\n }\n\n const { redirectUri, state, codeVerifier } = signInSession;\n const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);\n\n const { appId: clientId } = logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const codeTokenResponse = await fetchTokenByAuthorizationCode(\n {\n clientId,\n tokenEndpoint,\n redirectUri,\n codeVerifier,\n code,\n },\n requester\n );\n\n await this.verifyIdToken(codeTokenResponse.idToken);\n\n this.saveCodeToken(codeTokenResponse);\n this.signInSession = null;\n }\n\n public async signOut(postLogoutRedirectUri?: string) {\n if (!this.idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const { appId: clientId } = this.logtoConfig;\n const { endSessionEndpoint, revocationEndpoint } = await this.getOidcConfig();\n\n if (this.refreshToken) {\n try {\n await revoke(revocationEndpoint, clientId, this.refreshToken, this.adapter.requester);\n } catch {\n // Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed\n }\n }\n\n const url = generateSignOutUri({\n endSessionEndpoint,\n postLogoutRedirectUri,\n idToken: this.idToken,\n });\n\n this.accessTokenMap.clear();\n this.refreshToken = null;\n this.idToken = null;\n\n this.adapter.navigate(url);\n }\n\n private async getAccessTokenByRefreshToken(resource?: string): Promise<string> {\n if (!this.refreshToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n try {\n const accessTokenKey = buildAccessTokenKey(resource);\n const { appId: clientId } = this.logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const { accessToken, refreshToken, idToken, scope, expiresIn } =\n await fetchTokenByRefreshToken(\n {\n clientId,\n tokenEndpoint,\n refreshToken: this.refreshToken,\n resource,\n scopes: resource ? ['offline_access'] : undefined, // Force remove openid scope from the request\n },\n this.adapter.requester\n );\n\n this.accessTokenMap.set(accessTokenKey, {\n token: accessToken,\n scope,\n expiresAt: Math.round(Date.now() / 1000) + expiresIn,\n });\n this.saveAccessTokenMap();\n\n this.refreshToken = refreshToken;\n\n if (idToken) {\n await this.verifyIdToken(idToken);\n this.idToken = idToken;\n }\n\n return accessToken;\n } catch (error: unknown) {\n throw new LogtoClientError('get_access_token_by_refresh_token_failed', error);\n }\n }\n\n private async _getOidcConfig() {\n const { endpoint } = this.logtoConfig;\n const discoveryEndpoint = getDiscoveryEndpoint(endpoint);\n\n return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);\n }\n\n private async _getJwtVerifyGetKey() {\n const { jwksUri } = await this.getOidcConfig();\n\n return createRemoteJWKSet(new URL(jwksUri));\n }\n\n private async verifyIdToken(idToken: string) {\n const { appId } = this.logtoConfig;\n const { issuer } = await this.getOidcConfig();\n const jwtVerifyGetKey = await this.getJwtVerifyGetKey();\n\n try {\n await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);\n } catch (error: unknown) {\n throw new LogtoClientError('invalid_id_token', error);\n }\n }\n\n private saveCodeToken({\n refreshToken,\n idToken,\n scope,\n accessToken,\n expiresIn,\n }: CodeTokenResponse) {\n this.refreshToken = refreshToken ?? null;\n this.idToken = idToken;\n\n // NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)\n const accessTokenKey = buildAccessTokenKey();\n const expiresAt = Date.now() / 1000 + expiresIn;\n this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });\n this.saveAccessTokenMap();\n }\n\n private saveAccessTokenMap() {\n if (!this.logtoConfig.persistAccessToken) {\n return;\n }\n\n const data: Record<string, AccessToken> = {};\n\n for (const [key, accessToken] of this.accessTokenMap.entries()) {\n // eslint-disable-next-line @silverhand/fp/no-mutation\n data[key] = accessToken;\n }\n\n this.adapter.storage.setItem('accessToken', JSON.stringify(data));\n }\n\n private loadAccessTokenMap() {\n const raw = this.adapter.storage.getItem('accessToken');\n\n if (!raw) {\n return;\n }\n\n try {\n const json: unknown = JSON.parse(raw);\n assert(json, LogtoAccessTokenMapSchema);\n this.accessTokenMap.clear();\n\n for (const [key, accessToken] of Object.entries(json)) {\n this.accessTokenMap.set(key, accessToken);\n }\n } catch {}\n }\n}\n","import { NormalizeKeyPaths } from '@silverhand/essentials';\nimport get from 'lodash.get';\n\nconst logtoClientErrorCodes = Object.freeze({\n sign_in_session: {\n invalid: 'Invalid sign-in session.',\n not_found: 'Sign-in session not found.',\n },\n not_authenticated: 'Not authenticated.',\n get_access_token_by_refresh_token_failed: 'Failed to get access token by refresh token.',\n invalid_id_token: 'Invalid id token.',\n});\n\nexport type LogtoClientErrorCode = NormalizeKeyPaths<typeof logtoClientErrorCodes>;\n\nconst getMessageByErrorCode = (errorCode: LogtoClientErrorCode): string => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const message = get(logtoClientErrorCodes, errorCode);\n\n if (typeof message === 'string') {\n return message;\n }\n\n return errorCode;\n};\n\nexport class LogtoClientError extends Error {\n code: LogtoClientErrorCode;\n data: unknown;\n\n constructor(code: LogtoClientErrorCode, data?: unknown) {\n super(getMessageByErrorCode(code));\n this.code = code;\n this.data = data;\n }\n}\n","import { Prompt } from '@logto/js';\nimport { Infer, number, record, string, type } from 'superstruct';\n\nexport type LogtoConfig = {\n endpoint: string;\n appId: string;\n appSecret?: string;\n scopes?: string[];\n resources?: string[];\n prompt?: Prompt;\n persistAccessToken?: boolean;\n};\n\nexport const AccessTokenSchema = type({\n token: string(),\n scope: string(),\n expiresAt: number(),\n});\n\nexport type AccessToken = Infer<typeof AccessTokenSchema>;\n\nexport const LogtoSignInSessionItemSchema = type({\n redirectUri: string(),\n codeVerifier: string(),\n state: string(),\n});\n\nexport const LogtoAccessTokenMapSchema = record(string(), AccessTokenSchema);\n\nexport type LogtoSignInSessionItem = Infer<typeof LogtoSignInSessionItemSchema>;\n","import { discoveryPath } from '@logto/js';\n\nexport * from './requester';\n\nexport const buildAccessTokenKey = (resource = '', scopes: string[] = []): string =>\n `${scopes.slice().sort().join(' ')}@${resource}`;\n\nexport const getDiscoveryEndpoint = (endpoint: string): string =>\n new URL(discoveryPath, endpoint).toString();\n","import { LogtoError, LogtoRequestError, logtoRequestErrorSchema, Requester } from '@logto/js';\n\nexport const createRequester = (fetchFunction: typeof fetch): Requester => {\n return async <T>(...args: Parameters<typeof fetch>): Promise<T> => {\n const response = await fetchFunction(...args);\n\n if (!response.ok) {\n const responseJson = await response.json();\n\n if (!logtoRequestErrorSchema.is(responseJson)) {\n throw new LogtoError('unexpected_response_error', responseJson);\n }\n\n // Expected request error from server\n const { code, message } = responseJson;\n throw new LogtoRequestError(code, message);\n }\n\n return response.json();\n };\n};\n"],"names":[],"version":3,"file":"index.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/client/src/index.ts","packages/client/src/errors.ts","packages/client/src/types/index.ts","packages/client/src/utils/index.ts","packages/client/src/utils/requester.ts"],"sourcesContent":["import {\n CodeTokenResponse,\n decodeIdToken,\n fetchOidcConfig,\n fetchTokenByAuthorizationCode,\n fetchTokenByRefreshToken,\n generateSignInUri,\n generateSignOutUri,\n IdTokenClaims,\n Prompt,\n revoke,\n verifyAndParseCodeFromCallbackUri,\n verifyIdToken,\n withReservedScopes,\n} from '@logto/js';\nimport { Nullable } from '@silverhand/essentials';\nimport { createRemoteJWKSet } from 'jose';\nimport once from 'lodash.once';\nimport { assert } from 'superstruct';\n\nimport { ClientAdapter } from './adapter';\nimport { LogtoClientError } from './errors';\nimport {\n AccessToken,\n LogtoAccessTokenMapSchema,\n LogtoConfig,\n LogtoSignInSessionItem,\n LogtoSignInSessionItemSchema,\n} from './types';\nimport { buildAccessTokenKey, getDiscoveryEndpoint } from './utils';\n\nexport type { IdTokenClaims, LogtoErrorCode } from '@logto/js';\nexport { LogtoError, OidcError, Prompt, LogtoRequestError } from '@logto/js';\nexport * from './errors';\nexport type { Storage, StorageKey, ClientAdapter } from './adapter';\nexport { createRequester } from './utils';\nexport * from './types';\n\nexport default class LogtoClient {\n protected readonly logtoConfig: LogtoConfig;\n protected readonly getOidcConfig = once(this._getOidcConfig);\n protected readonly getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);\n protected readonly adapter: ClientAdapter;\n protected readonly accessTokenMap = new Map<string, AccessToken>();\n\n private readonly getAccessTokenPromiseMap = new Map<string, Promise<string>>();\n\n constructor(logtoConfig: LogtoConfig, adapter: ClientAdapter) {\n this.logtoConfig = {\n ...logtoConfig,\n prompt: logtoConfig.prompt ?? Prompt.Consent,\n scopes: withReservedScopes(logtoConfig.scopes).split(' '),\n };\n this.adapter = adapter;\n\n if (this.logtoConfig.persistAccessToken) {\n void this.loadAccessTokenMap();\n }\n }\n\n async isAuthenticated() {\n return Boolean(await this.getIdToken());\n }\n\n async getRefreshToken() {\n return this.adapter.storage.getItem('refreshToken');\n }\n\n async getIdToken() {\n return this.adapter.storage.getItem('idToken');\n }\n\n // eslint-disable-next-line complexity\n async getAccessToken(resource?: string): Promise<string> {\n if (!(await this.getIdToken())) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const accessTokenKey = buildAccessTokenKey(resource);\n const accessToken = this.accessTokenMap.get(accessTokenKey);\n\n if (accessToken && accessToken.expiresAt > Date.now() / 1000) {\n return accessToken.token;\n }\n\n // Since the access token has expired, delete it from the map.\n if (accessToken) {\n this.accessTokenMap.delete(accessTokenKey);\n }\n\n /**\n * Need to fetch a new access token using refresh token.\n * Reuse the cached promise if exists.\n */\n const cachedPromise = this.getAccessTokenPromiseMap.get(accessTokenKey);\n\n if (cachedPromise) {\n return cachedPromise;\n }\n\n /**\n * Create a new promise and cache in map to avoid race condition.\n * Since we enable \"refresh token rotation\" by default,\n * it will be problematic when calling multiple `getAccessToken()` closely.\n */\n const promise = this.getAccessTokenByRefreshToken(resource);\n this.getAccessTokenPromiseMap.set(accessTokenKey, promise);\n\n const token = await promise;\n this.getAccessTokenPromiseMap.delete(accessTokenKey);\n\n return token;\n }\n\n async getIdTokenClaims(): Promise<IdTokenClaims> {\n const idToken = await this.getIdToken();\n\n if (!idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n return decodeIdToken(idToken);\n }\n\n async signIn(redirectUri: string) {\n const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;\n const { authorizationEndpoint } = await this.getOidcConfig();\n const codeVerifier = this.adapter.generateCodeVerifier();\n const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);\n const state = this.adapter.generateState();\n\n const signInUri = generateSignInUri({\n authorizationEndpoint,\n clientId,\n redirectUri,\n codeChallenge,\n state,\n scopes,\n resources,\n prompt,\n });\n\n await this.setSignInSession({ redirectUri, codeVerifier, state });\n await this.setRefreshToken(null);\n await this.setIdToken(null);\n\n this.adapter.navigate(signInUri);\n }\n\n async isSignInRedirected(url: string): Promise<boolean> {\n const signInSession = await this.getSignInSession();\n\n if (!signInSession) {\n return false;\n }\n const { redirectUri } = signInSession;\n const { origin, pathname } = new URL(url);\n\n return `${origin}${pathname}` === redirectUri;\n }\n\n async handleSignInCallback(callbackUri: string) {\n const { logtoConfig, adapter } = this;\n const { requester } = adapter;\n const signInSession = await this.getSignInSession();\n\n if (!signInSession) {\n throw new LogtoClientError('sign_in_session.not_found');\n }\n\n const { redirectUri, state, codeVerifier } = signInSession;\n const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);\n\n const { appId: clientId } = logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const codeTokenResponse = await fetchTokenByAuthorizationCode(\n {\n clientId,\n tokenEndpoint,\n redirectUri,\n codeVerifier,\n code,\n },\n requester\n );\n\n await this.verifyIdToken(codeTokenResponse.idToken);\n await this.saveCodeToken(codeTokenResponse);\n await this.setSignInSession(null);\n }\n\n async signOut(postLogoutRedirectUri?: string) {\n const idToken = await this.getIdToken();\n\n if (!idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const { appId: clientId } = this.logtoConfig;\n const { endSessionEndpoint, revocationEndpoint } = await this.getOidcConfig();\n const refreshToken = await this.getRefreshToken();\n\n if (refreshToken) {\n try {\n await revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);\n } catch {\n // Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed\n }\n }\n\n const url = generateSignOutUri({\n endSessionEndpoint,\n postLogoutRedirectUri,\n idToken,\n });\n\n this.accessTokenMap.clear();\n await this.setRefreshToken(null);\n await this.setIdToken(null);\n\n this.adapter.navigate(url);\n }\n\n protected async getSignInSession(): Promise<Nullable<LogtoSignInSessionItem>> {\n const jsonItem = await this.adapter.storage.getItem('signInSession');\n\n if (!jsonItem) {\n return null;\n }\n\n try {\n const item: unknown = JSON.parse(jsonItem);\n assert(item, LogtoSignInSessionItemSchema);\n\n return item;\n } catch (error: unknown) {\n throw new LogtoClientError('sign_in_session.invalid', error);\n }\n }\n\n protected async setSignInSession(logtoSignInSessionItem: Nullable<LogtoSignInSessionItem>) {\n if (!logtoSignInSessionItem) {\n await this.adapter.storage.removeItem('signInSession');\n\n return;\n }\n\n const jsonItem = JSON.stringify(logtoSignInSessionItem);\n await this.adapter.storage.setItem('signInSession', jsonItem);\n }\n\n private async setIdToken(idToken: Nullable<string>) {\n if (!idToken) {\n await this.adapter.storage.removeItem('idToken');\n\n return;\n }\n\n await this.adapter.storage.setItem('idToken', idToken);\n }\n\n private async setRefreshToken(refreshToken: Nullable<string>) {\n if (!refreshToken) {\n await this.adapter.storage.removeItem('refreshToken');\n\n return;\n }\n\n await this.adapter.storage.setItem('refreshToken', refreshToken);\n }\n\n private async getAccessTokenByRefreshToken(resource?: string): Promise<string> {\n const currentRefreshToken = await this.getRefreshToken();\n\n if (!currentRefreshToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n try {\n const accessTokenKey = buildAccessTokenKey(resource);\n const { appId: clientId } = this.logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const { accessToken, refreshToken, idToken, scope, expiresIn } =\n await fetchTokenByRefreshToken(\n {\n clientId,\n tokenEndpoint,\n refreshToken: currentRefreshToken,\n resource,\n scopes: resource ? ['offline_access'] : undefined, // Force remove openid scope from the request\n },\n this.adapter.requester\n );\n\n this.accessTokenMap.set(accessTokenKey, {\n token: accessToken,\n scope,\n expiresAt: Math.round(Date.now() / 1000) + expiresIn,\n });\n\n await this.saveAccessTokenMap();\n await this.setRefreshToken(refreshToken);\n\n if (idToken) {\n await this.verifyIdToken(idToken);\n await this.setIdToken(idToken);\n }\n\n return accessToken;\n } catch (error: unknown) {\n throw new LogtoClientError('get_access_token_by_refresh_token_failed', error);\n }\n }\n\n private async _getOidcConfig() {\n const { endpoint } = this.logtoConfig;\n const discoveryEndpoint = getDiscoveryEndpoint(endpoint);\n\n return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);\n }\n\n private async _getJwtVerifyGetKey() {\n const { jwksUri } = await this.getOidcConfig();\n\n return createRemoteJWKSet(new URL(jwksUri));\n }\n\n private async verifyIdToken(idToken: string) {\n const { appId } = this.logtoConfig;\n const { issuer } = await this.getOidcConfig();\n const jwtVerifyGetKey = await this.getJwtVerifyGetKey();\n\n try {\n await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);\n } catch (error: unknown) {\n throw new LogtoClientError('invalid_id_token', error);\n }\n }\n\n private async saveCodeToken({\n refreshToken,\n idToken,\n scope,\n accessToken,\n expiresIn,\n }: CodeTokenResponse) {\n await this.setRefreshToken(refreshToken ?? null);\n await this.setIdToken(idToken);\n\n // NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)\n const accessTokenKey = buildAccessTokenKey();\n const expiresAt = Date.now() / 1000 + expiresIn;\n this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });\n await this.saveAccessTokenMap();\n }\n\n private async saveAccessTokenMap() {\n if (!this.logtoConfig.persistAccessToken) {\n return;\n }\n\n const data: Record<string, AccessToken> = {};\n\n for (const [key, accessToken] of this.accessTokenMap.entries()) {\n // eslint-disable-next-line @silverhand/fp/no-mutation\n data[key] = accessToken;\n }\n\n await this.adapter.storage.setItem('accessToken', JSON.stringify(data));\n }\n\n private async loadAccessTokenMap() {\n const raw = await this.adapter.storage.getItem('accessToken');\n\n if (!raw) {\n return;\n }\n\n try {\n const json: unknown = JSON.parse(raw);\n assert(json, LogtoAccessTokenMapSchema);\n this.accessTokenMap.clear();\n\n for (const [key, accessToken] of Object.entries(json)) {\n this.accessTokenMap.set(key, accessToken);\n }\n } catch {}\n }\n}\n","import { NormalizeKeyPaths } from '@silverhand/essentials';\nimport get from 'lodash.get';\n\nconst logtoClientErrorCodes = Object.freeze({\n sign_in_session: {\n invalid: 'Invalid sign-in session.',\n not_found: 'Sign-in session not found.',\n },\n not_authenticated: 'Not authenticated.',\n get_access_token_by_refresh_token_failed: 'Failed to get access token by refresh token.',\n invalid_id_token: 'Invalid id token.',\n});\n\nexport type LogtoClientErrorCode = NormalizeKeyPaths<typeof logtoClientErrorCodes>;\n\nconst getMessageByErrorCode = (errorCode: LogtoClientErrorCode): string => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const message = get(logtoClientErrorCodes, errorCode);\n\n if (typeof message === 'string') {\n return message;\n }\n\n return errorCode;\n};\n\nexport class LogtoClientError extends Error {\n code: LogtoClientErrorCode;\n data: unknown;\n\n constructor(code: LogtoClientErrorCode, data?: unknown) {\n super(getMessageByErrorCode(code));\n this.code = code;\n this.data = data;\n }\n}\n","import { Prompt } from '@logto/js';\nimport { Infer, number, record, string, type } from 'superstruct';\n\nexport type LogtoConfig = {\n endpoint: string;\n appId: string;\n appSecret?: string;\n scopes?: string[];\n resources?: string[];\n prompt?: Prompt;\n persistAccessToken?: boolean;\n};\n\nexport const AccessTokenSchema = type({\n token: string(),\n scope: string(),\n expiresAt: number(),\n});\n\nexport type AccessToken = Infer<typeof AccessTokenSchema>;\n\nexport const LogtoSignInSessionItemSchema = type({\n redirectUri: string(),\n codeVerifier: string(),\n state: string(),\n});\n\nexport const LogtoAccessTokenMapSchema = record(string(), AccessTokenSchema);\n\nexport type LogtoSignInSessionItem = Infer<typeof LogtoSignInSessionItemSchema>;\n","import { discoveryPath } from '@logto/js';\n\nexport * from './requester';\n\nexport const buildAccessTokenKey = (resource = '', scopes: string[] = []): string =>\n `${scopes.slice().sort().join(' ')}@${resource}`;\n\nexport const getDiscoveryEndpoint = (endpoint: string): string =>\n new URL(discoveryPath, endpoint).toString();\n","import { LogtoError, LogtoRequestError, logtoRequestErrorSchema, Requester } from '@logto/js';\n\nexport const createRequester = (fetchFunction: typeof fetch): Requester => {\n return async <T>(...args: Parameters<typeof fetch>): Promise<T> => {\n const response = await fetchFunction(...args);\n\n if (!response.ok) {\n const responseJson = await response.json();\n\n if (!logtoRequestErrorSchema.is(responseJson)) {\n throw new LogtoError('unexpected_response_error', responseJson);\n }\n\n // Expected request error from server\n const { code, message } = responseJson;\n throw new LogtoRequestError(code, message);\n }\n\n return response.json();\n };\n};\n"],"names":[],"version":3,"file":"index.js.map"}
|
package/lib/module.js
CHANGED
|
@@ -95,55 +95,20 @@ class $19775a679e2952df$export$2e2bcd8739ae039 {
|
|
|
95
95
|
scopes: (0, $kqBTI$withReservedScopes)(logtoConfig.scopes).split(" ")
|
|
96
96
|
};
|
|
97
97
|
this.adapter = adapter;
|
|
98
|
-
this._idToken = this.adapter.storage.getItem("idToken");
|
|
99
98
|
if (this.logtoConfig.persistAccessToken) this.loadAccessTokenMap();
|
|
100
99
|
}
|
|
101
|
-
|
|
102
|
-
return Boolean(this.
|
|
100
|
+
async isAuthenticated() {
|
|
101
|
+
return Boolean(await this.getIdToken());
|
|
103
102
|
}
|
|
104
|
-
|
|
105
|
-
const jsonItem = this.adapter.storage.getItem("signInSession");
|
|
106
|
-
if (!jsonItem) return null;
|
|
107
|
-
try {
|
|
108
|
-
const item = JSON.parse(jsonItem);
|
|
109
|
-
(0, $kqBTI$assert)(item, (0, $50f2bb780a45e70c$export$7b65a75f516b80e1));
|
|
110
|
-
return item;
|
|
111
|
-
} catch (error) {
|
|
112
|
-
throw new (0, $4ec05cedcef20733$export$877962ca249b8fc8)("sign_in_session.invalid", error);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
set signInSession(logtoSignInSessionItem) {
|
|
116
|
-
if (!logtoSignInSessionItem) {
|
|
117
|
-
this.adapter.storage.removeItem("signInSession");
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const jsonItem = JSON.stringify(logtoSignInSessionItem);
|
|
121
|
-
this.adapter.storage.setItem("signInSession", jsonItem);
|
|
122
|
-
}
|
|
123
|
-
get refreshToken() {
|
|
103
|
+
async getRefreshToken() {
|
|
124
104
|
return this.adapter.storage.getItem("refreshToken");
|
|
125
105
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
this.adapter.storage.removeItem("refreshToken");
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
this.adapter.storage.setItem("refreshToken", refreshToken);
|
|
132
|
-
}
|
|
133
|
-
get idToken() {
|
|
134
|
-
return this._idToken;
|
|
135
|
-
}
|
|
136
|
-
set idToken(idToken) {
|
|
137
|
-
this._idToken = idToken;
|
|
138
|
-
if (!idToken) {
|
|
139
|
-
this.adapter.storage.removeItem("idToken");
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
this.adapter.storage.setItem("idToken", idToken);
|
|
106
|
+
async getIdToken() {
|
|
107
|
+
return this.adapter.storage.getItem("idToken");
|
|
143
108
|
}
|
|
144
109
|
// eslint-disable-next-line complexity
|
|
145
110
|
async getAccessToken(resource) {
|
|
146
|
-
if (!this.
|
|
111
|
+
if (!await this.getIdToken()) throw new (0, $4ec05cedcef20733$export$877962ca249b8fc8)("not_authenticated");
|
|
147
112
|
const accessTokenKey = (0, $dcfd5d64758ae70b$export$8f595bd2a47bcea6)(resource);
|
|
148
113
|
const accessToken = this.accessTokenMap.get(accessTokenKey);
|
|
149
114
|
if (accessToken && accessToken.expiresAt > Date.now() / 1000) return accessToken.token;
|
|
@@ -164,9 +129,10 @@ class $19775a679e2952df$export$2e2bcd8739ae039 {
|
|
|
164
129
|
this.getAccessTokenPromiseMap.delete(accessTokenKey);
|
|
165
130
|
return token;
|
|
166
131
|
}
|
|
167
|
-
getIdTokenClaims() {
|
|
168
|
-
|
|
169
|
-
|
|
132
|
+
async getIdTokenClaims() {
|
|
133
|
+
const idToken = await this.getIdToken();
|
|
134
|
+
if (!idToken) throw new (0, $4ec05cedcef20733$export$877962ca249b8fc8)("not_authenticated");
|
|
135
|
+
return (0, $kqBTI$decodeIdToken)(idToken);
|
|
170
136
|
}
|
|
171
137
|
async signIn(redirectUri) {
|
|
172
138
|
const { appId: clientId , prompt: prompt , resources: resources , scopes: scopes } = this.logtoConfig;
|
|
@@ -184,25 +150,26 @@ class $19775a679e2952df$export$2e2bcd8739ae039 {
|
|
|
184
150
|
resources: resources,
|
|
185
151
|
prompt: prompt
|
|
186
152
|
});
|
|
187
|
-
this.
|
|
153
|
+
await this.setSignInSession({
|
|
188
154
|
redirectUri: redirectUri,
|
|
189
155
|
codeVerifier: codeVerifier,
|
|
190
156
|
state: state
|
|
191
|
-
};
|
|
192
|
-
this.
|
|
193
|
-
this.
|
|
157
|
+
});
|
|
158
|
+
await this.setRefreshToken(null);
|
|
159
|
+
await this.setIdToken(null);
|
|
194
160
|
this.adapter.navigate(signInUri);
|
|
195
161
|
}
|
|
196
|
-
isSignInRedirected(url) {
|
|
197
|
-
const
|
|
162
|
+
async isSignInRedirected(url) {
|
|
163
|
+
const signInSession = await this.getSignInSession();
|
|
198
164
|
if (!signInSession) return false;
|
|
199
165
|
const { redirectUri: redirectUri } = signInSession;
|
|
200
166
|
const { origin: origin , pathname: pathname } = new URL(url);
|
|
201
167
|
return `${origin}${pathname}` === redirectUri;
|
|
202
168
|
}
|
|
203
169
|
async handleSignInCallback(callbackUri) {
|
|
204
|
-
const {
|
|
170
|
+
const { logtoConfig: logtoConfig , adapter: adapter } = this;
|
|
205
171
|
const { requester: requester } = adapter;
|
|
172
|
+
const signInSession = await this.getSignInSession();
|
|
206
173
|
if (!signInSession) throw new (0, $4ec05cedcef20733$export$877962ca249b8fc8)("sign_in_session.not_found");
|
|
207
174
|
const { redirectUri: redirectUri , state: state , codeVerifier: codeVerifier } = signInSession;
|
|
208
175
|
const code = (0, $kqBTI$verifyAndParseCodeFromCallbackUri)(callbackUri, redirectUri, state);
|
|
@@ -216,30 +183,66 @@ class $19775a679e2952df$export$2e2bcd8739ae039 {
|
|
|
216
183
|
code: code
|
|
217
184
|
}, requester);
|
|
218
185
|
await this.verifyIdToken(codeTokenResponse.idToken);
|
|
219
|
-
this.saveCodeToken(codeTokenResponse);
|
|
220
|
-
this.
|
|
186
|
+
await this.saveCodeToken(codeTokenResponse);
|
|
187
|
+
await this.setSignInSession(null);
|
|
221
188
|
}
|
|
222
189
|
async signOut(postLogoutRedirectUri) {
|
|
223
|
-
|
|
190
|
+
const idToken = await this.getIdToken();
|
|
191
|
+
if (!idToken) throw new (0, $4ec05cedcef20733$export$877962ca249b8fc8)("not_authenticated");
|
|
224
192
|
const { appId: clientId } = this.logtoConfig;
|
|
225
193
|
const { endSessionEndpoint: endSessionEndpoint , revocationEndpoint: revocationEndpoint } = await this.getOidcConfig();
|
|
226
|
-
|
|
227
|
-
|
|
194
|
+
const refreshToken = await this.getRefreshToken();
|
|
195
|
+
if (refreshToken) try {
|
|
196
|
+
await (0, $kqBTI$revoke)(revocationEndpoint, clientId, refreshToken, this.adapter.requester);
|
|
228
197
|
} catch {
|
|
229
198
|
// Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed
|
|
230
199
|
}
|
|
231
200
|
const url = (0, $kqBTI$generateSignOutUri)({
|
|
232
201
|
endSessionEndpoint: endSessionEndpoint,
|
|
233
202
|
postLogoutRedirectUri: postLogoutRedirectUri,
|
|
234
|
-
idToken:
|
|
203
|
+
idToken: idToken
|
|
235
204
|
});
|
|
236
205
|
this.accessTokenMap.clear();
|
|
237
|
-
this.
|
|
238
|
-
this.
|
|
206
|
+
await this.setRefreshToken(null);
|
|
207
|
+
await this.setIdToken(null);
|
|
239
208
|
this.adapter.navigate(url);
|
|
240
209
|
}
|
|
210
|
+
async getSignInSession() {
|
|
211
|
+
const jsonItem = await this.adapter.storage.getItem("signInSession");
|
|
212
|
+
if (!jsonItem) return null;
|
|
213
|
+
try {
|
|
214
|
+
const item = JSON.parse(jsonItem);
|
|
215
|
+
(0, $kqBTI$assert)(item, (0, $50f2bb780a45e70c$export$7b65a75f516b80e1));
|
|
216
|
+
return item;
|
|
217
|
+
} catch (error) {
|
|
218
|
+
throw new (0, $4ec05cedcef20733$export$877962ca249b8fc8)("sign_in_session.invalid", error);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async setSignInSession(logtoSignInSessionItem) {
|
|
222
|
+
if (!logtoSignInSessionItem) {
|
|
223
|
+
await this.adapter.storage.removeItem("signInSession");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const jsonItem = JSON.stringify(logtoSignInSessionItem);
|
|
227
|
+
await this.adapter.storage.setItem("signInSession", jsonItem);
|
|
228
|
+
}
|
|
229
|
+
async setIdToken(idToken) {
|
|
230
|
+
if (!idToken) {
|
|
231
|
+
await this.adapter.storage.removeItem("idToken");
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
await this.adapter.storage.setItem("idToken", idToken);
|
|
235
|
+
}
|
|
236
|
+
async setRefreshToken(refreshToken) {
|
|
237
|
+
if (!refreshToken) {
|
|
238
|
+
await this.adapter.storage.removeItem("refreshToken");
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
await this.adapter.storage.setItem("refreshToken", refreshToken);
|
|
242
|
+
}
|
|
241
243
|
async getAccessTokenByRefreshToken(resource) {
|
|
242
|
-
|
|
244
|
+
const currentRefreshToken = await this.getRefreshToken();
|
|
245
|
+
if (!currentRefreshToken) throw new (0, $4ec05cedcef20733$export$877962ca249b8fc8)("not_authenticated");
|
|
243
246
|
try {
|
|
244
247
|
const accessTokenKey = (0, $dcfd5d64758ae70b$export$8f595bd2a47bcea6)(resource);
|
|
245
248
|
const { appId: clientId } = this.logtoConfig;
|
|
@@ -247,7 +250,7 @@ class $19775a679e2952df$export$2e2bcd8739ae039 {
|
|
|
247
250
|
const { accessToken: accessToken , refreshToken: refreshToken , idToken: idToken , scope: scope , expiresIn: expiresIn } = await (0, $kqBTI$fetchTokenByRefreshToken)({
|
|
248
251
|
clientId: clientId,
|
|
249
252
|
tokenEndpoint: tokenEndpoint,
|
|
250
|
-
refreshToken:
|
|
253
|
+
refreshToken: currentRefreshToken,
|
|
251
254
|
resource: resource,
|
|
252
255
|
scopes: resource ? [
|
|
253
256
|
"offline_access"
|
|
@@ -258,11 +261,11 @@ class $19775a679e2952df$export$2e2bcd8739ae039 {
|
|
|
258
261
|
scope: scope,
|
|
259
262
|
expiresAt: Math.round(Date.now() / 1000) + expiresIn
|
|
260
263
|
});
|
|
261
|
-
this.saveAccessTokenMap();
|
|
262
|
-
this.refreshToken
|
|
264
|
+
await this.saveAccessTokenMap();
|
|
265
|
+
await this.setRefreshToken(refreshToken);
|
|
263
266
|
if (idToken) {
|
|
264
267
|
await this.verifyIdToken(idToken);
|
|
265
|
-
this.idToken
|
|
268
|
+
await this.setIdToken(idToken);
|
|
266
269
|
}
|
|
267
270
|
return accessToken;
|
|
268
271
|
} catch (error) {
|
|
@@ -288,9 +291,9 @@ class $19775a679e2952df$export$2e2bcd8739ae039 {
|
|
|
288
291
|
throw new (0, $4ec05cedcef20733$export$877962ca249b8fc8)("invalid_id_token", error);
|
|
289
292
|
}
|
|
290
293
|
}
|
|
291
|
-
saveCodeToken({ refreshToken: refreshToken , idToken: idToken , scope: scope , accessToken: accessToken , expiresIn: expiresIn }) {
|
|
292
|
-
this.refreshToken
|
|
293
|
-
this.idToken
|
|
294
|
+
async saveCodeToken({ refreshToken: refreshToken , idToken: idToken , scope: scope , accessToken: accessToken , expiresIn: expiresIn }) {
|
|
295
|
+
await this.setRefreshToken(refreshToken ?? null);
|
|
296
|
+
await this.setIdToken(idToken);
|
|
294
297
|
// NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)
|
|
295
298
|
const accessTokenKey = (0, $dcfd5d64758ae70b$export$8f595bd2a47bcea6)();
|
|
296
299
|
const expiresAt = Date.now() / 1000 + expiresIn;
|
|
@@ -299,17 +302,17 @@ class $19775a679e2952df$export$2e2bcd8739ae039 {
|
|
|
299
302
|
scope: scope,
|
|
300
303
|
expiresAt: expiresAt
|
|
301
304
|
});
|
|
302
|
-
this.saveAccessTokenMap();
|
|
305
|
+
await this.saveAccessTokenMap();
|
|
303
306
|
}
|
|
304
|
-
saveAccessTokenMap() {
|
|
307
|
+
async saveAccessTokenMap() {
|
|
305
308
|
if (!this.logtoConfig.persistAccessToken) return;
|
|
306
309
|
const data = {};
|
|
307
310
|
for (const [key, accessToken] of this.accessTokenMap.entries())// eslint-disable-next-line @silverhand/fp/no-mutation
|
|
308
311
|
data[key] = accessToken;
|
|
309
|
-
this.adapter.storage.setItem("accessToken", JSON.stringify(data));
|
|
312
|
+
await this.adapter.storage.setItem("accessToken", JSON.stringify(data));
|
|
310
313
|
}
|
|
311
|
-
loadAccessTokenMap() {
|
|
312
|
-
const raw = this.adapter.storage.getItem("accessToken");
|
|
314
|
+
async loadAccessTokenMap() {
|
|
315
|
+
const raw = await this.adapter.storage.getItem("accessToken");
|
|
313
316
|
if (!raw) return;
|
|
314
317
|
try {
|
|
315
318
|
const json = JSON.parse(raw);
|
package/lib/module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/client/src/index.ts","packages/client/src/errors.ts","packages/client/src/types/index.ts","packages/client/src/utils/index.ts","packages/client/src/utils/requester.ts"],"sourcesContent":["import {\n CodeTokenResponse,\n decodeIdToken,\n fetchOidcConfig,\n fetchTokenByAuthorizationCode,\n fetchTokenByRefreshToken,\n generateSignInUri,\n generateSignOutUri,\n IdTokenClaims,\n Prompt,\n revoke,\n verifyAndParseCodeFromCallbackUri,\n verifyIdToken,\n withReservedScopes,\n} from '@logto/js';\nimport { Nullable } from '@silverhand/essentials';\nimport { createRemoteJWKSet } from 'jose';\nimport once from 'lodash.once';\nimport { assert } from 'superstruct';\n\nimport { ClientAdapter } from './adapter';\nimport { LogtoClientError } from './errors';\nimport {\n AccessToken,\n LogtoAccessTokenMapSchema,\n LogtoConfig,\n LogtoSignInSessionItem,\n LogtoSignInSessionItemSchema,\n} from './types';\nimport { buildAccessTokenKey, getDiscoveryEndpoint } from './utils';\n\nexport type { IdTokenClaims, LogtoErrorCode } from '@logto/js';\nexport { LogtoError, OidcError, Prompt, LogtoRequestError } from '@logto/js';\nexport * from './errors';\nexport type { Storage, StorageKey, ClientAdapter } from './adapter';\nexport { createRequester } from './utils';\nexport * from './types';\n\nexport default class LogtoClient {\n protected readonly logtoConfig: LogtoConfig;\n protected readonly getOidcConfig = once(this._getOidcConfig);\n protected readonly getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);\n\n protected readonly adapter: ClientAdapter;\n\n protected readonly accessTokenMap = new Map<string, AccessToken>();\n\n private readonly getAccessTokenPromiseMap = new Map<string, Promise<string>>();\n private _idToken: Nullable<string>;\n\n constructor(logtoConfig: LogtoConfig, adapter: ClientAdapter) {\n this.logtoConfig = {\n ...logtoConfig,\n prompt: logtoConfig.prompt ?? Prompt.Consent,\n scopes: withReservedScopes(logtoConfig.scopes).split(' '),\n };\n this.adapter = adapter;\n this._idToken = this.adapter.storage.getItem('idToken');\n\n if (this.logtoConfig.persistAccessToken) {\n this.loadAccessTokenMap();\n }\n }\n\n public get isAuthenticated() {\n return Boolean(this.idToken);\n }\n\n protected get signInSession(): Nullable<LogtoSignInSessionItem> {\n const jsonItem = this.adapter.storage.getItem('signInSession');\n\n if (!jsonItem) {\n return null;\n }\n\n try {\n const item: unknown = JSON.parse(jsonItem);\n assert(item, LogtoSignInSessionItemSchema);\n\n return item;\n } catch (error: unknown) {\n throw new LogtoClientError('sign_in_session.invalid', error);\n }\n }\n\n protected set signInSession(logtoSignInSessionItem: Nullable<LogtoSignInSessionItem>) {\n if (!logtoSignInSessionItem) {\n this.adapter.storage.removeItem('signInSession');\n\n return;\n }\n\n const jsonItem = JSON.stringify(logtoSignInSessionItem);\n this.adapter.storage.setItem('signInSession', jsonItem);\n }\n\n get refreshToken() {\n return this.adapter.storage.getItem('refreshToken');\n }\n\n private set refreshToken(refreshToken: Nullable<string>) {\n if (!refreshToken) {\n this.adapter.storage.removeItem('refreshToken');\n\n return;\n }\n\n this.adapter.storage.setItem('refreshToken', refreshToken);\n }\n\n get idToken() {\n return this._idToken;\n }\n\n private set idToken(idToken: Nullable<string>) {\n this._idToken = idToken;\n\n if (!idToken) {\n this.adapter.storage.removeItem('idToken');\n\n return;\n }\n\n this.adapter.storage.setItem('idToken', idToken);\n }\n\n // eslint-disable-next-line complexity\n public async getAccessToken(resource?: string): Promise<string> {\n if (!this.idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const accessTokenKey = buildAccessTokenKey(resource);\n const accessToken = this.accessTokenMap.get(accessTokenKey);\n\n if (accessToken && accessToken.expiresAt > Date.now() / 1000) {\n return accessToken.token;\n }\n\n // Since the access token has expired, delete it from the map.\n if (accessToken) {\n this.accessTokenMap.delete(accessTokenKey);\n }\n\n /**\n * Need to fetch a new access token using refresh token.\n * Reuse the cached promise if exists.\n */\n const cachedPromise = this.getAccessTokenPromiseMap.get(accessTokenKey);\n\n if (cachedPromise) {\n return cachedPromise;\n }\n\n /**\n * Create a new promise and cache in map to avoid race condition.\n * Since we enable \"refresh token rotation\" by default,\n * it will be problematic when calling multiple `getAccessToken()` closely.\n */\n const promise = this.getAccessTokenByRefreshToken(resource);\n this.getAccessTokenPromiseMap.set(accessTokenKey, promise);\n\n const token = await promise;\n this.getAccessTokenPromiseMap.delete(accessTokenKey);\n\n return token;\n }\n\n public getIdTokenClaims(): IdTokenClaims {\n if (!this.idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n return decodeIdToken(this.idToken);\n }\n\n public async signIn(redirectUri: string) {\n const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;\n const { authorizationEndpoint } = await this.getOidcConfig();\n const codeVerifier = this.adapter.generateCodeVerifier();\n const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);\n const state = this.adapter.generateState();\n\n const signInUri = generateSignInUri({\n authorizationEndpoint,\n clientId,\n redirectUri,\n codeChallenge,\n state,\n scopes,\n resources,\n prompt,\n });\n\n this.signInSession = { redirectUri, codeVerifier, state };\n this.refreshToken = null;\n this.idToken = null;\n\n this.adapter.navigate(signInUri);\n }\n\n public isSignInRedirected(url: string): boolean {\n const { signInSession } = this;\n\n if (!signInSession) {\n return false;\n }\n const { redirectUri } = signInSession;\n const { origin, pathname } = new URL(url);\n\n return `${origin}${pathname}` === redirectUri;\n }\n\n public async handleSignInCallback(callbackUri: string) {\n const { signInSession, logtoConfig, adapter } = this;\n const { requester } = adapter;\n\n if (!signInSession) {\n throw new LogtoClientError('sign_in_session.not_found');\n }\n\n const { redirectUri, state, codeVerifier } = signInSession;\n const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);\n\n const { appId: clientId } = logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const codeTokenResponse = await fetchTokenByAuthorizationCode(\n {\n clientId,\n tokenEndpoint,\n redirectUri,\n codeVerifier,\n code,\n },\n requester\n );\n\n await this.verifyIdToken(codeTokenResponse.idToken);\n\n this.saveCodeToken(codeTokenResponse);\n this.signInSession = null;\n }\n\n public async signOut(postLogoutRedirectUri?: string) {\n if (!this.idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const { appId: clientId } = this.logtoConfig;\n const { endSessionEndpoint, revocationEndpoint } = await this.getOidcConfig();\n\n if (this.refreshToken) {\n try {\n await revoke(revocationEndpoint, clientId, this.refreshToken, this.adapter.requester);\n } catch {\n // Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed\n }\n }\n\n const url = generateSignOutUri({\n endSessionEndpoint,\n postLogoutRedirectUri,\n idToken: this.idToken,\n });\n\n this.accessTokenMap.clear();\n this.refreshToken = null;\n this.idToken = null;\n\n this.adapter.navigate(url);\n }\n\n private async getAccessTokenByRefreshToken(resource?: string): Promise<string> {\n if (!this.refreshToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n try {\n const accessTokenKey = buildAccessTokenKey(resource);\n const { appId: clientId } = this.logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const { accessToken, refreshToken, idToken, scope, expiresIn } =\n await fetchTokenByRefreshToken(\n {\n clientId,\n tokenEndpoint,\n refreshToken: this.refreshToken,\n resource,\n scopes: resource ? ['offline_access'] : undefined, // Force remove openid scope from the request\n },\n this.adapter.requester\n );\n\n this.accessTokenMap.set(accessTokenKey, {\n token: accessToken,\n scope,\n expiresAt: Math.round(Date.now() / 1000) + expiresIn,\n });\n this.saveAccessTokenMap();\n\n this.refreshToken = refreshToken;\n\n if (idToken) {\n await this.verifyIdToken(idToken);\n this.idToken = idToken;\n }\n\n return accessToken;\n } catch (error: unknown) {\n throw new LogtoClientError('get_access_token_by_refresh_token_failed', error);\n }\n }\n\n private async _getOidcConfig() {\n const { endpoint } = this.logtoConfig;\n const discoveryEndpoint = getDiscoveryEndpoint(endpoint);\n\n return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);\n }\n\n private async _getJwtVerifyGetKey() {\n const { jwksUri } = await this.getOidcConfig();\n\n return createRemoteJWKSet(new URL(jwksUri));\n }\n\n private async verifyIdToken(idToken: string) {\n const { appId } = this.logtoConfig;\n const { issuer } = await this.getOidcConfig();\n const jwtVerifyGetKey = await this.getJwtVerifyGetKey();\n\n try {\n await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);\n } catch (error: unknown) {\n throw new LogtoClientError('invalid_id_token', error);\n }\n }\n\n private saveCodeToken({\n refreshToken,\n idToken,\n scope,\n accessToken,\n expiresIn,\n }: CodeTokenResponse) {\n this.refreshToken = refreshToken ?? null;\n this.idToken = idToken;\n\n // NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)\n const accessTokenKey = buildAccessTokenKey();\n const expiresAt = Date.now() / 1000 + expiresIn;\n this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });\n this.saveAccessTokenMap();\n }\n\n private saveAccessTokenMap() {\n if (!this.logtoConfig.persistAccessToken) {\n return;\n }\n\n const data: Record<string, AccessToken> = {};\n\n for (const [key, accessToken] of this.accessTokenMap.entries()) {\n // eslint-disable-next-line @silverhand/fp/no-mutation\n data[key] = accessToken;\n }\n\n this.adapter.storage.setItem('accessToken', JSON.stringify(data));\n }\n\n private loadAccessTokenMap() {\n const raw = this.adapter.storage.getItem('accessToken');\n\n if (!raw) {\n return;\n }\n\n try {\n const json: unknown = JSON.parse(raw);\n assert(json, LogtoAccessTokenMapSchema);\n this.accessTokenMap.clear();\n\n for (const [key, accessToken] of Object.entries(json)) {\n this.accessTokenMap.set(key, accessToken);\n }\n } catch {}\n }\n}\n","import { NormalizeKeyPaths } from '@silverhand/essentials';\nimport get from 'lodash.get';\n\nconst logtoClientErrorCodes = Object.freeze({\n sign_in_session: {\n invalid: 'Invalid sign-in session.',\n not_found: 'Sign-in session not found.',\n },\n not_authenticated: 'Not authenticated.',\n get_access_token_by_refresh_token_failed: 'Failed to get access token by refresh token.',\n invalid_id_token: 'Invalid id token.',\n});\n\nexport type LogtoClientErrorCode = NormalizeKeyPaths<typeof logtoClientErrorCodes>;\n\nconst getMessageByErrorCode = (errorCode: LogtoClientErrorCode): string => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const message = get(logtoClientErrorCodes, errorCode);\n\n if (typeof message === 'string') {\n return message;\n }\n\n return errorCode;\n};\n\nexport class LogtoClientError extends Error {\n code: LogtoClientErrorCode;\n data: unknown;\n\n constructor(code: LogtoClientErrorCode, data?: unknown) {\n super(getMessageByErrorCode(code));\n this.code = code;\n this.data = data;\n }\n}\n","import { Prompt } from '@logto/js';\nimport { Infer, number, record, string, type } from 'superstruct';\n\nexport type LogtoConfig = {\n endpoint: string;\n appId: string;\n appSecret?: string;\n scopes?: string[];\n resources?: string[];\n prompt?: Prompt;\n persistAccessToken?: boolean;\n};\n\nexport const AccessTokenSchema = type({\n token: string(),\n scope: string(),\n expiresAt: number(),\n});\n\nexport type AccessToken = Infer<typeof AccessTokenSchema>;\n\nexport const LogtoSignInSessionItemSchema = type({\n redirectUri: string(),\n codeVerifier: string(),\n state: string(),\n});\n\nexport const LogtoAccessTokenMapSchema = record(string(), AccessTokenSchema);\n\nexport type LogtoSignInSessionItem = Infer<typeof LogtoSignInSessionItemSchema>;\n","import { discoveryPath } from '@logto/js';\n\nexport * from './requester';\n\nexport const buildAccessTokenKey = (resource = '', scopes: string[] = []): string =>\n `${scopes.slice().sort().join(' ')}@${resource}`;\n\nexport const getDiscoveryEndpoint = (endpoint: string): string =>\n new URL(discoveryPath, endpoint).toString();\n","import { LogtoError, LogtoRequestError, logtoRequestErrorSchema, Requester } from '@logto/js';\n\nexport const createRequester = (fetchFunction: typeof fetch): Requester => {\n return async <T>(...args: Parameters<typeof fetch>): Promise<T> => {\n const response = await fetchFunction(...args);\n\n if (!response.ok) {\n const responseJson = await response.json();\n\n if (!logtoRequestErrorSchema.is(responseJson)) {\n throw new LogtoError('unexpected_response_error', responseJson);\n }\n\n // Expected request error from server\n const { code, message } = responseJson;\n throw new LogtoRequestError(code, message);\n }\n\n return response.json();\n };\n};\n"],"names":[],"version":3,"file":"module.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/client/src/index.ts","packages/client/src/errors.ts","packages/client/src/types/index.ts","packages/client/src/utils/index.ts","packages/client/src/utils/requester.ts"],"sourcesContent":["import {\n CodeTokenResponse,\n decodeIdToken,\n fetchOidcConfig,\n fetchTokenByAuthorizationCode,\n fetchTokenByRefreshToken,\n generateSignInUri,\n generateSignOutUri,\n IdTokenClaims,\n Prompt,\n revoke,\n verifyAndParseCodeFromCallbackUri,\n verifyIdToken,\n withReservedScopes,\n} from '@logto/js';\nimport { Nullable } from '@silverhand/essentials';\nimport { createRemoteJWKSet } from 'jose';\nimport once from 'lodash.once';\nimport { assert } from 'superstruct';\n\nimport { ClientAdapter } from './adapter';\nimport { LogtoClientError } from './errors';\nimport {\n AccessToken,\n LogtoAccessTokenMapSchema,\n LogtoConfig,\n LogtoSignInSessionItem,\n LogtoSignInSessionItemSchema,\n} from './types';\nimport { buildAccessTokenKey, getDiscoveryEndpoint } from './utils';\n\nexport type { IdTokenClaims, LogtoErrorCode } from '@logto/js';\nexport { LogtoError, OidcError, Prompt, LogtoRequestError } from '@logto/js';\nexport * from './errors';\nexport type { Storage, StorageKey, ClientAdapter } from './adapter';\nexport { createRequester } from './utils';\nexport * from './types';\n\nexport default class LogtoClient {\n protected readonly logtoConfig: LogtoConfig;\n protected readonly getOidcConfig = once(this._getOidcConfig);\n protected readonly getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);\n protected readonly adapter: ClientAdapter;\n protected readonly accessTokenMap = new Map<string, AccessToken>();\n\n private readonly getAccessTokenPromiseMap = new Map<string, Promise<string>>();\n\n constructor(logtoConfig: LogtoConfig, adapter: ClientAdapter) {\n this.logtoConfig = {\n ...logtoConfig,\n prompt: logtoConfig.prompt ?? Prompt.Consent,\n scopes: withReservedScopes(logtoConfig.scopes).split(' '),\n };\n this.adapter = adapter;\n\n if (this.logtoConfig.persistAccessToken) {\n void this.loadAccessTokenMap();\n }\n }\n\n async isAuthenticated() {\n return Boolean(await this.getIdToken());\n }\n\n async getRefreshToken() {\n return this.adapter.storage.getItem('refreshToken');\n }\n\n async getIdToken() {\n return this.adapter.storage.getItem('idToken');\n }\n\n // eslint-disable-next-line complexity\n async getAccessToken(resource?: string): Promise<string> {\n if (!(await this.getIdToken())) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const accessTokenKey = buildAccessTokenKey(resource);\n const accessToken = this.accessTokenMap.get(accessTokenKey);\n\n if (accessToken && accessToken.expiresAt > Date.now() / 1000) {\n return accessToken.token;\n }\n\n // Since the access token has expired, delete it from the map.\n if (accessToken) {\n this.accessTokenMap.delete(accessTokenKey);\n }\n\n /**\n * Need to fetch a new access token using refresh token.\n * Reuse the cached promise if exists.\n */\n const cachedPromise = this.getAccessTokenPromiseMap.get(accessTokenKey);\n\n if (cachedPromise) {\n return cachedPromise;\n }\n\n /**\n * Create a new promise and cache in map to avoid race condition.\n * Since we enable \"refresh token rotation\" by default,\n * it will be problematic when calling multiple `getAccessToken()` closely.\n */\n const promise = this.getAccessTokenByRefreshToken(resource);\n this.getAccessTokenPromiseMap.set(accessTokenKey, promise);\n\n const token = await promise;\n this.getAccessTokenPromiseMap.delete(accessTokenKey);\n\n return token;\n }\n\n async getIdTokenClaims(): Promise<IdTokenClaims> {\n const idToken = await this.getIdToken();\n\n if (!idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n return decodeIdToken(idToken);\n }\n\n async signIn(redirectUri: string) {\n const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;\n const { authorizationEndpoint } = await this.getOidcConfig();\n const codeVerifier = this.adapter.generateCodeVerifier();\n const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);\n const state = this.adapter.generateState();\n\n const signInUri = generateSignInUri({\n authorizationEndpoint,\n clientId,\n redirectUri,\n codeChallenge,\n state,\n scopes,\n resources,\n prompt,\n });\n\n await this.setSignInSession({ redirectUri, codeVerifier, state });\n await this.setRefreshToken(null);\n await this.setIdToken(null);\n\n this.adapter.navigate(signInUri);\n }\n\n async isSignInRedirected(url: string): Promise<boolean> {\n const signInSession = await this.getSignInSession();\n\n if (!signInSession) {\n return false;\n }\n const { redirectUri } = signInSession;\n const { origin, pathname } = new URL(url);\n\n return `${origin}${pathname}` === redirectUri;\n }\n\n async handleSignInCallback(callbackUri: string) {\n const { logtoConfig, adapter } = this;\n const { requester } = adapter;\n const signInSession = await this.getSignInSession();\n\n if (!signInSession) {\n throw new LogtoClientError('sign_in_session.not_found');\n }\n\n const { redirectUri, state, codeVerifier } = signInSession;\n const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);\n\n const { appId: clientId } = logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const codeTokenResponse = await fetchTokenByAuthorizationCode(\n {\n clientId,\n tokenEndpoint,\n redirectUri,\n codeVerifier,\n code,\n },\n requester\n );\n\n await this.verifyIdToken(codeTokenResponse.idToken);\n await this.saveCodeToken(codeTokenResponse);\n await this.setSignInSession(null);\n }\n\n async signOut(postLogoutRedirectUri?: string) {\n const idToken = await this.getIdToken();\n\n if (!idToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n const { appId: clientId } = this.logtoConfig;\n const { endSessionEndpoint, revocationEndpoint } = await this.getOidcConfig();\n const refreshToken = await this.getRefreshToken();\n\n if (refreshToken) {\n try {\n await revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);\n } catch {\n // Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed\n }\n }\n\n const url = generateSignOutUri({\n endSessionEndpoint,\n postLogoutRedirectUri,\n idToken,\n });\n\n this.accessTokenMap.clear();\n await this.setRefreshToken(null);\n await this.setIdToken(null);\n\n this.adapter.navigate(url);\n }\n\n protected async getSignInSession(): Promise<Nullable<LogtoSignInSessionItem>> {\n const jsonItem = await this.adapter.storage.getItem('signInSession');\n\n if (!jsonItem) {\n return null;\n }\n\n try {\n const item: unknown = JSON.parse(jsonItem);\n assert(item, LogtoSignInSessionItemSchema);\n\n return item;\n } catch (error: unknown) {\n throw new LogtoClientError('sign_in_session.invalid', error);\n }\n }\n\n protected async setSignInSession(logtoSignInSessionItem: Nullable<LogtoSignInSessionItem>) {\n if (!logtoSignInSessionItem) {\n await this.adapter.storage.removeItem('signInSession');\n\n return;\n }\n\n const jsonItem = JSON.stringify(logtoSignInSessionItem);\n await this.adapter.storage.setItem('signInSession', jsonItem);\n }\n\n private async setIdToken(idToken: Nullable<string>) {\n if (!idToken) {\n await this.adapter.storage.removeItem('idToken');\n\n return;\n }\n\n await this.adapter.storage.setItem('idToken', idToken);\n }\n\n private async setRefreshToken(refreshToken: Nullable<string>) {\n if (!refreshToken) {\n await this.adapter.storage.removeItem('refreshToken');\n\n return;\n }\n\n await this.adapter.storage.setItem('refreshToken', refreshToken);\n }\n\n private async getAccessTokenByRefreshToken(resource?: string): Promise<string> {\n const currentRefreshToken = await this.getRefreshToken();\n\n if (!currentRefreshToken) {\n throw new LogtoClientError('not_authenticated');\n }\n\n try {\n const accessTokenKey = buildAccessTokenKey(resource);\n const { appId: clientId } = this.logtoConfig;\n const { tokenEndpoint } = await this.getOidcConfig();\n const { accessToken, refreshToken, idToken, scope, expiresIn } =\n await fetchTokenByRefreshToken(\n {\n clientId,\n tokenEndpoint,\n refreshToken: currentRefreshToken,\n resource,\n scopes: resource ? ['offline_access'] : undefined, // Force remove openid scope from the request\n },\n this.adapter.requester\n );\n\n this.accessTokenMap.set(accessTokenKey, {\n token: accessToken,\n scope,\n expiresAt: Math.round(Date.now() / 1000) + expiresIn,\n });\n\n await this.saveAccessTokenMap();\n await this.setRefreshToken(refreshToken);\n\n if (idToken) {\n await this.verifyIdToken(idToken);\n await this.setIdToken(idToken);\n }\n\n return accessToken;\n } catch (error: unknown) {\n throw new LogtoClientError('get_access_token_by_refresh_token_failed', error);\n }\n }\n\n private async _getOidcConfig() {\n const { endpoint } = this.logtoConfig;\n const discoveryEndpoint = getDiscoveryEndpoint(endpoint);\n\n return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);\n }\n\n private async _getJwtVerifyGetKey() {\n const { jwksUri } = await this.getOidcConfig();\n\n return createRemoteJWKSet(new URL(jwksUri));\n }\n\n private async verifyIdToken(idToken: string) {\n const { appId } = this.logtoConfig;\n const { issuer } = await this.getOidcConfig();\n const jwtVerifyGetKey = await this.getJwtVerifyGetKey();\n\n try {\n await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);\n } catch (error: unknown) {\n throw new LogtoClientError('invalid_id_token', error);\n }\n }\n\n private async saveCodeToken({\n refreshToken,\n idToken,\n scope,\n accessToken,\n expiresIn,\n }: CodeTokenResponse) {\n await this.setRefreshToken(refreshToken ?? null);\n await this.setIdToken(idToken);\n\n // NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)\n const accessTokenKey = buildAccessTokenKey();\n const expiresAt = Date.now() / 1000 + expiresIn;\n this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });\n await this.saveAccessTokenMap();\n }\n\n private async saveAccessTokenMap() {\n if (!this.logtoConfig.persistAccessToken) {\n return;\n }\n\n const data: Record<string, AccessToken> = {};\n\n for (const [key, accessToken] of this.accessTokenMap.entries()) {\n // eslint-disable-next-line @silverhand/fp/no-mutation\n data[key] = accessToken;\n }\n\n await this.adapter.storage.setItem('accessToken', JSON.stringify(data));\n }\n\n private async loadAccessTokenMap() {\n const raw = await this.adapter.storage.getItem('accessToken');\n\n if (!raw) {\n return;\n }\n\n try {\n const json: unknown = JSON.parse(raw);\n assert(json, LogtoAccessTokenMapSchema);\n this.accessTokenMap.clear();\n\n for (const [key, accessToken] of Object.entries(json)) {\n this.accessTokenMap.set(key, accessToken);\n }\n } catch {}\n }\n}\n","import { NormalizeKeyPaths } from '@silverhand/essentials';\nimport get from 'lodash.get';\n\nconst logtoClientErrorCodes = Object.freeze({\n sign_in_session: {\n invalid: 'Invalid sign-in session.',\n not_found: 'Sign-in session not found.',\n },\n not_authenticated: 'Not authenticated.',\n get_access_token_by_refresh_token_failed: 'Failed to get access token by refresh token.',\n invalid_id_token: 'Invalid id token.',\n});\n\nexport type LogtoClientErrorCode = NormalizeKeyPaths<typeof logtoClientErrorCodes>;\n\nconst getMessageByErrorCode = (errorCode: LogtoClientErrorCode): string => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const message = get(logtoClientErrorCodes, errorCode);\n\n if (typeof message === 'string') {\n return message;\n }\n\n return errorCode;\n};\n\nexport class LogtoClientError extends Error {\n code: LogtoClientErrorCode;\n data: unknown;\n\n constructor(code: LogtoClientErrorCode, data?: unknown) {\n super(getMessageByErrorCode(code));\n this.code = code;\n this.data = data;\n }\n}\n","import { Prompt } from '@logto/js';\nimport { Infer, number, record, string, type } from 'superstruct';\n\nexport type LogtoConfig = {\n endpoint: string;\n appId: string;\n appSecret?: string;\n scopes?: string[];\n resources?: string[];\n prompt?: Prompt;\n persistAccessToken?: boolean;\n};\n\nexport const AccessTokenSchema = type({\n token: string(),\n scope: string(),\n expiresAt: number(),\n});\n\nexport type AccessToken = Infer<typeof AccessTokenSchema>;\n\nexport const LogtoSignInSessionItemSchema = type({\n redirectUri: string(),\n codeVerifier: string(),\n state: string(),\n});\n\nexport const LogtoAccessTokenMapSchema = record(string(), AccessTokenSchema);\n\nexport type LogtoSignInSessionItem = Infer<typeof LogtoSignInSessionItemSchema>;\n","import { discoveryPath } from '@logto/js';\n\nexport * from './requester';\n\nexport const buildAccessTokenKey = (resource = '', scopes: string[] = []): string =>\n `${scopes.slice().sort().join(' ')}@${resource}`;\n\nexport const getDiscoveryEndpoint = (endpoint: string): string =>\n new URL(discoveryPath, endpoint).toString();\n","import { LogtoError, LogtoRequestError, logtoRequestErrorSchema, Requester } from '@logto/js';\n\nexport const createRequester = (fetchFunction: typeof fetch): Requester => {\n return async <T>(...args: Parameters<typeof fetch>): Promise<T> => {\n const response = await fetchFunction(...args);\n\n if (!response.ok) {\n const responseJson = await response.json();\n\n if (!logtoRequestErrorSchema.is(responseJson)) {\n throw new LogtoError('unexpected_response_error', responseJson);\n }\n\n // Expected request error from server\n const { code, message } = responseJson;\n throw new LogtoRequestError(code, message);\n }\n\n return response.json();\n };\n};\n"],"names":[],"version":3,"file":"module.js.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logto/client",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.3",
|
|
4
4
|
"source": "./src/index.ts",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"publishConfig": {
|
|
68
68
|
"access": "public"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "e227f9b92f76ea7e12c2aac3d5e5b24f2b85e7e8"
|
|
71
71
|
}
|