@logto/js 0.2.0 → 1.0.0-alpha.1

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.
@@ -1,14 +0,0 @@
1
- import { KeysToCamelCase } from '@silverhand/essentials';
2
- import { Requester } from '../utils';
3
- declare type OidcConfigSnakeCaseResponse = {
4
- authorization_endpoint: string;
5
- token_endpoint: string;
6
- end_session_endpoint: string;
7
- revocation_endpoint: string;
8
- jwks_uri: string;
9
- issuer: string;
10
- };
11
- export declare const discoveryPath = "/oidc/.well-known/openid-configuration";
12
- export declare type OidcConfigResponse = KeysToCamelCase<OidcConfigSnakeCaseResponse>;
13
- export declare const fetchOidcConfig: (endpoint: string, requester: Requester) => Promise<OidcConfigResponse>;
14
- export {};
@@ -1,10 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.fetchOidcConfig = exports.discoveryPath = void 0;
7
- const camelcase_keys_1 = __importDefault(require("camelcase-keys"));
8
- exports.discoveryPath = '/oidc/.well-known/openid-configuration';
9
- const fetchOidcConfig = async (endpoint, requester) => (0, camelcase_keys_1.default)(await requester(endpoint));
10
- exports.fetchOidcConfig = fetchOidcConfig;
@@ -1,2 +0,0 @@
1
- import { Requester } from '../utils';
2
- export declare const revoke: (revocationEndpoint: string, clientId: string, token: string, requester: Requester) => Promise<void>;
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.revoke = void 0;
4
- const consts_1 = require("../consts");
5
- const revoke = async (revocationEndpoint, clientId, token, requester) => requester(revocationEndpoint, {
6
- method: 'POST',
7
- headers: consts_1.ContentType.formUrlEncoded,
8
- body: new URLSearchParams({
9
- [consts_1.QueryKey.ClientId]: clientId,
10
- [consts_1.QueryKey.Token]: token,
11
- }),
12
- });
13
- exports.revoke = revoke;
@@ -1,12 +0,0 @@
1
- import { Prompt } from '../consts';
2
- export declare type SignInUriParameters = {
3
- authorizationEndpoint: string;
4
- clientId: string;
5
- redirectUri: string;
6
- codeChallenge: string;
7
- state: string;
8
- scopes?: string[];
9
- resources?: string[];
10
- prompt?: Prompt;
11
- };
12
- export declare const generateSignInUri: ({ authorizationEndpoint, clientId, redirectUri, codeChallenge, state, scopes, resources, prompt, }: SignInUriParameters) => string;
@@ -1,24 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateSignInUri = void 0;
4
- const consts_1 = require("../consts");
5
- const utils_1 = require("../utils");
6
- const codeChallengeMethod = 'S256';
7
- const responseType = 'code';
8
- const generateSignInUri = ({ authorizationEndpoint, clientId, redirectUri, codeChallenge, state, scopes, resources, prompt, }) => {
9
- const urlSearchParameters = new URLSearchParams({
10
- [consts_1.QueryKey.ClientId]: clientId,
11
- [consts_1.QueryKey.RedirectUri]: redirectUri,
12
- [consts_1.QueryKey.CodeChallenge]: codeChallenge,
13
- [consts_1.QueryKey.CodeChallengeMethod]: codeChallengeMethod,
14
- [consts_1.QueryKey.State]: state,
15
- [consts_1.QueryKey.ResponseType]: responseType,
16
- [consts_1.QueryKey.Prompt]: prompt ?? consts_1.Prompt.Consent,
17
- [consts_1.QueryKey.Scope]: (0, utils_1.withReservedScopes)(scopes),
18
- });
19
- for (const resource of resources ?? []) {
20
- urlSearchParameters.append(consts_1.QueryKey.Resource, resource);
21
- }
22
- return `${authorizationEndpoint}?${urlSearchParameters.toString()}`;
23
- };
24
- exports.generateSignInUri = generateSignInUri;
@@ -1,7 +0,0 @@
1
- declare type SignOutUriParameters = {
2
- endSessionEndpoint: string;
3
- idToken: string;
4
- postLogoutRedirectUri?: string;
5
- };
6
- export declare const generateSignOutUri: ({ endSessionEndpoint, idToken, postLogoutRedirectUri, }: SignOutUriParameters) => string;
7
- export {};
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateSignOutUri = void 0;
4
- const consts_1 = require("../consts");
5
- const generateSignOutUri = ({ endSessionEndpoint, idToken, postLogoutRedirectUri, }) => {
6
- const urlSearchParameters = new URLSearchParams({ [consts_1.QueryKey.IdTokenHint]: idToken });
7
- if (postLogoutRedirectUri) {
8
- urlSearchParameters.append(consts_1.QueryKey.PostLogoutRedirectUri, postLogoutRedirectUri);
9
- }
10
- return `${endSessionEndpoint}?${urlSearchParameters.toString()}`;
11
- };
12
- exports.generateSignOutUri = generateSignOutUri;
@@ -1,2 +0,0 @@
1
- export declare const parseUriParameters: (uri: string) => URLSearchParams;
2
- export declare const verifyAndParseCodeFromCallbackUri: (callbackUri: string, redirectUri: string, state: string) => string;
@@ -1,36 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.verifyAndParseCodeFromCallbackUri = exports.parseUriParameters = void 0;
4
- const essentials_1 = require("@silverhand/essentials");
5
- const consts_1 = require("../consts");
6
- const errors_1 = require("./errors");
7
- const parseUriParameters = (uri) => {
8
- const [, queryString = ''] = uri.split('?');
9
- return new URLSearchParams(queryString);
10
- };
11
- exports.parseUriParameters = parseUriParameters;
12
- // eslint-disable-next-line complexity
13
- const verifyAndParseCodeFromCallbackUri = (callbackUri, redirectUri, state) => {
14
- if (!callbackUri.startsWith(redirectUri)) {
15
- throw new errors_1.LogtoError('callback_uri_verification.redirect_uri_mismatched');
16
- }
17
- const uriParameters = (0, exports.parseUriParameters)(callbackUri);
18
- const error = (0, essentials_1.conditional)(uriParameters.get(consts_1.QueryKey.Error));
19
- const errorDescription = (0, essentials_1.conditional)(uriParameters.get(consts_1.QueryKey.ErrorDescription));
20
- if (error) {
21
- throw new errors_1.LogtoError('callback_uri_verification.error_found', new errors_1.OidcError(error, errorDescription));
22
- }
23
- const stateFromCallbackUri = uriParameters.get(consts_1.QueryKey.State);
24
- if (!stateFromCallbackUri) {
25
- throw new errors_1.LogtoError('callback_uri_verification.missing_state');
26
- }
27
- if (stateFromCallbackUri !== state) {
28
- throw new errors_1.LogtoError('callback_uri_verification.state_mismatched');
29
- }
30
- const code = uriParameters.get(consts_1.QueryKey.Code);
31
- if (!code) {
32
- throw new errors_1.LogtoError('callback_uri_verification.missing_code');
33
- }
34
- return code;
35
- };
36
- exports.verifyAndParseCodeFromCallbackUri = verifyAndParseCodeFromCallbackUri;
@@ -1,33 +0,0 @@
1
- import { NormalizeKeyPaths } from '@silverhand/essentials';
2
- declare const logtoErrorCodes: Readonly<{
3
- id_token: {
4
- invalid_iat: string;
5
- invalid_token: string;
6
- };
7
- callback_uri_verification: {
8
- redirect_uri_mismatched: string;
9
- error_found: string;
10
- missing_state: string;
11
- state_mismatched: string;
12
- missing_code: string;
13
- };
14
- requester: {
15
- not_provide_fetch: string;
16
- };
17
- }>;
18
- export declare type LogtoErrorCode = NormalizeKeyPaths<typeof logtoErrorCodes>;
19
- export declare class LogtoError extends Error {
20
- code: LogtoErrorCode;
21
- data: unknown;
22
- constructor(code: LogtoErrorCode, data?: unknown);
23
- }
24
- export declare class LogtoRequestError extends Error {
25
- code: string;
26
- constructor(code: string, message: string);
27
- }
28
- export declare class OidcError {
29
- error: string;
30
- errorDescription?: string;
31
- constructor(error: string, errorDescription?: string);
32
- }
33
- export {};
@@ -1,54 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.OidcError = exports.LogtoRequestError = exports.LogtoError = void 0;
7
- const lodash_get_1 = __importDefault(require("lodash.get"));
8
- const logtoErrorCodes = Object.freeze({
9
- id_token: {
10
- invalid_iat: 'Invalid issued at time',
11
- invalid_token: 'Invalid token',
12
- },
13
- callback_uri_verification: {
14
- redirect_uri_mismatched: 'Redirect URI mismatched',
15
- error_found: 'Error found',
16
- missing_state: 'Missing state',
17
- state_mismatched: 'State mismatched',
18
- missing_code: 'Missing code',
19
- },
20
- requester: {
21
- not_provide_fetch: 'Should provide a fetch function under Node.js',
22
- },
23
- });
24
- const getMessageByErrorCode = (errorCode) => {
25
- // TODO: linear issue LOG-1419
26
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
27
- const message = (0, lodash_get_1.default)(logtoErrorCodes, errorCode);
28
- if (typeof message === 'string') {
29
- return message;
30
- }
31
- return errorCode;
32
- };
33
- class LogtoError extends Error {
34
- constructor(code, data) {
35
- super(getMessageByErrorCode(code));
36
- this.code = code;
37
- this.data = data;
38
- }
39
- }
40
- exports.LogtoError = LogtoError;
41
- class LogtoRequestError extends Error {
42
- constructor(code, message) {
43
- super(message);
44
- this.code = code;
45
- }
46
- }
47
- exports.LogtoRequestError = LogtoRequestError;
48
- class OidcError {
49
- constructor(error, errorDescription) {
50
- this.error = error;
51
- this.errorDescription = errorDescription;
52
- }
53
- }
54
- exports.OidcError = OidcError;
@@ -1,18 +0,0 @@
1
- /** @link [Proof Key for Code Exchange by OAuth Public Clients](https://datatracker.ietf.org/doc/html/rfc7636) */
2
- /**
3
- * Generates random string for state and encodes them in url safe base64
4
- */
5
- export declare const generateState: () => string;
6
- /**
7
- * Generates code verifier
8
- *
9
- * @link [Client Creates a Code Verifier](https://datatracker.ietf.org/doc/html/rfc7636#section-4.1)
10
- */
11
- export declare const generateCodeVerifier: () => string;
12
- /**
13
- * Calculates the S256 PKCE code challenge for an arbitrary code verifier and encodes it in url safe base64
14
- *
15
- * @param {String} codeVerifier Code verifier to calculate the S256 code challenge for
16
- * @link [Client Creates the Code Challenge](https://datatracker.ietf.org/doc/html/rfc7636#section-4.2)
17
- */
18
- export declare const generateCodeChallenge: (codeVerifier: string) => Promise<string>;
@@ -1,34 +0,0 @@
1
- "use strict";
2
- /** @link [Proof Key for Code Exchange by OAuth Public Clients](https://datatracker.ietf.org/doc/html/rfc7636) */
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.generateCodeChallenge = exports.generateCodeVerifier = exports.generateState = void 0;
5
- const js_base64_1 = require("js-base64");
6
- /**
7
- * @param length The length of the raw random data.
8
- */
9
- const generateRandomString = (length = 64) => (0, js_base64_1.fromUint8Array)(crypto.getRandomValues(new Uint8Array(length)), true);
10
- /**
11
- * Generates random string for state and encodes them in url safe base64
12
- */
13
- const generateState = () => generateRandomString();
14
- exports.generateState = generateState;
15
- /**
16
- * Generates code verifier
17
- *
18
- * @link [Client Creates a Code Verifier](https://datatracker.ietf.org/doc/html/rfc7636#section-4.1)
19
- */
20
- const generateCodeVerifier = () => generateRandomString();
21
- exports.generateCodeVerifier = generateCodeVerifier;
22
- /**
23
- * Calculates the S256 PKCE code challenge for an arbitrary code verifier and encodes it in url safe base64
24
- *
25
- * @param {String} codeVerifier Code verifier to calculate the S256 code challenge for
26
- * @link [Client Creates the Code Challenge](https://datatracker.ietf.org/doc/html/rfc7636#section-4.2)
27
- */
28
- const generateCodeChallenge = async (codeVerifier) => {
29
- const encodedCodeVerifier = new TextEncoder().encode(codeVerifier);
30
- // TODO: crypto related to linear issue LOG-1517
31
- const codeChallenge = new Uint8Array(await crypto.subtle.digest('SHA-256', encodedCodeVerifier));
32
- return (0, js_base64_1.fromUint8Array)(codeChallenge, true);
33
- };
34
- exports.generateCodeChallenge = generateCodeChallenge;
@@ -1,32 +0,0 @@
1
- import { JWTVerifyGetKey } from 'jose';
2
- import * as s from 'superstruct';
3
- /**
4
- * @link [ID Token](https://openid.net/specs/openid-connect-core-1_0.html#IDToken)
5
- */
6
- declare const IdTokenClaimsSchema: s.Struct<{
7
- iss: string;
8
- sub: string;
9
- aud: string;
10
- exp: number;
11
- iat: number;
12
- at_hash?: string | null | undefined;
13
- name?: string | null | undefined;
14
- username?: string | null | undefined;
15
- avatar?: string | null | undefined;
16
- role_names?: string[] | null | undefined;
17
- }, {
18
- iss: s.Struct<string, null>;
19
- sub: s.Struct<string, null>;
20
- aud: s.Struct<string, null>;
21
- exp: s.Struct<number, null>;
22
- iat: s.Struct<number, null>;
23
- at_hash: s.Struct<string | null | undefined, null>;
24
- name: s.Struct<string | null | undefined, null>;
25
- username: s.Struct<string | null | undefined, null>;
26
- avatar: s.Struct<string | null | undefined, null>;
27
- role_names: s.Struct<string[] | null | undefined, s.Struct<string, null>>;
28
- }>;
29
- export declare type IdTokenClaims = s.Infer<typeof IdTokenClaimsSchema>;
30
- export declare const verifyIdToken: (idToken: string, clientId: string, issuer: string, jwks: JWTVerifyGetKey) => Promise<void>;
31
- export declare const decodeIdToken: (token: string) => IdTokenClaims;
32
- export {};
@@ -1,60 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
- }) : (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- o[k2] = m[k];
8
- }));
9
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
- Object.defineProperty(o, "default", { enumerable: true, value: v });
11
- }) : function(o, v) {
12
- o["default"] = v;
13
- });
14
- var __importStar = (this && this.__importStar) || function (mod) {
15
- if (mod && mod.__esModule) return mod;
16
- var result = {};
17
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
- __setModuleDefault(result, mod);
19
- return result;
20
- };
21
- Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.decodeIdToken = exports.verifyIdToken = void 0;
23
- const essentials_1 = require("@silverhand/essentials");
24
- const jose_1 = require("jose");
25
- const s = __importStar(require("superstruct"));
26
- const errors_1 = require("./errors");
27
- const issuedAtTimeTolerance = 60;
28
- /**
29
- * @link [ID Token](https://openid.net/specs/openid-connect-core-1_0.html#IDToken)
30
- */
31
- const IdTokenClaimsSchema = s.type({
32
- iss: s.string(),
33
- sub: s.string(),
34
- aud: s.string(),
35
- exp: s.number(),
36
- iat: s.number(),
37
- at_hash: s.nullable(s.optional(s.string())),
38
- name: s.nullable(s.optional(s.string())),
39
- username: s.nullable(s.optional(s.string())),
40
- avatar: s.nullable(s.optional(s.string())),
41
- role_names: s.nullable(s.optional(s.array(s.string()))),
42
- });
43
- const verifyIdToken = async (idToken, clientId, issuer, jwks) => {
44
- const result = await (0, jose_1.jwtVerify)(idToken, jwks, { audience: clientId, issuer });
45
- if (Math.abs((result.payload.iat ?? 0) - Date.now() / 1000) > issuedAtTimeTolerance) {
46
- throw new errors_1.LogtoError('id_token.invalid_iat');
47
- }
48
- };
49
- exports.verifyIdToken = verifyIdToken;
50
- const decodeIdToken = (token) => {
51
- const { 1: encodedPayload } = token.split('.');
52
- if (!encodedPayload) {
53
- throw new errors_1.LogtoError('id_token.invalid_token');
54
- }
55
- const json = essentials_1.UrlSafeBase64.decode(encodedPayload);
56
- const idTokenClaims = JSON.parse(json);
57
- s.assert(idTokenClaims, IdTokenClaimsSchema);
58
- return idTokenClaims;
59
- };
60
- exports.decodeIdToken = decodeIdToken;
@@ -1,6 +0,0 @@
1
- export * from './callback-uri';
2
- export * from './errors';
3
- export * from './generators';
4
- export * from './id-token';
5
- export * from './requester';
6
- export * from './scopes';
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
- }) : (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- o[k2] = m[k];
8
- }));
9
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
- };
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- __exportStar(require("./callback-uri"), exports);
14
- __exportStar(require("./errors"), exports);
15
- __exportStar(require("./generators"), exports);
16
- __exportStar(require("./id-token"), exports);
17
- __exportStar(require("./requester"), exports);
18
- __exportStar(require("./scopes"), exports);
@@ -1,2 +0,0 @@
1
- export declare const createRequester: (fetchFunction?: typeof fetch | undefined) => <T>(input: RequestInfo, init?: RequestInit | undefined) => Promise<T>;
2
- export declare type Requester = ReturnType<typeof createRequester>;
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createRequester = void 0;
4
- const essentials_1 = require("@silverhand/essentials");
5
- const errors_1 = require("./errors");
6
- const createRequester = (fetchFunction) => {
7
- if (!fetchFunction && (0, essentials_1.isNode)()) {
8
- throw new errors_1.LogtoError('requester.not_provide_fetch');
9
- }
10
- return async (...args) => {
11
- const response = await (fetchFunction ?? fetch)(...args);
12
- if (!response.ok) {
13
- // Expected request error from server
14
- const { code, message } = await response.json();
15
- throw new errors_1.LogtoRequestError(code, message);
16
- }
17
- return response.json();
18
- };
19
- };
20
- exports.createRequester = createRequester;
@@ -1,5 +0,0 @@
1
- /**
2
- * @param originalScopes
3
- * @return scopes should contain all reserved scopes ( Logto requires `openid` and `offline_access` )
4
- */
5
- export declare const withReservedScopes: (originalScopes?: string[] | undefined) => string;
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.withReservedScopes = void 0;
4
- /**
5
- * @param originalScopes
6
- * @return scopes should contain all reserved scopes ( Logto requires `openid` and `offline_access` )
7
- */
8
- const withReservedScopes = (originalScopes) => {
9
- const uniqueScopes = new Set(['openid', 'offline_access', 'profile', ...(originalScopes ?? [])]);
10
- return Array.from(uniqueScopes).join(' ');
11
- };
12
- exports.withReservedScopes = withReservedScopes;