@logto/client 1.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/errors.cjs +17 -0
- package/lib/errors.d.ts +3 -6
- package/lib/errors.js +4 -22
- package/lib/{index.mjs → index.cjs} +67 -36
- package/lib/index.d.ts +8 -16
- package/lib/index.js +36 -71
- package/lib/mock.d.ts +3 -3
- package/lib/types/{index.mjs → index.cjs} +8 -5
- package/lib/types/index.js +5 -8
- package/lib/utils/index.cjs +9 -0
- package/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.js +3 -6
- package/lib/utils/once.cjs +20 -0
- package/lib/utils/once.d.ts +3 -0
- package/lib/utils/once.js +18 -0
- package/lib/utils/{requester.mjs → requester.cjs} +7 -5
- package/lib/utils/requester.js +5 -7
- package/package.json +24 -29
- package/lib/errors.mjs +0 -27
- package/lib/utils/index.mjs +0 -6
package/lib/errors.cjs
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const logtoClientErrorCodes = Object.freeze({
|
|
4
|
+
'sign_in_session.invalid': 'Invalid sign-in session.',
|
|
5
|
+
'sign_in_session.not_found': 'Sign-in session not found.',
|
|
6
|
+
not_authenticated: 'Not authenticated.',
|
|
7
|
+
fetch_user_info_failed: 'Unable to fetch user info. The access token may be invalid.',
|
|
8
|
+
});
|
|
9
|
+
class LogtoClientError extends Error {
|
|
10
|
+
constructor(code, data) {
|
|
11
|
+
super(logtoClientErrorCodes[code]);
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.data = data;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.LogtoClientError = LogtoClientError;
|
package/lib/errors.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import type { NormalizeKeyPaths } from '@silverhand/essentials';
|
|
2
1
|
declare const logtoClientErrorCodes: Readonly<{
|
|
3
|
-
sign_in_session:
|
|
4
|
-
|
|
5
|
-
not_found: string;
|
|
6
|
-
};
|
|
2
|
+
'sign_in_session.invalid': "Invalid sign-in session.";
|
|
3
|
+
'sign_in_session.not_found': "Sign-in session not found.";
|
|
7
4
|
not_authenticated: "Not authenticated.";
|
|
8
5
|
fetch_user_info_failed: "Unable to fetch user info. The access token may be invalid.";
|
|
9
6
|
}>;
|
|
10
|
-
export type LogtoClientErrorCode =
|
|
7
|
+
export type LogtoClientErrorCode = keyof typeof logtoClientErrorCodes;
|
|
11
8
|
export declare class LogtoClientError extends Error {
|
|
12
9
|
code: LogtoClientErrorCode;
|
|
13
10
|
data: unknown;
|
package/lib/errors.js
CHANGED
|
@@ -1,33 +1,15 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var get = require('lodash.get');
|
|
4
|
-
|
|
5
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
-
|
|
7
|
-
var get__default = /*#__PURE__*/_interopDefault(get);
|
|
8
|
-
|
|
9
1
|
const logtoClientErrorCodes = Object.freeze({
|
|
10
|
-
sign_in_session:
|
|
11
|
-
|
|
12
|
-
not_found: 'Sign-in session not found.',
|
|
13
|
-
},
|
|
2
|
+
'sign_in_session.invalid': 'Invalid sign-in session.',
|
|
3
|
+
'sign_in_session.not_found': 'Sign-in session not found.',
|
|
14
4
|
not_authenticated: 'Not authenticated.',
|
|
15
5
|
fetch_user_info_failed: 'Unable to fetch user info. The access token may be invalid.',
|
|
16
6
|
});
|
|
17
|
-
const getMessageByErrorCode = (errorCode) => {
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
19
|
-
const message = get__default.default(logtoClientErrorCodes, errorCode);
|
|
20
|
-
if (typeof message === 'string') {
|
|
21
|
-
return message;
|
|
22
|
-
}
|
|
23
|
-
return errorCode;
|
|
24
|
-
};
|
|
25
7
|
class LogtoClientError extends Error {
|
|
26
8
|
constructor(code, data) {
|
|
27
|
-
super(
|
|
9
|
+
super(logtoClientErrorCodes[code]);
|
|
28
10
|
this.code = code;
|
|
29
11
|
this.data = data;
|
|
30
12
|
}
|
|
31
13
|
}
|
|
32
14
|
|
|
33
|
-
|
|
15
|
+
export { LogtoClientError };
|
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var js = require('@logto/js');
|
|
6
|
+
var jose = require('jose');
|
|
7
|
+
var errors = require('./errors.cjs');
|
|
8
|
+
var index = require('./types/index.cjs');
|
|
9
|
+
var index$1 = require('./utils/index.cjs');
|
|
10
|
+
var once = require('./utils/once.cjs');
|
|
11
|
+
var requester = require('./utils/requester.cjs');
|
|
9
12
|
|
|
10
13
|
class LogtoClient {
|
|
11
14
|
constructor(logtoConfig, adapter) {
|
|
12
|
-
this.getOidcConfig = once(this._getOidcConfig);
|
|
13
|
-
this.getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);
|
|
15
|
+
this.getOidcConfig = once.once(this._getOidcConfig);
|
|
16
|
+
this.getJwtVerifyGetKey = once.once(this._getJwtVerifyGetKey);
|
|
14
17
|
this.accessTokenMap = new Map();
|
|
15
18
|
this.logtoConfig = {
|
|
16
19
|
...logtoConfig,
|
|
17
|
-
prompt: logtoConfig.prompt ?? Prompt.Consent,
|
|
18
|
-
scopes: withDefaultScopes(logtoConfig.scopes).split(' '),
|
|
20
|
+
prompt: logtoConfig.prompt ?? js.Prompt.Consent,
|
|
21
|
+
scopes: js.withDefaultScopes(logtoConfig.scopes).split(' '),
|
|
19
22
|
};
|
|
20
23
|
this.adapter = adapter;
|
|
21
24
|
void this.loadAccessTokenMap();
|
|
@@ -31,9 +34,9 @@ class LogtoClient {
|
|
|
31
34
|
}
|
|
32
35
|
async getAccessToken(resource) {
|
|
33
36
|
if (!(await this.getIdToken())) {
|
|
34
|
-
throw new LogtoClientError('not_authenticated');
|
|
37
|
+
throw new errors.LogtoClientError('not_authenticated');
|
|
35
38
|
}
|
|
36
|
-
const accessTokenKey = buildAccessTokenKey(resource);
|
|
39
|
+
const accessTokenKey = index$1.buildAccessTokenKey(resource);
|
|
37
40
|
const accessToken = this.accessTokenMap.get(accessTokenKey);
|
|
38
41
|
if (accessToken && accessToken.expiresAt > Date.now() / 1000) {
|
|
39
42
|
return accessToken.token;
|
|
@@ -50,17 +53,17 @@ class LogtoClient {
|
|
|
50
53
|
async getIdTokenClaims() {
|
|
51
54
|
const idToken = await this.getIdToken();
|
|
52
55
|
if (!idToken) {
|
|
53
|
-
throw new LogtoClientError('not_authenticated');
|
|
56
|
+
throw new errors.LogtoClientError('not_authenticated');
|
|
54
57
|
}
|
|
55
|
-
return decodeIdToken(idToken);
|
|
58
|
+
return js.decodeIdToken(idToken);
|
|
56
59
|
}
|
|
57
60
|
async fetchUserInfo() {
|
|
58
61
|
const { userinfoEndpoint } = await this.getOidcConfig();
|
|
59
62
|
const accessToken = await this.getAccessToken();
|
|
60
63
|
if (!accessToken) {
|
|
61
|
-
throw new LogtoClientError('fetch_user_info_failed');
|
|
64
|
+
throw new errors.LogtoClientError('fetch_user_info_failed');
|
|
62
65
|
}
|
|
63
|
-
return fetchUserInfo(userinfoEndpoint, accessToken, this.adapter.requester);
|
|
66
|
+
return js.fetchUserInfo(userinfoEndpoint, accessToken, this.adapter.requester);
|
|
64
67
|
}
|
|
65
68
|
async signIn(redirectUri, interactionMode) {
|
|
66
69
|
const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;
|
|
@@ -68,7 +71,7 @@ class LogtoClient {
|
|
|
68
71
|
const codeVerifier = this.adapter.generateCodeVerifier();
|
|
69
72
|
const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);
|
|
70
73
|
const state = this.adapter.generateState();
|
|
71
|
-
const signInUri = generateSignInUri({
|
|
74
|
+
const signInUri = js.generateSignInUri({
|
|
72
75
|
authorizationEndpoint,
|
|
73
76
|
clientId,
|
|
74
77
|
redirectUri,
|
|
@@ -98,13 +101,13 @@ class LogtoClient {
|
|
|
98
101
|
const { requester } = adapter;
|
|
99
102
|
const signInSession = await this.getSignInSession();
|
|
100
103
|
if (!signInSession) {
|
|
101
|
-
throw new LogtoClientError('sign_in_session.not_found');
|
|
104
|
+
throw new errors.LogtoClientError('sign_in_session.not_found');
|
|
102
105
|
}
|
|
103
106
|
const { redirectUri, state, codeVerifier } = signInSession;
|
|
104
|
-
const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);
|
|
107
|
+
const code = js.verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);
|
|
105
108
|
const { appId: clientId } = logtoConfig;
|
|
106
109
|
const { tokenEndpoint } = await this.getOidcConfig();
|
|
107
|
-
const codeTokenResponse = await fetchTokenByAuthorizationCode({
|
|
110
|
+
const codeTokenResponse = await js.fetchTokenByAuthorizationCode({
|
|
108
111
|
clientId,
|
|
109
112
|
tokenEndpoint,
|
|
110
113
|
redirectUri,
|
|
@@ -121,13 +124,13 @@ class LogtoClient {
|
|
|
121
124
|
const refreshToken = await this.getRefreshToken();
|
|
122
125
|
if (refreshToken) {
|
|
123
126
|
try {
|
|
124
|
-
await revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);
|
|
127
|
+
await js.revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);
|
|
125
128
|
}
|
|
126
129
|
catch {
|
|
127
130
|
// Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
|
-
const url = generateSignOutUri({
|
|
133
|
+
const url = js.generateSignOutUri({
|
|
131
134
|
endSessionEndpoint,
|
|
132
135
|
postLogoutRedirectUri,
|
|
133
136
|
clientId,
|
|
@@ -144,8 +147,8 @@ class LogtoClient {
|
|
|
144
147
|
return null;
|
|
145
148
|
}
|
|
146
149
|
const item = JSON.parse(jsonItem);
|
|
147
|
-
if (!isLogtoSignInSessionItem(item)) {
|
|
148
|
-
throw new LogtoClientError('sign_in_session.invalid');
|
|
150
|
+
if (!index.isLogtoSignInSessionItem(item)) {
|
|
151
|
+
throw new errors.LogtoClientError('sign_in_session.invalid');
|
|
149
152
|
}
|
|
150
153
|
return item;
|
|
151
154
|
}
|
|
@@ -174,12 +177,12 @@ class LogtoClient {
|
|
|
174
177
|
async getAccessTokenByRefreshToken(resource) {
|
|
175
178
|
const currentRefreshToken = await this.getRefreshToken();
|
|
176
179
|
if (!currentRefreshToken) {
|
|
177
|
-
throw new LogtoClientError('not_authenticated');
|
|
180
|
+
throw new errors.LogtoClientError('not_authenticated');
|
|
178
181
|
}
|
|
179
|
-
const accessTokenKey = buildAccessTokenKey(resource);
|
|
182
|
+
const accessTokenKey = index$1.buildAccessTokenKey(resource);
|
|
180
183
|
const { appId: clientId } = this.logtoConfig;
|
|
181
184
|
const { tokenEndpoint } = await this.getOidcConfig();
|
|
182
|
-
const { accessToken, refreshToken, idToken, scope, expiresIn } = await fetchTokenByRefreshToken({
|
|
185
|
+
const { accessToken, refreshToken, idToken, scope, expiresIn } = await js.fetchTokenByRefreshToken({
|
|
183
186
|
clientId,
|
|
184
187
|
tokenEndpoint,
|
|
185
188
|
refreshToken: currentRefreshToken,
|
|
@@ -200,24 +203,24 @@ class LogtoClient {
|
|
|
200
203
|
}
|
|
201
204
|
async _getOidcConfig() {
|
|
202
205
|
const { endpoint } = this.logtoConfig;
|
|
203
|
-
const discoveryEndpoint = getDiscoveryEndpoint(endpoint);
|
|
204
|
-
return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);
|
|
206
|
+
const discoveryEndpoint = index$1.getDiscoveryEndpoint(endpoint);
|
|
207
|
+
return js.fetchOidcConfig(discoveryEndpoint, this.adapter.requester);
|
|
205
208
|
}
|
|
206
209
|
async _getJwtVerifyGetKey() {
|
|
207
210
|
const { jwksUri } = await this.getOidcConfig();
|
|
208
|
-
return createRemoteJWKSet(new URL(jwksUri));
|
|
211
|
+
return jose.createRemoteJWKSet(new URL(jwksUri));
|
|
209
212
|
}
|
|
210
213
|
async verifyIdToken(idToken) {
|
|
211
214
|
const { appId } = this.logtoConfig;
|
|
212
215
|
const { issuer } = await this.getOidcConfig();
|
|
213
216
|
const jwtVerifyGetKey = await this.getJwtVerifyGetKey();
|
|
214
|
-
await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);
|
|
217
|
+
await js.verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);
|
|
215
218
|
}
|
|
216
219
|
async saveCodeToken({ refreshToken, idToken, scope, accessToken, expiresIn, }) {
|
|
217
220
|
await this.setRefreshToken(refreshToken ?? null);
|
|
218
221
|
await this.setIdToken(idToken);
|
|
219
222
|
// NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)
|
|
220
|
-
const accessTokenKey = buildAccessTokenKey();
|
|
223
|
+
const accessTokenKey = index$1.buildAccessTokenKey();
|
|
221
224
|
const expiresAt = Date.now() / 1000 + expiresIn;
|
|
222
225
|
this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });
|
|
223
226
|
await this.saveAccessTokenMap();
|
|
@@ -237,7 +240,7 @@ class LogtoClient {
|
|
|
237
240
|
}
|
|
238
241
|
try {
|
|
239
242
|
const json = JSON.parse(raw);
|
|
240
|
-
if (!isLogtoAccessTokenMap(json)) {
|
|
243
|
+
if (!index.isLogtoAccessTokenMap(json)) {
|
|
241
244
|
return;
|
|
242
245
|
}
|
|
243
246
|
this.accessTokenMap.clear();
|
|
@@ -251,4 +254,32 @@ class LogtoClient {
|
|
|
251
254
|
}
|
|
252
255
|
}
|
|
253
256
|
|
|
254
|
-
|
|
257
|
+
Object.defineProperty(exports, 'LogtoError', {
|
|
258
|
+
enumerable: true,
|
|
259
|
+
get: function () { return js.LogtoError; }
|
|
260
|
+
});
|
|
261
|
+
Object.defineProperty(exports, 'LogtoRequestError', {
|
|
262
|
+
enumerable: true,
|
|
263
|
+
get: function () { return js.LogtoRequestError; }
|
|
264
|
+
});
|
|
265
|
+
Object.defineProperty(exports, 'OidcError', {
|
|
266
|
+
enumerable: true,
|
|
267
|
+
get: function () { return js.OidcError; }
|
|
268
|
+
});
|
|
269
|
+
Object.defineProperty(exports, 'Prompt', {
|
|
270
|
+
enumerable: true,
|
|
271
|
+
get: function () { return js.Prompt; }
|
|
272
|
+
});
|
|
273
|
+
Object.defineProperty(exports, 'ReservedScope', {
|
|
274
|
+
enumerable: true,
|
|
275
|
+
get: function () { return js.ReservedScope; }
|
|
276
|
+
});
|
|
277
|
+
Object.defineProperty(exports, 'UserScope', {
|
|
278
|
+
enumerable: true,
|
|
279
|
+
get: function () { return js.UserScope; }
|
|
280
|
+
});
|
|
281
|
+
exports.LogtoClientError = errors.LogtoClientError;
|
|
282
|
+
exports.isLogtoAccessTokenMap = index.isLogtoAccessTokenMap;
|
|
283
|
+
exports.isLogtoSignInSessionItem = index.isLogtoSignInSessionItem;
|
|
284
|
+
exports.createRequester = requester.createRequester;
|
|
285
|
+
exports.default = LogtoClient;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
import type { IdTokenClaims, UserInfoResponse, InteractionMode } from '@logto/js';
|
|
2
2
|
import type { Nullable } from '@silverhand/essentials';
|
|
3
|
-
import type { ClientAdapter } from './adapter';
|
|
4
|
-
import type { AccessToken, LogtoConfig, LogtoSignInSessionItem } from './types';
|
|
3
|
+
import type { ClientAdapter } from './adapter.js';
|
|
4
|
+
import type { AccessToken, LogtoConfig, LogtoSignInSessionItem } from './types/index.js';
|
|
5
5
|
export type { IdTokenClaims, LogtoErrorCode, UserInfoResponse, InteractionMode } from '@logto/js';
|
|
6
6
|
export { LogtoError, OidcError, Prompt, LogtoRequestError, ReservedScope, UserScope, } from '@logto/js';
|
|
7
|
-
export * from './errors';
|
|
8
|
-
export type { Storage, StorageKey, ClientAdapter } from './adapter';
|
|
9
|
-
export { createRequester } from './utils';
|
|
10
|
-
export * from './types';
|
|
7
|
+
export * from './errors.js';
|
|
8
|
+
export type { Storage, StorageKey, ClientAdapter } from './adapter.js';
|
|
9
|
+
export { createRequester } from './utils/index.js';
|
|
10
|
+
export * from './types/index.js';
|
|
11
11
|
export default class LogtoClient {
|
|
12
12
|
protected readonly logtoConfig: LogtoConfig;
|
|
13
|
-
protected readonly getOidcConfig:
|
|
14
|
-
|
|
15
|
-
token_endpoint: string;
|
|
16
|
-
userinfo_endpoint: string;
|
|
17
|
-
end_session_endpoint: string;
|
|
18
|
-
revocation_endpoint: string;
|
|
19
|
-
jwks_uri: string;
|
|
20
|
-
issuer: string;
|
|
21
|
-
}>>;
|
|
22
|
-
protected readonly getJwtVerifyGetKey: () => Promise<(protectedHeader?: import("jose").JWSHeaderParameters | undefined, token?: import("jose").FlattenedJWSInput | undefined) => Promise<import("jose").KeyLike>>;
|
|
13
|
+
protected readonly getOidcConfig: typeof this._getOidcConfig;
|
|
14
|
+
protected readonly getJwtVerifyGetKey: (...args: unknown[]) => Promise<(protectedHeader?: import("jose").JWSHeaderParameters | undefined, token?: import("jose").FlattenedJWSInput | undefined) => Promise<import("jose").KeyLike>>;
|
|
23
15
|
protected readonly adapter: ClientAdapter;
|
|
24
16
|
protected readonly accessTokenMap: Map<string, AccessToken>;
|
|
25
17
|
constructor(logtoConfig: LogtoConfig, adapter: ClientAdapter);
|
package/lib/index.js
CHANGED
|
@@ -1,28 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
var index = require('./types/index.js');
|
|
10
|
-
var index$1 = require('./utils/index.js');
|
|
11
|
-
var requester = require('./utils/requester.js');
|
|
12
|
-
|
|
13
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
-
|
|
15
|
-
var once__default = /*#__PURE__*/_interopDefault(once);
|
|
1
|
+
import { Prompt, withDefaultScopes, decodeIdToken, fetchUserInfo, generateSignInUri, verifyAndParseCodeFromCallbackUri, fetchTokenByAuthorizationCode, revoke, generateSignOutUri, fetchTokenByRefreshToken, fetchOidcConfig, verifyIdToken } from '@logto/js';
|
|
2
|
+
export { LogtoError, LogtoRequestError, OidcError, Prompt, ReservedScope, UserScope } from '@logto/js';
|
|
3
|
+
import { createRemoteJWKSet } from 'jose';
|
|
4
|
+
import { LogtoClientError } from './errors.js';
|
|
5
|
+
import { isLogtoSignInSessionItem, isLogtoAccessTokenMap } from './types/index.js';
|
|
6
|
+
import { buildAccessTokenKey, getDiscoveryEndpoint } from './utils/index.js';
|
|
7
|
+
import { once } from './utils/once.js';
|
|
8
|
+
export { createRequester } from './utils/requester.js';
|
|
16
9
|
|
|
17
10
|
class LogtoClient {
|
|
18
11
|
constructor(logtoConfig, adapter) {
|
|
19
|
-
this.getOidcConfig =
|
|
20
|
-
this.getJwtVerifyGetKey =
|
|
12
|
+
this.getOidcConfig = once(this._getOidcConfig);
|
|
13
|
+
this.getJwtVerifyGetKey = once(this._getJwtVerifyGetKey);
|
|
21
14
|
this.accessTokenMap = new Map();
|
|
22
15
|
this.logtoConfig = {
|
|
23
16
|
...logtoConfig,
|
|
24
|
-
prompt: logtoConfig.prompt ??
|
|
25
|
-
scopes:
|
|
17
|
+
prompt: logtoConfig.prompt ?? Prompt.Consent,
|
|
18
|
+
scopes: withDefaultScopes(logtoConfig.scopes).split(' '),
|
|
26
19
|
};
|
|
27
20
|
this.adapter = adapter;
|
|
28
21
|
void this.loadAccessTokenMap();
|
|
@@ -38,9 +31,9 @@ class LogtoClient {
|
|
|
38
31
|
}
|
|
39
32
|
async getAccessToken(resource) {
|
|
40
33
|
if (!(await this.getIdToken())) {
|
|
41
|
-
throw new
|
|
34
|
+
throw new LogtoClientError('not_authenticated');
|
|
42
35
|
}
|
|
43
|
-
const accessTokenKey =
|
|
36
|
+
const accessTokenKey = buildAccessTokenKey(resource);
|
|
44
37
|
const accessToken = this.accessTokenMap.get(accessTokenKey);
|
|
45
38
|
if (accessToken && accessToken.expiresAt > Date.now() / 1000) {
|
|
46
39
|
return accessToken.token;
|
|
@@ -57,17 +50,17 @@ class LogtoClient {
|
|
|
57
50
|
async getIdTokenClaims() {
|
|
58
51
|
const idToken = await this.getIdToken();
|
|
59
52
|
if (!idToken) {
|
|
60
|
-
throw new
|
|
53
|
+
throw new LogtoClientError('not_authenticated');
|
|
61
54
|
}
|
|
62
|
-
return
|
|
55
|
+
return decodeIdToken(idToken);
|
|
63
56
|
}
|
|
64
57
|
async fetchUserInfo() {
|
|
65
58
|
const { userinfoEndpoint } = await this.getOidcConfig();
|
|
66
59
|
const accessToken = await this.getAccessToken();
|
|
67
60
|
if (!accessToken) {
|
|
68
|
-
throw new
|
|
61
|
+
throw new LogtoClientError('fetch_user_info_failed');
|
|
69
62
|
}
|
|
70
|
-
return
|
|
63
|
+
return fetchUserInfo(userinfoEndpoint, accessToken, this.adapter.requester);
|
|
71
64
|
}
|
|
72
65
|
async signIn(redirectUri, interactionMode) {
|
|
73
66
|
const { appId: clientId, prompt, resources, scopes } = this.logtoConfig;
|
|
@@ -75,7 +68,7 @@ class LogtoClient {
|
|
|
75
68
|
const codeVerifier = this.adapter.generateCodeVerifier();
|
|
76
69
|
const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier);
|
|
77
70
|
const state = this.adapter.generateState();
|
|
78
|
-
const signInUri =
|
|
71
|
+
const signInUri = generateSignInUri({
|
|
79
72
|
authorizationEndpoint,
|
|
80
73
|
clientId,
|
|
81
74
|
redirectUri,
|
|
@@ -105,13 +98,13 @@ class LogtoClient {
|
|
|
105
98
|
const { requester } = adapter;
|
|
106
99
|
const signInSession = await this.getSignInSession();
|
|
107
100
|
if (!signInSession) {
|
|
108
|
-
throw new
|
|
101
|
+
throw new LogtoClientError('sign_in_session.not_found');
|
|
109
102
|
}
|
|
110
103
|
const { redirectUri, state, codeVerifier } = signInSession;
|
|
111
|
-
const code =
|
|
104
|
+
const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state);
|
|
112
105
|
const { appId: clientId } = logtoConfig;
|
|
113
106
|
const { tokenEndpoint } = await this.getOidcConfig();
|
|
114
|
-
const codeTokenResponse = await
|
|
107
|
+
const codeTokenResponse = await fetchTokenByAuthorizationCode({
|
|
115
108
|
clientId,
|
|
116
109
|
tokenEndpoint,
|
|
117
110
|
redirectUri,
|
|
@@ -128,13 +121,13 @@ class LogtoClient {
|
|
|
128
121
|
const refreshToken = await this.getRefreshToken();
|
|
129
122
|
if (refreshToken) {
|
|
130
123
|
try {
|
|
131
|
-
await
|
|
124
|
+
await revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester);
|
|
132
125
|
}
|
|
133
126
|
catch {
|
|
134
127
|
// Do nothing at this point, as we don't want to break the sign-out flow even if the revocation is failed
|
|
135
128
|
}
|
|
136
129
|
}
|
|
137
|
-
const url =
|
|
130
|
+
const url = generateSignOutUri({
|
|
138
131
|
endSessionEndpoint,
|
|
139
132
|
postLogoutRedirectUri,
|
|
140
133
|
clientId,
|
|
@@ -151,8 +144,8 @@ class LogtoClient {
|
|
|
151
144
|
return null;
|
|
152
145
|
}
|
|
153
146
|
const item = JSON.parse(jsonItem);
|
|
154
|
-
if (!
|
|
155
|
-
throw new
|
|
147
|
+
if (!isLogtoSignInSessionItem(item)) {
|
|
148
|
+
throw new LogtoClientError('sign_in_session.invalid');
|
|
156
149
|
}
|
|
157
150
|
return item;
|
|
158
151
|
}
|
|
@@ -181,12 +174,12 @@ class LogtoClient {
|
|
|
181
174
|
async getAccessTokenByRefreshToken(resource) {
|
|
182
175
|
const currentRefreshToken = await this.getRefreshToken();
|
|
183
176
|
if (!currentRefreshToken) {
|
|
184
|
-
throw new
|
|
177
|
+
throw new LogtoClientError('not_authenticated');
|
|
185
178
|
}
|
|
186
|
-
const accessTokenKey =
|
|
179
|
+
const accessTokenKey = buildAccessTokenKey(resource);
|
|
187
180
|
const { appId: clientId } = this.logtoConfig;
|
|
188
181
|
const { tokenEndpoint } = await this.getOidcConfig();
|
|
189
|
-
const { accessToken, refreshToken, idToken, scope, expiresIn } = await
|
|
182
|
+
const { accessToken, refreshToken, idToken, scope, expiresIn } = await fetchTokenByRefreshToken({
|
|
190
183
|
clientId,
|
|
191
184
|
tokenEndpoint,
|
|
192
185
|
refreshToken: currentRefreshToken,
|
|
@@ -207,24 +200,24 @@ class LogtoClient {
|
|
|
207
200
|
}
|
|
208
201
|
async _getOidcConfig() {
|
|
209
202
|
const { endpoint } = this.logtoConfig;
|
|
210
|
-
const discoveryEndpoint =
|
|
211
|
-
return
|
|
203
|
+
const discoveryEndpoint = getDiscoveryEndpoint(endpoint);
|
|
204
|
+
return fetchOidcConfig(discoveryEndpoint, this.adapter.requester);
|
|
212
205
|
}
|
|
213
206
|
async _getJwtVerifyGetKey() {
|
|
214
207
|
const { jwksUri } = await this.getOidcConfig();
|
|
215
|
-
return
|
|
208
|
+
return createRemoteJWKSet(new URL(jwksUri));
|
|
216
209
|
}
|
|
217
210
|
async verifyIdToken(idToken) {
|
|
218
211
|
const { appId } = this.logtoConfig;
|
|
219
212
|
const { issuer } = await this.getOidcConfig();
|
|
220
213
|
const jwtVerifyGetKey = await this.getJwtVerifyGetKey();
|
|
221
|
-
await
|
|
214
|
+
await verifyIdToken(idToken, appId, issuer, jwtVerifyGetKey);
|
|
222
215
|
}
|
|
223
216
|
async saveCodeToken({ refreshToken, idToken, scope, accessToken, expiresIn, }) {
|
|
224
217
|
await this.setRefreshToken(refreshToken ?? null);
|
|
225
218
|
await this.setIdToken(idToken);
|
|
226
219
|
// NOTE: Will add scope to accessTokenKey when needed. (Linear issue LOG-1589)
|
|
227
|
-
const accessTokenKey =
|
|
220
|
+
const accessTokenKey = buildAccessTokenKey();
|
|
228
221
|
const expiresAt = Date.now() / 1000 + expiresIn;
|
|
229
222
|
this.accessTokenMap.set(accessTokenKey, { token: accessToken, scope, expiresAt });
|
|
230
223
|
await this.saveAccessTokenMap();
|
|
@@ -244,7 +237,7 @@ class LogtoClient {
|
|
|
244
237
|
}
|
|
245
238
|
try {
|
|
246
239
|
const json = JSON.parse(raw);
|
|
247
|
-
if (!
|
|
240
|
+
if (!isLogtoAccessTokenMap(json)) {
|
|
248
241
|
return;
|
|
249
242
|
}
|
|
250
243
|
this.accessTokenMap.clear();
|
|
@@ -258,32 +251,4 @@ class LogtoClient {
|
|
|
258
251
|
}
|
|
259
252
|
}
|
|
260
253
|
|
|
261
|
-
|
|
262
|
-
enumerable: true,
|
|
263
|
-
get: function () { return js.LogtoError; }
|
|
264
|
-
});
|
|
265
|
-
Object.defineProperty(exports, 'LogtoRequestError', {
|
|
266
|
-
enumerable: true,
|
|
267
|
-
get: function () { return js.LogtoRequestError; }
|
|
268
|
-
});
|
|
269
|
-
Object.defineProperty(exports, 'OidcError', {
|
|
270
|
-
enumerable: true,
|
|
271
|
-
get: function () { return js.OidcError; }
|
|
272
|
-
});
|
|
273
|
-
Object.defineProperty(exports, 'Prompt', {
|
|
274
|
-
enumerable: true,
|
|
275
|
-
get: function () { return js.Prompt; }
|
|
276
|
-
});
|
|
277
|
-
Object.defineProperty(exports, 'ReservedScope', {
|
|
278
|
-
enumerable: true,
|
|
279
|
-
get: function () { return js.ReservedScope; }
|
|
280
|
-
});
|
|
281
|
-
Object.defineProperty(exports, 'UserScope', {
|
|
282
|
-
enumerable: true,
|
|
283
|
-
get: function () { return js.UserScope; }
|
|
284
|
-
});
|
|
285
|
-
exports.LogtoClientError = errors.LogtoClientError;
|
|
286
|
-
exports.isLogtoAccessTokenMap = index.isLogtoAccessTokenMap;
|
|
287
|
-
exports.isLogtoSignInSessionItem = index.isLogtoSignInSessionItem;
|
|
288
|
-
exports.createRequester = requester.createRequester;
|
|
289
|
-
exports.default = LogtoClient;
|
|
254
|
+
export { LogtoClientError, LogtoClient as default, isLogtoAccessTokenMap, isLogtoSignInSessionItem };
|
package/lib/mock.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/// <reference types="jest" />
|
|
2
2
|
import { Prompt } from '@logto/js';
|
|
3
3
|
import type { Nullable } from '@silverhand/essentials';
|
|
4
|
-
import type {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
4
|
+
import type { Storage } from './adapter.js';
|
|
5
|
+
import type { AccessToken, LogtoConfig, LogtoSignInSessionItem } from './index.js';
|
|
6
|
+
import LogtoClient from './index.js';
|
|
7
7
|
export declare const appId = "app_id_value";
|
|
8
8
|
export declare const endpoint = "https://logto.dev";
|
|
9
9
|
export declare class MockedStorage implements Storage {
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var js = require('@logto/js');
|
|
2
4
|
|
|
3
5
|
const isLogtoSignInSessionItem = (data) => {
|
|
4
|
-
if (!isArbitraryObject(data)) {
|
|
6
|
+
if (!js.isArbitraryObject(data)) {
|
|
5
7
|
return false;
|
|
6
8
|
}
|
|
7
9
|
return ['redirectUri', 'codeVerifier', 'state'].every((key) => typeof data[key] === 'string');
|
|
8
10
|
};
|
|
9
11
|
const isLogtoAccessTokenMap = (data) => {
|
|
10
|
-
if (!isArbitraryObject(data)) {
|
|
12
|
+
if (!js.isArbitraryObject(data)) {
|
|
11
13
|
return false;
|
|
12
14
|
}
|
|
13
15
|
return Object.values(data).every((value) => {
|
|
14
|
-
if (!isArbitraryObject(value)) {
|
|
16
|
+
if (!js.isArbitraryObject(value)) {
|
|
15
17
|
return false;
|
|
16
18
|
}
|
|
17
19
|
return (typeof value.token === 'string' &&
|
|
@@ -20,4 +22,5 @@ const isLogtoAccessTokenMap = (data) => {
|
|
|
20
22
|
});
|
|
21
23
|
};
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
exports.isLogtoAccessTokenMap = isLogtoAccessTokenMap;
|
|
26
|
+
exports.isLogtoSignInSessionItem = isLogtoSignInSessionItem;
|
package/lib/types/index.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var js = require('@logto/js');
|
|
1
|
+
import { isArbitraryObject } from '@logto/js';
|
|
4
2
|
|
|
5
3
|
const isLogtoSignInSessionItem = (data) => {
|
|
6
|
-
if (!
|
|
4
|
+
if (!isArbitraryObject(data)) {
|
|
7
5
|
return false;
|
|
8
6
|
}
|
|
9
7
|
return ['redirectUri', 'codeVerifier', 'state'].every((key) => typeof data[key] === 'string');
|
|
10
8
|
};
|
|
11
9
|
const isLogtoAccessTokenMap = (data) => {
|
|
12
|
-
if (!
|
|
10
|
+
if (!isArbitraryObject(data)) {
|
|
13
11
|
return false;
|
|
14
12
|
}
|
|
15
13
|
return Object.values(data).every((value) => {
|
|
16
|
-
if (!
|
|
14
|
+
if (!isArbitraryObject(value)) {
|
|
17
15
|
return false;
|
|
18
16
|
}
|
|
19
17
|
return (typeof value.token === 'string' &&
|
|
@@ -22,5 +20,4 @@ const isLogtoAccessTokenMap = (data) => {
|
|
|
22
20
|
});
|
|
23
21
|
};
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
exports.isLogtoSignInSessionItem = isLogtoSignInSessionItem;
|
|
23
|
+
export { isLogtoAccessTokenMap, isLogtoSignInSessionItem };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var js = require('@logto/js');
|
|
4
|
+
|
|
5
|
+
const buildAccessTokenKey = (resource = '', scopes = []) => `${scopes.slice().sort().join(' ')}@${resource}`;
|
|
6
|
+
const getDiscoveryEndpoint = (endpoint) => new URL(js.discoveryPath, endpoint).toString();
|
|
7
|
+
|
|
8
|
+
exports.buildAccessTokenKey = buildAccessTokenKey;
|
|
9
|
+
exports.getDiscoveryEndpoint = getDiscoveryEndpoint;
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var js = require('@logto/js');
|
|
1
|
+
import { discoveryPath } from '@logto/js';
|
|
4
2
|
|
|
5
3
|
const buildAccessTokenKey = (resource = '', scopes = []) => `${scopes.slice().sort().join(' ')}@${resource}`;
|
|
6
|
-
const getDiscoveryEndpoint = (endpoint) => new URL(
|
|
4
|
+
const getDiscoveryEndpoint = (endpoint) => new URL(discoveryPath, endpoint).toString();
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
exports.getDiscoveryEndpoint = getDiscoveryEndpoint;
|
|
6
|
+
export { buildAccessTokenKey, getDiscoveryEndpoint };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// TODO @sijie move to essentials
|
|
4
|
+
/* eslint-disable @silverhand/fp/no-let */
|
|
5
|
+
/* eslint-disable @silverhand/fp/no-mutation */
|
|
6
|
+
function once(function_) {
|
|
7
|
+
let called = false;
|
|
8
|
+
let result;
|
|
9
|
+
return function (...args) {
|
|
10
|
+
if (!called) {
|
|
11
|
+
called = true;
|
|
12
|
+
result = function_.apply(this, args);
|
|
13
|
+
}
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/* eslint-enable @silverhand/fp/no-mutation */
|
|
18
|
+
/* eslint-enable @silverhand/fp/no-let */
|
|
19
|
+
|
|
20
|
+
exports.once = once;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// TODO @sijie move to essentials
|
|
2
|
+
/* eslint-disable @silverhand/fp/no-let */
|
|
3
|
+
/* eslint-disable @silverhand/fp/no-mutation */
|
|
4
|
+
function once(function_) {
|
|
5
|
+
let called = false;
|
|
6
|
+
let result;
|
|
7
|
+
return function (...args) {
|
|
8
|
+
if (!called) {
|
|
9
|
+
called = true;
|
|
10
|
+
result = function_.apply(this, args);
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/* eslint-enable @silverhand/fp/no-mutation */
|
|
16
|
+
/* eslint-enable @silverhand/fp/no-let */
|
|
17
|
+
|
|
18
|
+
export { once };
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var js = require('@logto/js');
|
|
2
4
|
|
|
3
5
|
const createRequester = (fetchFunction) => {
|
|
4
6
|
return async (...args) => {
|
|
5
7
|
const response = await fetchFunction(...args);
|
|
6
8
|
if (!response.ok) {
|
|
7
9
|
const responseJson = await response.json();
|
|
8
|
-
if (!isLogtoRequestError(responseJson)) {
|
|
9
|
-
throw new LogtoError('unexpected_response_error', responseJson);
|
|
10
|
+
if (!js.isLogtoRequestError(responseJson)) {
|
|
11
|
+
throw new js.LogtoError('unexpected_response_error', responseJson);
|
|
10
12
|
}
|
|
11
13
|
// Expected request error from server
|
|
12
14
|
const { code, message } = responseJson;
|
|
13
|
-
throw new LogtoRequestError(code, message);
|
|
15
|
+
throw new js.LogtoRequestError(code, message);
|
|
14
16
|
}
|
|
15
17
|
return response.json();
|
|
16
18
|
};
|
|
17
19
|
};
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
exports.createRequester = createRequester;
|
package/lib/utils/requester.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var js = require('@logto/js');
|
|
1
|
+
import { isLogtoRequestError, LogtoError, LogtoRequestError } from '@logto/js';
|
|
4
2
|
|
|
5
3
|
const createRequester = (fetchFunction) => {
|
|
6
4
|
return async (...args) => {
|
|
7
5
|
const response = await fetchFunction(...args);
|
|
8
6
|
if (!response.ok) {
|
|
9
7
|
const responseJson = await response.json();
|
|
10
|
-
if (!
|
|
11
|
-
throw new
|
|
8
|
+
if (!isLogtoRequestError(responseJson)) {
|
|
9
|
+
throw new LogtoError('unexpected_response_error', responseJson);
|
|
12
10
|
}
|
|
13
11
|
// Expected request error from server
|
|
14
12
|
const { code, message } = responseJson;
|
|
15
|
-
throw new
|
|
13
|
+
throw new LogtoRequestError(code, message);
|
|
16
14
|
}
|
|
17
15
|
return response.json();
|
|
18
16
|
};
|
|
19
17
|
};
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
export { createRequester };
|
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logto/client",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"main": "./lib/index.
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./lib/index.cjs",
|
|
6
|
+
"module": "./lib/index.js",
|
|
7
|
+
"types": "./lib/index.d.ts",
|
|
6
8
|
"exports": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
+
"types": "./lib/index.d.ts",
|
|
10
|
+
"require": "./lib/index.cjs",
|
|
11
|
+
"import": "./lib/index.js",
|
|
12
|
+
"default": "./lib/index.js"
|
|
9
13
|
},
|
|
10
|
-
"module": "./lib/index.mjs",
|
|
11
|
-
"types": "./lib/index.d.ts",
|
|
12
14
|
"files": [
|
|
13
15
|
"lib"
|
|
14
16
|
],
|
|
@@ -18,33 +20,18 @@
|
|
|
18
20
|
"url": "https://github.com/logto-io/js.git",
|
|
19
21
|
"directory": "packages/client"
|
|
20
22
|
},
|
|
21
|
-
"scripts": {
|
|
22
|
-
"dev:tsc": "tsc -p tsconfig.build.json -w --preserveWatchOutput",
|
|
23
|
-
"precommit": "lint-staged",
|
|
24
|
-
"check": "tsc --noEmit",
|
|
25
|
-
"build": "rm -rf lib/ && tsc -p tsconfig.build.json --noEmit && rollup -c",
|
|
26
|
-
"lint": "eslint --ext .ts src",
|
|
27
|
-
"test": "jest",
|
|
28
|
-
"test:coverage": "jest --silent --env=jsdom && jest --silent --coverage",
|
|
29
|
-
"prepack": "pnpm test"
|
|
30
|
-
},
|
|
31
23
|
"dependencies": {
|
|
32
|
-
"@logto/js": "^
|
|
33
|
-
"@silverhand/essentials": "^2.6.
|
|
24
|
+
"@logto/js": "^2.0.0",
|
|
25
|
+
"@silverhand/essentials": "^2.6.2",
|
|
34
26
|
"camelcase-keys": "^7.0.1",
|
|
35
|
-
"jose": "^4.13.2"
|
|
36
|
-
"lodash.get": "^4.4.2",
|
|
37
|
-
"lodash.once": "^4.1.1"
|
|
27
|
+
"jose": "^4.13.2"
|
|
38
28
|
},
|
|
39
29
|
"devDependencies": {
|
|
40
|
-
"@
|
|
41
|
-
"@silverhand/
|
|
42
|
-
"@silverhand/ts-config": "^1.0.0",
|
|
30
|
+
"@silverhand/eslint-config": "^3.0.1",
|
|
31
|
+
"@silverhand/ts-config": "^3.0.0",
|
|
43
32
|
"@swc/core": "^1.3.50",
|
|
44
33
|
"@swc/jest": "^0.2.24",
|
|
45
34
|
"@types/jest": "^29.5.0",
|
|
46
|
-
"@types/lodash.get": "^4.4.6",
|
|
47
|
-
"@types/lodash.once": "^4.1.7",
|
|
48
35
|
"@types/node": "^18.0.0",
|
|
49
36
|
"eslint": "^8.38.0",
|
|
50
37
|
"jest": "^29.5.0",
|
|
@@ -63,5 +50,13 @@
|
|
|
63
50
|
"publishConfig": {
|
|
64
51
|
"access": "public"
|
|
65
52
|
},
|
|
66
|
-
"
|
|
67
|
-
|
|
53
|
+
"scripts": {
|
|
54
|
+
"dev:tsc": "tsc -p tsconfig.build.json -w --preserveWatchOutput",
|
|
55
|
+
"precommit": "lint-staged",
|
|
56
|
+
"check": "tsc --noEmit",
|
|
57
|
+
"build": "rm -rf lib/ && tsc -p tsconfig.build.json --noEmit && rollup -c",
|
|
58
|
+
"lint": "eslint --ext .ts src",
|
|
59
|
+
"test": "jest",
|
|
60
|
+
"test:coverage": "jest --silent --env=jsdom && jest --silent --coverage"
|
|
61
|
+
}
|
|
62
|
+
}
|
package/lib/errors.mjs
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import get from 'lodash.get';
|
|
2
|
-
|
|
3
|
-
const logtoClientErrorCodes = Object.freeze({
|
|
4
|
-
sign_in_session: {
|
|
5
|
-
invalid: 'Invalid sign-in session.',
|
|
6
|
-
not_found: 'Sign-in session not found.',
|
|
7
|
-
},
|
|
8
|
-
not_authenticated: 'Not authenticated.',
|
|
9
|
-
fetch_user_info_failed: 'Unable to fetch user info. The access token may be invalid.',
|
|
10
|
-
});
|
|
11
|
-
const getMessageByErrorCode = (errorCode) => {
|
|
12
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
13
|
-
const message = get(logtoClientErrorCodes, errorCode);
|
|
14
|
-
if (typeof message === 'string') {
|
|
15
|
-
return message;
|
|
16
|
-
}
|
|
17
|
-
return errorCode;
|
|
18
|
-
};
|
|
19
|
-
class LogtoClientError extends Error {
|
|
20
|
-
constructor(code, data) {
|
|
21
|
-
super(getMessageByErrorCode(code));
|
|
22
|
-
this.code = code;
|
|
23
|
-
this.data = data;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export { LogtoClientError };
|
package/lib/utils/index.mjs
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { discoveryPath } from '@logto/js';
|
|
2
|
-
|
|
3
|
-
const buildAccessTokenKey = (resource = '', scopes = []) => `${scopes.slice().sort().join(' ')}@${resource}`;
|
|
4
|
-
const getDiscoveryEndpoint = (endpoint) => new URL(discoveryPath, endpoint).toString();
|
|
5
|
-
|
|
6
|
-
export { buildAccessTokenKey, getDiscoveryEndpoint };
|