@logto/js 4.2.0 → 5.0.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/lib/core/sign-in.d.ts +1 -1
- package/lib/types/index.d.ts +0 -2
- package/lib/utils/angular.d.ts +36 -0
- package/lib/utils/angular.js +11 -3
- package/package.json +9 -11
- package/lib/consts/index.cjs +0 -78
- package/lib/consts/openid.cjs +0 -155
- package/lib/core/fetch-token.cjs +0 -57
- package/lib/core/oidc-config.cjs +0 -13
- package/lib/core/revoke.cjs +0 -14
- package/lib/core/sign-in.cjs +0 -56
- package/lib/core/sign-out.cjs +0 -13
- package/lib/core/user-info.cjs +0 -7
- package/lib/index.cjs +0 -72
- package/lib/utils/access-token.cjs +0 -40
- package/lib/utils/angular.cjs +0 -58
- package/lib/utils/arbitrary-object.cjs +0 -5
- package/lib/utils/callback-uri.cjs +0 -36
- package/lib/utils/errors.cjs +0 -58
- package/lib/utils/id-token.cjs +0 -54
- package/lib/utils/scopes.cjs +0 -23
package/lib/core/sign-in.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export type SignInUriParameters = {
|
|
|
27
27
|
*/
|
|
28
28
|
firstScreen?: FirstScreen;
|
|
29
29
|
/**
|
|
30
|
-
* Specifies identifiers used in the identifier sign-in
|
|
30
|
+
* Specifies identifiers used in the identifier sign-in, identifier register, and reset password pages.
|
|
31
31
|
*
|
|
32
32
|
* Available values: `email`, `phone`, `username`.
|
|
33
33
|
*
|
package/lib/types/index.d.ts
CHANGED
|
@@ -22,7 +22,5 @@ export type InteractionMode = 'signIn' | 'signUp';
|
|
|
22
22
|
* standard, but a Logto-specific extension.
|
|
23
23
|
*
|
|
24
24
|
* Note: `signIn` is deprecated, use `sign_in` instead
|
|
25
|
-
*
|
|
26
|
-
* @experimental Don't use this type as it's under development.
|
|
27
25
|
*/
|
|
28
26
|
export type FirstScreen = 'signIn' | 'sign_in' | 'register' | 'reset_password' | 'identifier:sign_in' | 'identifier:register' | 'single_sign_on';
|
package/lib/utils/angular.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type OpenIdConfiguration } from 'angular-auth-oidc-client';
|
|
2
2
|
import { Prompt } from '../consts/index.js';
|
|
3
|
+
import { type SignInUriParameters } from '../index.js';
|
|
3
4
|
/** The Logto configuration object for Angular apps. */
|
|
4
5
|
export type LogtoAngularConfig = {
|
|
5
6
|
/**
|
|
@@ -48,6 +49,41 @@ export type LogtoAngularConfig = {
|
|
|
48
49
|
* @default true
|
|
49
50
|
*/
|
|
50
51
|
includeReservedScopes?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Login hint indicates the current user (usually an email address or a phone number).
|
|
54
|
+
*
|
|
55
|
+
* @link SignInUriParameters.loginHint
|
|
56
|
+
*/
|
|
57
|
+
loginHint?: SignInUriParameters['loginHint'];
|
|
58
|
+
/**
|
|
59
|
+
* The first screen to be shown in the sign-in experience.
|
|
60
|
+
*
|
|
61
|
+
* @link SignInUriParameters.firstScreen
|
|
62
|
+
*/
|
|
63
|
+
firstScreen?: SignInUriParameters['firstScreen'];
|
|
64
|
+
/**
|
|
65
|
+
* Identifiers used in the identifier sign-in, identifier register or reset password pages.
|
|
66
|
+
*
|
|
67
|
+
* Note: This parameter is applicable only when the `firstScreen` is set to either`identifierSignIn`
|
|
68
|
+
* or `identifierRegister`.
|
|
69
|
+
*
|
|
70
|
+
* @link SignInUriParameters.identifiers
|
|
71
|
+
*/
|
|
72
|
+
identifiers?: SignInUriParameters['identifiers'];
|
|
73
|
+
/**
|
|
74
|
+
* Direct sign-in options.
|
|
75
|
+
*
|
|
76
|
+
* @link SignInUriParameters.directSignIn
|
|
77
|
+
*/
|
|
78
|
+
directSignIn?: SignInUriParameters['directSignIn'];
|
|
79
|
+
/**
|
|
80
|
+
* Extra parameters to be appended to the sign-in URI.
|
|
81
|
+
*
|
|
82
|
+
* Note: The parameters should be supported by the authorization server.
|
|
83
|
+
*
|
|
84
|
+
* @link SignInUriParameters.extraParams
|
|
85
|
+
*/
|
|
86
|
+
extraParams?: SignInUriParameters['extraParams'];
|
|
51
87
|
};
|
|
52
88
|
/**
|
|
53
89
|
* A helper function to build the OpenID Connect configuration for `angular-auth-oidc-client`
|
package/lib/utils/angular.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { conditional } from '@silverhand/essentials';
|
|
2
|
+
import { Prompt, QueryKey } from '../consts/index.js';
|
|
2
3
|
import { withReservedScopes } from './scopes.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -26,9 +27,16 @@ import { withReservedScopes } from './scopes.js';
|
|
|
26
27
|
* about how to use the library.
|
|
27
28
|
*/
|
|
28
29
|
const buildAngularAuthConfig = (logtoConfig) => {
|
|
29
|
-
const { endpoint, appId: clientId, scopes, resource, redirectUri: redirectUrl, postLogoutRedirectUri, prompt = Prompt.Consent, includeReservedScopes = true, } = logtoConfig;
|
|
30
|
+
const { endpoint, appId: clientId, scopes, resource, redirectUri: redirectUrl, postLogoutRedirectUri, prompt = Prompt.Consent, includeReservedScopes = true, loginHint, identifiers, firstScreen, directSignIn, extraParams, } = logtoConfig;
|
|
30
31
|
const scope = includeReservedScopes ? withReservedScopes(scopes) : scopes?.join(' ');
|
|
31
|
-
const customParameters =
|
|
32
|
+
const customParameters = {
|
|
33
|
+
...conditional(resource && { [QueryKey.Resource]: resource }),
|
|
34
|
+
...conditional(loginHint && { [QueryKey.LoginHint]: loginHint }),
|
|
35
|
+
...conditional(firstScreen && { [QueryKey.FirstScreen]: firstScreen }),
|
|
36
|
+
...conditional(identifiers && { [QueryKey.Identifier]: identifiers.join(' ') }),
|
|
37
|
+
...conditional(directSignIn && { [QueryKey.DirectSignIn]: `${directSignIn.method}:${directSignIn.target}` }),
|
|
38
|
+
...extraParams,
|
|
39
|
+
};
|
|
32
40
|
return {
|
|
33
41
|
authority: new URL('/oidc', endpoint).href,
|
|
34
42
|
redirectUrl,
|
package/package.json
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logto/js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.3",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "./lib/index.cjs",
|
|
6
5
|
"module": "./lib/index.js",
|
|
7
6
|
"types": "./lib/index.d.ts",
|
|
8
7
|
"exports": {
|
|
9
8
|
"types": "./lib/index.d.ts",
|
|
10
|
-
"require": "./lib/index.cjs",
|
|
11
9
|
"import": "./lib/index.js"
|
|
12
10
|
},
|
|
13
11
|
"files": [
|
|
@@ -20,23 +18,23 @@
|
|
|
20
18
|
"directory": "packages/js"
|
|
21
19
|
},
|
|
22
20
|
"dependencies": {
|
|
23
|
-
"@silverhand/essentials": "^2.
|
|
24
|
-
"camelcase-keys": "^
|
|
21
|
+
"@silverhand/essentials": "^2.9.2",
|
|
22
|
+
"camelcase-keys": "^9.1.3"
|
|
25
23
|
},
|
|
26
24
|
"devDependencies": {
|
|
27
25
|
"@silverhand/eslint-config": "^6.0.1",
|
|
28
26
|
"@silverhand/ts-config": "^6.0.0",
|
|
29
|
-
"@types/node": "^
|
|
30
|
-
"@vitest/coverage-v8": "^1.
|
|
31
|
-
"angular-auth-oidc-client": "^
|
|
27
|
+
"@types/node": "^22.0.0",
|
|
28
|
+
"@vitest/coverage-v8": "^2.1.9",
|
|
29
|
+
"angular-auth-oidc-client": "^19.0.0",
|
|
32
30
|
"eslint": "^8.57.0",
|
|
33
|
-
"happy-dom": "^
|
|
31
|
+
"happy-dom": "^16.0.0",
|
|
34
32
|
"jose": "^5.2.2",
|
|
35
33
|
"lint-staged": "^15.0.0",
|
|
36
34
|
"prettier": "^3.0.0",
|
|
37
|
-
"rollup": "^4.
|
|
35
|
+
"rollup": "^4.22.4",
|
|
38
36
|
"typescript": "^5.3.3",
|
|
39
|
-
"vitest": "^1.
|
|
37
|
+
"vitest": "^2.1.9"
|
|
40
38
|
},
|
|
41
39
|
"eslintConfig": {
|
|
42
40
|
"extends": "@silverhand"
|
package/lib/consts/index.cjs
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var openid = require('./openid.cjs');
|
|
4
|
-
|
|
5
|
-
const ContentType = {
|
|
6
|
-
formUrlEncoded: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
7
|
-
};
|
|
8
|
-
exports.TokenGrantType = void 0;
|
|
9
|
-
(function (TokenGrantType) {
|
|
10
|
-
TokenGrantType["AuthorizationCode"] = "authorization_code";
|
|
11
|
-
TokenGrantType["RefreshToken"] = "refresh_token";
|
|
12
|
-
})(exports.TokenGrantType || (exports.TokenGrantType = {}));
|
|
13
|
-
exports.QueryKey = void 0;
|
|
14
|
-
(function (QueryKey) {
|
|
15
|
-
QueryKey["ClientId"] = "client_id";
|
|
16
|
-
QueryKey["Code"] = "code";
|
|
17
|
-
QueryKey["CodeChallenge"] = "code_challenge";
|
|
18
|
-
QueryKey["CodeChallengeMethod"] = "code_challenge_method";
|
|
19
|
-
QueryKey["CodeVerifier"] = "code_verifier";
|
|
20
|
-
QueryKey["Error"] = "error";
|
|
21
|
-
QueryKey["ErrorDescription"] = "error_description";
|
|
22
|
-
QueryKey["GrantType"] = "grant_type";
|
|
23
|
-
QueryKey["IdToken"] = "id_token";
|
|
24
|
-
QueryKey["IdTokenHint"] = "id_token_hint";
|
|
25
|
-
QueryKey["LoginHint"] = "login_hint";
|
|
26
|
-
QueryKey["PostLogoutRedirectUri"] = "post_logout_redirect_uri";
|
|
27
|
-
QueryKey["Prompt"] = "prompt";
|
|
28
|
-
QueryKey["RedirectUri"] = "redirect_uri";
|
|
29
|
-
QueryKey["RefreshToken"] = "refresh_token";
|
|
30
|
-
QueryKey["Resource"] = "resource";
|
|
31
|
-
QueryKey["ResponseType"] = "response_type";
|
|
32
|
-
QueryKey["Scope"] = "scope";
|
|
33
|
-
QueryKey["State"] = "state";
|
|
34
|
-
QueryKey["Token"] = "token";
|
|
35
|
-
// Need to align with the OIDC extraParams settings in core
|
|
36
|
-
QueryKey["InteractionMode"] = "interaction_mode";
|
|
37
|
-
/** The query key for specifying the organization ID. */
|
|
38
|
-
QueryKey["OrganizationId"] = "organization_id";
|
|
39
|
-
QueryKey["FirstScreen"] = "first_screen";
|
|
40
|
-
QueryKey["Identifier"] = "identifier";
|
|
41
|
-
QueryKey["DirectSignIn"] = "direct_sign_in";
|
|
42
|
-
})(exports.QueryKey || (exports.QueryKey = {}));
|
|
43
|
-
/** The prompt parameter to be used for the authorization request. */
|
|
44
|
-
exports.Prompt = void 0;
|
|
45
|
-
(function (Prompt) {
|
|
46
|
-
Prompt["None"] = "none";
|
|
47
|
-
/**
|
|
48
|
-
* The Authorization Server MUST prompt the End-User for consent
|
|
49
|
-
* before returning information to the Client.
|
|
50
|
-
*/
|
|
51
|
-
Prompt["Consent"] = "consent";
|
|
52
|
-
/**
|
|
53
|
-
* The Authorization Server MUST prompt the End-User for re-authentication,
|
|
54
|
-
* forcing the user to log in again. Note the there'll be no Refresh Token
|
|
55
|
-
* returned in this case.
|
|
56
|
-
*/
|
|
57
|
-
Prompt["Login"] = "login";
|
|
58
|
-
})(exports.Prompt || (exports.Prompt = {}));
|
|
59
|
-
|
|
60
|
-
Object.defineProperty(exports, "ReservedResource", {
|
|
61
|
-
enumerable: true,
|
|
62
|
-
get: function () { return openid.ReservedResource; }
|
|
63
|
-
});
|
|
64
|
-
Object.defineProperty(exports, "ReservedScope", {
|
|
65
|
-
enumerable: true,
|
|
66
|
-
get: function () { return openid.ReservedScope; }
|
|
67
|
-
});
|
|
68
|
-
Object.defineProperty(exports, "UserScope", {
|
|
69
|
-
enumerable: true,
|
|
70
|
-
get: function () { return openid.UserScope; }
|
|
71
|
-
});
|
|
72
|
-
exports.buildOrganizationUrn = openid.buildOrganizationUrn;
|
|
73
|
-
exports.getOrganizationIdFromUrn = openid.getOrganizationIdFromUrn;
|
|
74
|
-
exports.idTokenClaims = openid.idTokenClaims;
|
|
75
|
-
exports.organizationUrnPrefix = openid.organizationUrnPrefix;
|
|
76
|
-
exports.userClaims = openid.userClaims;
|
|
77
|
-
exports.userinfoClaims = openid.userinfoClaims;
|
|
78
|
-
exports.ContentType = ContentType;
|
package/lib/consts/openid.cjs
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @overview Constants for Logto. Synchronized with `@logto/core-kit` package at hash `081094d`.
|
|
5
|
-
*/
|
|
6
|
-
/** Scopes that reserved by Logto, which will be added to the auth request automatically. */
|
|
7
|
-
exports.ReservedScope = void 0;
|
|
8
|
-
(function (ReservedScope) {
|
|
9
|
-
ReservedScope["OpenId"] = "openid";
|
|
10
|
-
ReservedScope["OfflineAccess"] = "offline_access";
|
|
11
|
-
})(exports.ReservedScope || (exports.ReservedScope = {}));
|
|
12
|
-
/** Resources that reserved by Logto, which cannot be defined by users. */
|
|
13
|
-
exports.ReservedResource = void 0;
|
|
14
|
-
(function (ReservedResource) {
|
|
15
|
-
/**
|
|
16
|
-
* The resource for organization template per RFC 0001.
|
|
17
|
-
*
|
|
18
|
-
* @see {@link https://github.com/logto-io/rfcs | RFC 0001} for more details.
|
|
19
|
-
*/
|
|
20
|
-
ReservedResource["Organization"] = "urn:logto:resource:organizations";
|
|
21
|
-
})(exports.ReservedResource || (exports.ReservedResource = {}));
|
|
22
|
-
/**
|
|
23
|
-
* Scopes for ID Token and Userinfo Endpoint.
|
|
24
|
-
*/
|
|
25
|
-
exports.UserScope = void 0;
|
|
26
|
-
(function (UserScope) {
|
|
27
|
-
/**
|
|
28
|
-
* Scope for basic user info.
|
|
29
|
-
*
|
|
30
|
-
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
31
|
-
*/
|
|
32
|
-
UserScope["Profile"] = "profile";
|
|
33
|
-
/**
|
|
34
|
-
* Scope for user email address.
|
|
35
|
-
*
|
|
36
|
-
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
37
|
-
*/
|
|
38
|
-
UserScope["Email"] = "email";
|
|
39
|
-
/**
|
|
40
|
-
* Scope for user phone number.
|
|
41
|
-
*
|
|
42
|
-
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
43
|
-
*/
|
|
44
|
-
UserScope["Phone"] = "phone";
|
|
45
|
-
/**
|
|
46
|
-
* Scope for user's custom data.
|
|
47
|
-
*
|
|
48
|
-
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
49
|
-
*/
|
|
50
|
-
UserScope["CustomData"] = "custom_data";
|
|
51
|
-
/**
|
|
52
|
-
* Scope for user's social identity details.
|
|
53
|
-
*
|
|
54
|
-
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
55
|
-
*/
|
|
56
|
-
UserScope["Identities"] = "identities";
|
|
57
|
-
/**
|
|
58
|
-
* Scope for user's roles.
|
|
59
|
-
*
|
|
60
|
-
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
61
|
-
*/
|
|
62
|
-
UserScope["Roles"] = "roles";
|
|
63
|
-
/**
|
|
64
|
-
* Scope for user's organization IDs and perform organization token grant per [RFC 0001](https://github.com/logto-io/rfcs).
|
|
65
|
-
*
|
|
66
|
-
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
67
|
-
*/
|
|
68
|
-
UserScope["Organizations"] = "urn:logto:scope:organizations";
|
|
69
|
-
/**
|
|
70
|
-
* Scope for user's organization roles per [RFC 0001](https://github.com/logto-io/rfcs).
|
|
71
|
-
*
|
|
72
|
-
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
73
|
-
*/
|
|
74
|
-
UserScope["OrganizationRoles"] = "urn:logto:scope:organization_roles";
|
|
75
|
-
})(exports.UserScope || (exports.UserScope = {}));
|
|
76
|
-
/**
|
|
77
|
-
* Mapped claims that ID Token includes.
|
|
78
|
-
*/
|
|
79
|
-
const idTokenClaims = Object.freeze({
|
|
80
|
-
[exports.UserScope.Profile]: ['name', 'picture', 'username'],
|
|
81
|
-
[exports.UserScope.Email]: ['email', 'email_verified'],
|
|
82
|
-
[exports.UserScope.Phone]: ['phone_number', 'phone_number_verified'],
|
|
83
|
-
[exports.UserScope.Roles]: ['roles'],
|
|
84
|
-
[exports.UserScope.Organizations]: ['organizations'],
|
|
85
|
-
[exports.UserScope.OrganizationRoles]: ['organization_roles'],
|
|
86
|
-
[exports.UserScope.CustomData]: [],
|
|
87
|
-
[exports.UserScope.Identities]: [],
|
|
88
|
-
});
|
|
89
|
-
/**
|
|
90
|
-
* Additional claims that Userinfo Endpoint returns.
|
|
91
|
-
*/
|
|
92
|
-
const userinfoClaims = Object.freeze({
|
|
93
|
-
[exports.UserScope.Profile]: [],
|
|
94
|
-
[exports.UserScope.Email]: [],
|
|
95
|
-
[exports.UserScope.Phone]: [],
|
|
96
|
-
[exports.UserScope.Roles]: [],
|
|
97
|
-
[exports.UserScope.Organizations]: [],
|
|
98
|
-
[exports.UserScope.OrganizationRoles]: [],
|
|
99
|
-
[exports.UserScope.CustomData]: ['custom_data'],
|
|
100
|
-
[exports.UserScope.Identities]: ['identities'],
|
|
101
|
-
});
|
|
102
|
-
const userClaims = Object.freeze(
|
|
103
|
-
// Hard to infer type directly, use `as` for a workaround.
|
|
104
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
105
|
-
Object.fromEntries(Object.values(exports.UserScope).map((current) => [
|
|
106
|
-
current,
|
|
107
|
-
[...idTokenClaims[current], ...userinfoClaims[current]],
|
|
108
|
-
])));
|
|
109
|
-
/**
|
|
110
|
-
* The prefix of the URN (Uniform Resource Name) for the organization in Logto.
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```
|
|
114
|
-
* urn:logto:organization:123 // organization with ID 123
|
|
115
|
-
* ```
|
|
116
|
-
* @see {@link https://en.wikipedia.org/wiki/Uniform_Resource_Name | Uniform Resource Name}
|
|
117
|
-
*/
|
|
118
|
-
const organizationUrnPrefix = 'urn:logto:organization:';
|
|
119
|
-
/**
|
|
120
|
-
* Build the URN (Uniform Resource Name) for the organization in Logto.
|
|
121
|
-
*
|
|
122
|
-
* @param organizationId The ID of the organization.
|
|
123
|
-
* @returns The URN for the organization.
|
|
124
|
-
* @see {@link organizationUrnPrefix} for the prefix of the URN.
|
|
125
|
-
* @example
|
|
126
|
-
* ```ts
|
|
127
|
-
* buildOrganizationUrn('1') // returns 'urn:logto:organization:1'
|
|
128
|
-
* ```
|
|
129
|
-
*/
|
|
130
|
-
const buildOrganizationUrn = (organizationId) => `${organizationUrnPrefix}${organizationId}`;
|
|
131
|
-
/**
|
|
132
|
-
* Get the organization ID from the URN (Uniform Resource Name) for the organization in Logto.
|
|
133
|
-
*
|
|
134
|
-
* @param urn The URN for the organization. Must start with {@link organizationUrnPrefix}.
|
|
135
|
-
* @returns The ID of the organization.
|
|
136
|
-
* @throws {TypeError} If the URN is invalid.
|
|
137
|
-
* @example
|
|
138
|
-
* ```ts
|
|
139
|
-
* getOrganizationIdFromUrn('1') // throws TypeError
|
|
140
|
-
* getOrganizationIdFromUrn('urn:logto:organization:1') // returns '1'
|
|
141
|
-
* ```
|
|
142
|
-
*/
|
|
143
|
-
const getOrganizationIdFromUrn = (urn) => {
|
|
144
|
-
if (!urn.startsWith(organizationUrnPrefix)) {
|
|
145
|
-
throw new TypeError('Invalid organization URN.');
|
|
146
|
-
}
|
|
147
|
-
return urn.slice(organizationUrnPrefix.length);
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
exports.buildOrganizationUrn = buildOrganizationUrn;
|
|
151
|
-
exports.getOrganizationIdFromUrn = getOrganizationIdFromUrn;
|
|
152
|
-
exports.idTokenClaims = idTokenClaims;
|
|
153
|
-
exports.organizationUrnPrefix = organizationUrnPrefix;
|
|
154
|
-
exports.userClaims = userClaims;
|
|
155
|
-
exports.userinfoClaims = userinfoClaims;
|
package/lib/core/fetch-token.cjs
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var camelcaseKeys = require('camelcase-keys');
|
|
4
|
-
var index = require('../consts/index.cjs');
|
|
5
|
-
|
|
6
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
-
|
|
8
|
-
var camelcaseKeys__default = /*#__PURE__*/_interopDefault(camelcaseKeys);
|
|
9
|
-
|
|
10
|
-
const fetchTokenByAuthorizationCode = async ({ clientId, tokenEndpoint, redirectUri, codeVerifier, code, resource, }, requester) => {
|
|
11
|
-
const parameters = new URLSearchParams();
|
|
12
|
-
parameters.append(index.QueryKey.ClientId, clientId);
|
|
13
|
-
parameters.append(index.QueryKey.Code, code);
|
|
14
|
-
parameters.append(index.QueryKey.CodeVerifier, codeVerifier);
|
|
15
|
-
parameters.append(index.QueryKey.RedirectUri, redirectUri);
|
|
16
|
-
parameters.append(index.QueryKey.GrantType, index.TokenGrantType.AuthorizationCode);
|
|
17
|
-
if (resource) {
|
|
18
|
-
parameters.append(index.QueryKey.Resource, resource);
|
|
19
|
-
}
|
|
20
|
-
const snakeCaseCodeTokenResponse = await requester(tokenEndpoint, {
|
|
21
|
-
method: 'POST',
|
|
22
|
-
headers: index.ContentType.formUrlEncoded,
|
|
23
|
-
body: parameters.toString(),
|
|
24
|
-
});
|
|
25
|
-
return camelcaseKeys__default.default(snakeCaseCodeTokenResponse);
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Fetch access token by refresh token using the token endpoint and `refresh_token` grant type.
|
|
29
|
-
* @param params The parameters for fetching access token.
|
|
30
|
-
* @param requester The requester for sending HTTP request.
|
|
31
|
-
* @returns A Promise that resolves to the access token response.
|
|
32
|
-
*/
|
|
33
|
-
const fetchTokenByRefreshToken = async (params, requester) => {
|
|
34
|
-
const { clientId, tokenEndpoint, refreshToken, resource, organizationId, scopes } = params;
|
|
35
|
-
const parameters = new URLSearchParams();
|
|
36
|
-
parameters.append(index.QueryKey.ClientId, clientId);
|
|
37
|
-
parameters.append(index.QueryKey.RefreshToken, refreshToken);
|
|
38
|
-
parameters.append(index.QueryKey.GrantType, index.TokenGrantType.RefreshToken);
|
|
39
|
-
if (resource) {
|
|
40
|
-
parameters.append(index.QueryKey.Resource, resource);
|
|
41
|
-
}
|
|
42
|
-
if (organizationId) {
|
|
43
|
-
parameters.append(index.QueryKey.OrganizationId, organizationId);
|
|
44
|
-
}
|
|
45
|
-
if (scopes?.length) {
|
|
46
|
-
parameters.append(index.QueryKey.Scope, scopes.join(' '));
|
|
47
|
-
}
|
|
48
|
-
const snakeCaseRefreshTokenTokenResponse = await requester(tokenEndpoint, {
|
|
49
|
-
method: 'POST',
|
|
50
|
-
headers: index.ContentType.formUrlEncoded,
|
|
51
|
-
body: parameters.toString(),
|
|
52
|
-
});
|
|
53
|
-
return camelcaseKeys__default.default(snakeCaseRefreshTokenTokenResponse);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
exports.fetchTokenByAuthorizationCode = fetchTokenByAuthorizationCode;
|
|
57
|
-
exports.fetchTokenByRefreshToken = fetchTokenByRefreshToken;
|
package/lib/core/oidc-config.cjs
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var camelcaseKeys = require('camelcase-keys');
|
|
4
|
-
|
|
5
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
-
|
|
7
|
-
var camelcaseKeys__default = /*#__PURE__*/_interopDefault(camelcaseKeys);
|
|
8
|
-
|
|
9
|
-
const discoveryPath = '/oidc/.well-known/openid-configuration';
|
|
10
|
-
const fetchOidcConfig = async (endpoint, requester) => camelcaseKeys__default.default(await requester(endpoint));
|
|
11
|
-
|
|
12
|
-
exports.discoveryPath = discoveryPath;
|
|
13
|
-
exports.fetchOidcConfig = fetchOidcConfig;
|
package/lib/core/revoke.cjs
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var index = require('../consts/index.cjs');
|
|
4
|
-
|
|
5
|
-
const revoke = async (revocationEndpoint, clientId, token, requester) => requester(revocationEndpoint, {
|
|
6
|
-
method: 'POST',
|
|
7
|
-
headers: index.ContentType.formUrlEncoded,
|
|
8
|
-
body: new URLSearchParams({
|
|
9
|
-
[index.QueryKey.ClientId]: clientId,
|
|
10
|
-
[index.QueryKey.Token]: token,
|
|
11
|
-
}).toString(),
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
exports.revoke = revoke;
|
package/lib/core/sign-in.cjs
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var index = require('../consts/index.cjs');
|
|
4
|
-
var scopes = require('../utils/scopes.cjs');
|
|
5
|
-
|
|
6
|
-
const codeChallengeMethod = 'S256';
|
|
7
|
-
const responseType = 'code';
|
|
8
|
-
const buildPrompt = (prompt) => {
|
|
9
|
-
if (Array.isArray(prompt)) {
|
|
10
|
-
return prompt.join(' ');
|
|
11
|
-
}
|
|
12
|
-
return prompt ?? index.Prompt.Consent;
|
|
13
|
-
};
|
|
14
|
-
// eslint-disable-next-line complexity
|
|
15
|
-
const generateSignInUri = ({ authorizationEndpoint, clientId, redirectUri, codeChallenge, state, scopes: scopes$1, resources, prompt, firstScreen, identifiers: identifier, interactionMode, loginHint, directSignIn, extraParams, includeReservedScopes = true, }) => {
|
|
16
|
-
const urlSearchParameters = new URLSearchParams({
|
|
17
|
-
[index.QueryKey.ClientId]: clientId,
|
|
18
|
-
[index.QueryKey.RedirectUri]: redirectUri,
|
|
19
|
-
[index.QueryKey.CodeChallenge]: codeChallenge,
|
|
20
|
-
[index.QueryKey.CodeChallengeMethod]: codeChallengeMethod,
|
|
21
|
-
[index.QueryKey.State]: state,
|
|
22
|
-
[index.QueryKey.ResponseType]: responseType,
|
|
23
|
-
[index.QueryKey.Prompt]: buildPrompt(prompt),
|
|
24
|
-
});
|
|
25
|
-
const computedScopes = includeReservedScopes ? scopes.withReservedScopes(scopes$1) : scopes$1?.join(' ');
|
|
26
|
-
if (computedScopes) {
|
|
27
|
-
urlSearchParameters.append(index.QueryKey.Scope, computedScopes);
|
|
28
|
-
}
|
|
29
|
-
if (loginHint) {
|
|
30
|
-
urlSearchParameters.append(index.QueryKey.LoginHint, loginHint);
|
|
31
|
-
}
|
|
32
|
-
if (directSignIn) {
|
|
33
|
-
urlSearchParameters.append(index.QueryKey.DirectSignIn, `${directSignIn.method}:${directSignIn.target}`);
|
|
34
|
-
}
|
|
35
|
-
for (const resource of resources ?? []) {
|
|
36
|
-
urlSearchParameters.append(index.QueryKey.Resource, resource);
|
|
37
|
-
}
|
|
38
|
-
if (firstScreen) {
|
|
39
|
-
urlSearchParameters.append(index.QueryKey.FirstScreen, firstScreen);
|
|
40
|
-
}
|
|
41
|
-
// @deprecated Remove later
|
|
42
|
-
else if (interactionMode) {
|
|
43
|
-
urlSearchParameters.append(index.QueryKey.InteractionMode, interactionMode);
|
|
44
|
-
}
|
|
45
|
-
if (identifier && identifier.length > 0) {
|
|
46
|
-
urlSearchParameters.append(index.QueryKey.Identifier, identifier.join(' '));
|
|
47
|
-
}
|
|
48
|
-
if (extraParams) {
|
|
49
|
-
for (const [key, value] of Object.entries(extraParams)) {
|
|
50
|
-
urlSearchParameters.append(key, value);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return `${authorizationEndpoint}?${urlSearchParameters.toString()}`;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
exports.generateSignInUri = generateSignInUri;
|
package/lib/core/sign-out.cjs
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var index = require('../consts/index.cjs');
|
|
4
|
-
|
|
5
|
-
const generateSignOutUri = ({ endSessionEndpoint, clientId, postLogoutRedirectUri, }) => {
|
|
6
|
-
const urlSearchParameters = new URLSearchParams({ [index.QueryKey.ClientId]: clientId });
|
|
7
|
-
if (postLogoutRedirectUri) {
|
|
8
|
-
urlSearchParameters.append(index.QueryKey.PostLogoutRedirectUri, postLogoutRedirectUri);
|
|
9
|
-
}
|
|
10
|
-
return `${endSessionEndpoint}?${urlSearchParameters.toString()}`;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
exports.generateSignOutUri = generateSignOutUri;
|
package/lib/core/user-info.cjs
DELETED
package/lib/index.cjs
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var fetchToken = require('./core/fetch-token.cjs');
|
|
4
|
-
var oidcConfig = require('./core/oidc-config.cjs');
|
|
5
|
-
var revoke = require('./core/revoke.cjs');
|
|
6
|
-
var signIn = require('./core/sign-in.cjs');
|
|
7
|
-
var signOut = require('./core/sign-out.cjs');
|
|
8
|
-
var userInfo = require('./core/user-info.cjs');
|
|
9
|
-
var callbackUri = require('./utils/callback-uri.cjs');
|
|
10
|
-
var errors = require('./utils/errors.cjs');
|
|
11
|
-
var idToken = require('./utils/id-token.cjs');
|
|
12
|
-
var accessToken = require('./utils/access-token.cjs');
|
|
13
|
-
var scopes = require('./utils/scopes.cjs');
|
|
14
|
-
var arbitraryObject = require('./utils/arbitrary-object.cjs');
|
|
15
|
-
var angular = require('./utils/angular.cjs');
|
|
16
|
-
var index = require('./consts/index.cjs');
|
|
17
|
-
var openid = require('./consts/openid.cjs');
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
exports.fetchTokenByAuthorizationCode = fetchToken.fetchTokenByAuthorizationCode;
|
|
22
|
-
exports.fetchTokenByRefreshToken = fetchToken.fetchTokenByRefreshToken;
|
|
23
|
-
exports.discoveryPath = oidcConfig.discoveryPath;
|
|
24
|
-
exports.fetchOidcConfig = oidcConfig.fetchOidcConfig;
|
|
25
|
-
exports.revoke = revoke.revoke;
|
|
26
|
-
exports.generateSignInUri = signIn.generateSignInUri;
|
|
27
|
-
exports.generateSignOutUri = signOut.generateSignOutUri;
|
|
28
|
-
exports.fetchUserInfo = userInfo.fetchUserInfo;
|
|
29
|
-
exports.parseUriParameters = callbackUri.parseUriParameters;
|
|
30
|
-
exports.verifyAndParseCodeFromCallbackUri = callbackUri.verifyAndParseCodeFromCallbackUri;
|
|
31
|
-
exports.LogtoError = errors.LogtoError;
|
|
32
|
-
exports.LogtoRequestError = errors.LogtoRequestError;
|
|
33
|
-
exports.OidcError = errors.OidcError;
|
|
34
|
-
exports.isLogtoRequestError = errors.isLogtoRequestError;
|
|
35
|
-
exports.isLogtoRequestErrorJson = errors.isLogtoRequestErrorJson;
|
|
36
|
-
exports.decodeIdToken = idToken.decodeIdToken;
|
|
37
|
-
exports.decodeAccessToken = accessToken.decodeAccessToken;
|
|
38
|
-
exports.withDefaultScopes = scopes.withDefaultScopes;
|
|
39
|
-
exports.withReservedScopes = scopes.withReservedScopes;
|
|
40
|
-
exports.isArbitraryObject = arbitraryObject.isArbitraryObject;
|
|
41
|
-
exports.buildAngularAuthConfig = angular.buildAngularAuthConfig;
|
|
42
|
-
exports.ContentType = index.ContentType;
|
|
43
|
-
Object.defineProperty(exports, "Prompt", {
|
|
44
|
-
enumerable: true,
|
|
45
|
-
get: function () { return index.Prompt; }
|
|
46
|
-
});
|
|
47
|
-
Object.defineProperty(exports, "QueryKey", {
|
|
48
|
-
enumerable: true,
|
|
49
|
-
get: function () { return index.QueryKey; }
|
|
50
|
-
});
|
|
51
|
-
Object.defineProperty(exports, "TokenGrantType", {
|
|
52
|
-
enumerable: true,
|
|
53
|
-
get: function () { return index.TokenGrantType; }
|
|
54
|
-
});
|
|
55
|
-
Object.defineProperty(exports, "ReservedResource", {
|
|
56
|
-
enumerable: true,
|
|
57
|
-
get: function () { return openid.ReservedResource; }
|
|
58
|
-
});
|
|
59
|
-
Object.defineProperty(exports, "ReservedScope", {
|
|
60
|
-
enumerable: true,
|
|
61
|
-
get: function () { return openid.ReservedScope; }
|
|
62
|
-
});
|
|
63
|
-
Object.defineProperty(exports, "UserScope", {
|
|
64
|
-
enumerable: true,
|
|
65
|
-
get: function () { return openid.UserScope; }
|
|
66
|
-
});
|
|
67
|
-
exports.buildOrganizationUrn = openid.buildOrganizationUrn;
|
|
68
|
-
exports.getOrganizationIdFromUrn = openid.getOrganizationIdFromUrn;
|
|
69
|
-
exports.idTokenClaims = openid.idTokenClaims;
|
|
70
|
-
exports.organizationUrnPrefix = openid.organizationUrnPrefix;
|
|
71
|
-
exports.userClaims = openid.userClaims;
|
|
72
|
-
exports.userinfoClaims = openid.userinfoClaims;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var essentials = require('@silverhand/essentials');
|
|
4
|
-
var arbitraryObject = require('./arbitrary-object.cjs');
|
|
5
|
-
|
|
6
|
-
// https://docs.logto.io/docs/recipes/protect-your-api/
|
|
7
|
-
function assertAccessTokenClaims(data) {
|
|
8
|
-
if (!arbitraryObject.isArbitraryObject(data)) {
|
|
9
|
-
throw new TypeError('AccessToken is expected to be an object');
|
|
10
|
-
}
|
|
11
|
-
for (const key of ['jti', 'iss', 'sub', 'aud', 'client_id', 'scope']) {
|
|
12
|
-
if (data[key] === undefined) {
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
if (typeof data[key] !== 'string' && data[key] !== null) {
|
|
16
|
-
throw new TypeError(`At path: AccessToken.${key}: expected null or a string`);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
for (const key of ['exp', 'iat']) {
|
|
20
|
-
if (data[key] === undefined) {
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
if (typeof data[key] !== 'number' && data[key] !== null) {
|
|
24
|
-
throw new TypeError(`At path: AccessToken.${key}: expected null or a number`);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
const decodeAccessToken = (accessToken) => {
|
|
29
|
-
const { 1: encodedPayload } = accessToken.split('.');
|
|
30
|
-
if (!encodedPayload) {
|
|
31
|
-
// Non-JWT format token string
|
|
32
|
-
return {};
|
|
33
|
-
}
|
|
34
|
-
const json = essentials.urlSafeBase64.decode(encodedPayload);
|
|
35
|
-
const accessTokenClaims = JSON.parse(json);
|
|
36
|
-
assertAccessTokenClaims(accessTokenClaims);
|
|
37
|
-
return accessTokenClaims;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
exports.decodeAccessToken = decodeAccessToken;
|
package/lib/utils/angular.cjs
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var index = require('../consts/index.cjs');
|
|
4
|
-
var scopes = require('./scopes.cjs');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A helper function to build the OpenID Connect configuration for `angular-auth-oidc-client`
|
|
8
|
-
* using a Logto-friendly way.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* // A minimal example
|
|
13
|
-
* import { buildAngularAuthConfig } from '@logto/js';
|
|
14
|
-
* import { provideAuth } from 'angular-auth-oidc-client';
|
|
15
|
-
*
|
|
16
|
-
* provideAuth({
|
|
17
|
-
* config: buildAngularAuthConfig({
|
|
18
|
-
* endpoint: '<your-logto-endpoint>',
|
|
19
|
-
* appId: '<your-app-id>',
|
|
20
|
-
* redirectUri: '<your-app-redirect-uri>',
|
|
21
|
-
* }),
|
|
22
|
-
* });
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* @param logtoConfig The Logto configuration object for Angular apps.
|
|
26
|
-
* @returns The OpenID Connect configuration for `angular-auth-oidc-client`.
|
|
27
|
-
* @see {@link https://angular-auth-oidc-client.com/ | angular-auth-oidc-client} to learn more
|
|
28
|
-
* about how to use the library.
|
|
29
|
-
*/
|
|
30
|
-
const buildAngularAuthConfig = (logtoConfig) => {
|
|
31
|
-
const { endpoint, appId: clientId, scopes: scopes$1, resource, redirectUri: redirectUrl, postLogoutRedirectUri, prompt = index.Prompt.Consent, includeReservedScopes = true, } = logtoConfig;
|
|
32
|
-
const scope = includeReservedScopes ? scopes.withReservedScopes(scopes$1) : scopes$1?.join(' ');
|
|
33
|
-
const customParameters = resource ? { resource } : undefined;
|
|
34
|
-
return {
|
|
35
|
-
authority: new URL('/oidc', endpoint).href,
|
|
36
|
-
redirectUrl,
|
|
37
|
-
postLogoutRedirectUri,
|
|
38
|
-
clientId,
|
|
39
|
-
scope,
|
|
40
|
-
responseType: 'code',
|
|
41
|
-
autoUserInfo: !resource,
|
|
42
|
-
renewUserInfoAfterTokenRenew: !resource,
|
|
43
|
-
silentRenew: true,
|
|
44
|
-
useRefreshToken: true,
|
|
45
|
-
customParamsAuthRequest: {
|
|
46
|
-
prompt: Array.isArray(prompt) ? prompt.join(' ') : prompt,
|
|
47
|
-
...customParameters,
|
|
48
|
-
},
|
|
49
|
-
customParamsCodeRequest: {
|
|
50
|
-
...customParameters,
|
|
51
|
-
},
|
|
52
|
-
customParamsRefreshTokenRequest: {
|
|
53
|
-
...customParameters,
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
exports.buildAngularAuthConfig = buildAngularAuthConfig;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var essentials = require('@silverhand/essentials');
|
|
4
|
-
var index = require('../consts/index.cjs');
|
|
5
|
-
var errors = require('./errors.cjs');
|
|
6
|
-
|
|
7
|
-
const parseUriParameters = (uri) => {
|
|
8
|
-
const [, queryString = ''] = uri.split('?');
|
|
9
|
-
return new URLSearchParams(queryString);
|
|
10
|
-
};
|
|
11
|
-
const verifyAndParseCodeFromCallbackUri = (callbackUri, redirectUri, state) => {
|
|
12
|
-
if (!callbackUri.startsWith(redirectUri)) {
|
|
13
|
-
throw new errors.LogtoError('callback_uri_verification.redirect_uri_mismatched');
|
|
14
|
-
}
|
|
15
|
-
const uriParameters = parseUriParameters(callbackUri);
|
|
16
|
-
const error = essentials.conditional(uriParameters.get(index.QueryKey.Error));
|
|
17
|
-
const errorDescription = essentials.conditional(uriParameters.get(index.QueryKey.ErrorDescription));
|
|
18
|
-
if (error) {
|
|
19
|
-
throw new errors.LogtoError('callback_uri_verification.error_found', new errors.OidcError(error, errorDescription));
|
|
20
|
-
}
|
|
21
|
-
const stateFromCallbackUri = uriParameters.get(index.QueryKey.State);
|
|
22
|
-
if (!stateFromCallbackUri) {
|
|
23
|
-
throw new errors.LogtoError('callback_uri_verification.missing_state');
|
|
24
|
-
}
|
|
25
|
-
if (stateFromCallbackUri !== state) {
|
|
26
|
-
throw new errors.LogtoError('callback_uri_verification.state_mismatched');
|
|
27
|
-
}
|
|
28
|
-
const code = uriParameters.get(index.QueryKey.Code);
|
|
29
|
-
if (!code) {
|
|
30
|
-
throw new errors.LogtoError('callback_uri_verification.missing_code');
|
|
31
|
-
}
|
|
32
|
-
return code;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
exports.parseUriParameters = parseUriParameters;
|
|
36
|
-
exports.verifyAndParseCodeFromCallbackUri = verifyAndParseCodeFromCallbackUri;
|
package/lib/utils/errors.cjs
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var arbitraryObject = require('./arbitrary-object.cjs');
|
|
4
|
-
|
|
5
|
-
const logtoErrorCodes = Object.freeze({
|
|
6
|
-
'id_token.invalid_iat': 'Invalid issued at time in the ID token',
|
|
7
|
-
'id_token.invalid_token': 'Invalid ID token',
|
|
8
|
-
'callback_uri_verification.redirect_uri_mismatched': 'The callback URI mismatches the redirect URI.',
|
|
9
|
-
'callback_uri_verification.error_found': 'Error found in the callback URI',
|
|
10
|
-
'callback_uri_verification.missing_state': 'Missing state in the callback URI',
|
|
11
|
-
'callback_uri_verification.state_mismatched': 'State mismatched in the callback URI',
|
|
12
|
-
'callback_uri_verification.missing_code': 'Missing code in the callback URI',
|
|
13
|
-
crypto_subtle_unavailable: 'Crypto.subtle is unavailable in insecure contexts (non-HTTPS).',
|
|
14
|
-
unexpected_response_error: 'Unexpected response error from the server.',
|
|
15
|
-
});
|
|
16
|
-
class LogtoError extends Error {
|
|
17
|
-
constructor(code, data) {
|
|
18
|
-
super(logtoErrorCodes[code]);
|
|
19
|
-
this.code = code;
|
|
20
|
-
this.data = data;
|
|
21
|
-
this.name = 'LogtoError';
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
const isLogtoRequestError = (data) => {
|
|
25
|
-
if (!arbitraryObject.isArbitraryObject(data)) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
return data instanceof Error && data.name === 'LogtoRequestError';
|
|
29
|
-
};
|
|
30
|
-
const isLogtoRequestErrorJson = (data) => {
|
|
31
|
-
if (!arbitraryObject.isArbitraryObject(data)) {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
return typeof data.code === 'string' && typeof data.message === 'string';
|
|
35
|
-
};
|
|
36
|
-
class LogtoRequestError extends Error {
|
|
37
|
-
constructor(code, message,
|
|
38
|
-
/** The original response object from the server. */
|
|
39
|
-
cause) {
|
|
40
|
-
super(message);
|
|
41
|
-
this.code = code;
|
|
42
|
-
this.cause = cause;
|
|
43
|
-
this.name = 'LogtoRequestError';
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
class OidcError {
|
|
47
|
-
constructor(error, errorDescription) {
|
|
48
|
-
this.error = error;
|
|
49
|
-
this.errorDescription = errorDescription;
|
|
50
|
-
this.name = 'OidcError';
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
exports.LogtoError = LogtoError;
|
|
55
|
-
exports.LogtoRequestError = LogtoRequestError;
|
|
56
|
-
exports.OidcError = OidcError;
|
|
57
|
-
exports.isLogtoRequestError = isLogtoRequestError;
|
|
58
|
-
exports.isLogtoRequestErrorJson = isLogtoRequestErrorJson;
|
package/lib/utils/id-token.cjs
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var essentials = require('@silverhand/essentials');
|
|
4
|
-
var arbitraryObject = require('./arbitrary-object.cjs');
|
|
5
|
-
var errors = require('./errors.cjs');
|
|
6
|
-
|
|
7
|
-
/* eslint-disable complexity */
|
|
8
|
-
/**
|
|
9
|
-
* @link [ID Token](https://openid.net/specs/openid-connect-core-1_0.html#IDToken)
|
|
10
|
-
*/
|
|
11
|
-
function assertIdTokenClaims(data) {
|
|
12
|
-
if (!arbitraryObject.isArbitraryObject(data)) {
|
|
13
|
-
throw new TypeError('IdToken is expected to be an object');
|
|
14
|
-
}
|
|
15
|
-
for (const key of ['iss', 'sub', 'aud']) {
|
|
16
|
-
if (typeof data[key] !== 'string') {
|
|
17
|
-
throw new TypeError(`At path: IdToken.${key}: expected a string`);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
for (const key of ['exp', 'iat']) {
|
|
21
|
-
if (typeof data[key] !== 'number') {
|
|
22
|
-
throw new TypeError(`At path: IdToken.${key}: expected a number`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
for (const key of ['at_hash', 'name', 'username', 'picture', 'email', 'phone_number']) {
|
|
26
|
-
if (data[key] === undefined) {
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
if (typeof data[key] !== 'string' && data[key] !== null) {
|
|
30
|
-
throw new TypeError(`At path: IdToken.${key}: expected null or a string`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
for (const key of ['email_verified', 'phone_number_verified']) {
|
|
34
|
-
if (data[key] === undefined) {
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
if (typeof data[key] !== 'boolean') {
|
|
38
|
-
throw new TypeError(`At path: IdToken.${key}: expected a boolean`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/* eslint-enable complexity */
|
|
43
|
-
const decodeIdToken = (token) => {
|
|
44
|
-
const { 1: encodedPayload } = token.split('.');
|
|
45
|
-
if (!encodedPayload) {
|
|
46
|
-
throw new errors.LogtoError('id_token.invalid_token');
|
|
47
|
-
}
|
|
48
|
-
const json = essentials.urlSafeBase64.decode(encodedPayload);
|
|
49
|
-
const idTokenClaims = JSON.parse(json);
|
|
50
|
-
assertIdTokenClaims(idTokenClaims);
|
|
51
|
-
return idTokenClaims;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
exports.decodeIdToken = decodeIdToken;
|
package/lib/utils/scopes.cjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
require('../consts/index.cjs');
|
|
4
|
-
var openid = require('../consts/openid.cjs');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @param originalScopes
|
|
8
|
-
* @return scopes should contain all default scopes (`openid`, `offline_access` and `profile`)
|
|
9
|
-
*/
|
|
10
|
-
const withReservedScopes = (originalScopes) => {
|
|
11
|
-
const reservedScopes = Object.values(openid.ReservedScope);
|
|
12
|
-
const uniqueScopes = new Set([...reservedScopes, openid.UserScope.Profile, ...(originalScopes ?? [])]);
|
|
13
|
-
return Array.from(uniqueScopes).join(' ');
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Alias of {@link withReservedScopes}.
|
|
17
|
-
*
|
|
18
|
-
* @deprecated Use {@link withReservedScopes} instead.
|
|
19
|
-
*/
|
|
20
|
-
const withDefaultScopes = withReservedScopes;
|
|
21
|
-
|
|
22
|
-
exports.withDefaultScopes = withDefaultScopes;
|
|
23
|
-
exports.withReservedScopes = withReservedScopes;
|