6879 lines
220 KiB
JavaScript
6879 lines
220 KiB
JavaScript
"use strict";
|
|
var __create = Object.create;
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __getProtoOf = Object.getPrototypeOf;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __typeError = (msg) => {
|
|
throw TypeError(msg);
|
|
};
|
|
var __commonJS = (cb, mod) => function __require() {
|
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
};
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
// file that has been converted to a CommonJS file using a Babel-
|
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
mod
|
|
));
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
|
|
// ../../node_modules/.pnpm/cookie@1.0.2/node_modules/cookie/dist/index.js
|
|
var require_dist = __commonJS({
|
|
"../../node_modules/.pnpm/cookie@1.0.2/node_modules/cookie/dist/index.js"(exports2) {
|
|
"use strict";
|
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
exports2.parse = parse3;
|
|
exports2.serialize = serialize;
|
|
var cookieNameRegExp = /^[\u0021-\u003A\u003C\u003E-\u007E]+$/;
|
|
var cookieValueRegExp = /^[\u0021-\u003A\u003C-\u007E]*$/;
|
|
var domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i;
|
|
var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
|
|
var __toString = Object.prototype.toString;
|
|
var NullObject = /* @__PURE__ */ (() => {
|
|
const C = function() {
|
|
};
|
|
C.prototype = /* @__PURE__ */ Object.create(null);
|
|
return C;
|
|
})();
|
|
function parse3(str, options) {
|
|
const obj = new NullObject();
|
|
const len = str.length;
|
|
if (len < 2)
|
|
return obj;
|
|
const dec = options?.decode || decode;
|
|
let index = 0;
|
|
do {
|
|
const eqIdx = str.indexOf("=", index);
|
|
if (eqIdx === -1)
|
|
break;
|
|
const colonIdx = str.indexOf(";", index);
|
|
const endIdx = colonIdx === -1 ? len : colonIdx;
|
|
if (eqIdx > endIdx) {
|
|
index = str.lastIndexOf(";", eqIdx - 1) + 1;
|
|
continue;
|
|
}
|
|
const keyStartIdx = startIndex(str, index, eqIdx);
|
|
const keyEndIdx = endIndex(str, eqIdx, keyStartIdx);
|
|
const key = str.slice(keyStartIdx, keyEndIdx);
|
|
if (obj[key] === void 0) {
|
|
let valStartIdx = startIndex(str, eqIdx + 1, endIdx);
|
|
let valEndIdx = endIndex(str, endIdx, valStartIdx);
|
|
const value = dec(str.slice(valStartIdx, valEndIdx));
|
|
obj[key] = value;
|
|
}
|
|
index = endIdx + 1;
|
|
} while (index < len);
|
|
return obj;
|
|
}
|
|
function startIndex(str, index, max) {
|
|
do {
|
|
const code = str.charCodeAt(index);
|
|
if (code !== 32 && code !== 9)
|
|
return index;
|
|
} while (++index < max);
|
|
return max;
|
|
}
|
|
function endIndex(str, index, min) {
|
|
while (index > min) {
|
|
const code = str.charCodeAt(--index);
|
|
if (code !== 32 && code !== 9)
|
|
return index + 1;
|
|
}
|
|
return min;
|
|
}
|
|
function serialize(name, val, options) {
|
|
const enc = options?.encode || encodeURIComponent;
|
|
if (!cookieNameRegExp.test(name)) {
|
|
throw new TypeError(`argument name is invalid: ${name}`);
|
|
}
|
|
const value = enc(val);
|
|
if (!cookieValueRegExp.test(value)) {
|
|
throw new TypeError(`argument val is invalid: ${val}`);
|
|
}
|
|
let str = name + "=" + value;
|
|
if (!options)
|
|
return str;
|
|
if (options.maxAge !== void 0) {
|
|
if (!Number.isInteger(options.maxAge)) {
|
|
throw new TypeError(`option maxAge is invalid: ${options.maxAge}`);
|
|
}
|
|
str += "; Max-Age=" + options.maxAge;
|
|
}
|
|
if (options.domain) {
|
|
if (!domainValueRegExp.test(options.domain)) {
|
|
throw new TypeError(`option domain is invalid: ${options.domain}`);
|
|
}
|
|
str += "; Domain=" + options.domain;
|
|
}
|
|
if (options.path) {
|
|
if (!pathValueRegExp.test(options.path)) {
|
|
throw new TypeError(`option path is invalid: ${options.path}`);
|
|
}
|
|
str += "; Path=" + options.path;
|
|
}
|
|
if (options.expires) {
|
|
if (!isDate(options.expires) || !Number.isFinite(options.expires.valueOf())) {
|
|
throw new TypeError(`option expires is invalid: ${options.expires}`);
|
|
}
|
|
str += "; Expires=" + options.expires.toUTCString();
|
|
}
|
|
if (options.httpOnly) {
|
|
str += "; HttpOnly";
|
|
}
|
|
if (options.secure) {
|
|
str += "; Secure";
|
|
}
|
|
if (options.partitioned) {
|
|
str += "; Partitioned";
|
|
}
|
|
if (options.priority) {
|
|
const priority = typeof options.priority === "string" ? options.priority.toLowerCase() : void 0;
|
|
switch (priority) {
|
|
case "low":
|
|
str += "; Priority=Low";
|
|
break;
|
|
case "medium":
|
|
str += "; Priority=Medium";
|
|
break;
|
|
case "high":
|
|
str += "; Priority=High";
|
|
break;
|
|
default:
|
|
throw new TypeError(`option priority is invalid: ${options.priority}`);
|
|
}
|
|
}
|
|
if (options.sameSite) {
|
|
const sameSite = typeof options.sameSite === "string" ? options.sameSite.toLowerCase() : options.sameSite;
|
|
switch (sameSite) {
|
|
case true:
|
|
case "strict":
|
|
str += "; SameSite=Strict";
|
|
break;
|
|
case "lax":
|
|
str += "; SameSite=Lax";
|
|
break;
|
|
case "none":
|
|
str += "; SameSite=None";
|
|
break;
|
|
default:
|
|
throw new TypeError(`option sameSite is invalid: ${options.sameSite}`);
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
function decode(str) {
|
|
if (str.indexOf("%") === -1)
|
|
return str;
|
|
try {
|
|
return decodeURIComponent(str);
|
|
} catch (e) {
|
|
return str;
|
|
}
|
|
}
|
|
function isDate(val) {
|
|
return __toString.call(val) === "[object Date]";
|
|
}
|
|
}
|
|
});
|
|
|
|
// src/internal.ts
|
|
var internal_exports = {};
|
|
__export(internal_exports, {
|
|
AuthStatus: () => AuthStatus,
|
|
TokenType: () => TokenType,
|
|
authenticatedMachineObject: () => authenticatedMachineObject,
|
|
constants: () => constants,
|
|
createAuthenticateRequest: () => createAuthenticateRequest,
|
|
createBootstrapSignedOutState: () => createBootstrapSignedOutState,
|
|
createClerkRequest: () => createClerkRequest,
|
|
createRedirect: () => createRedirect,
|
|
debugRequestState: () => debugRequestState,
|
|
decorateObjectWithResources: () => decorateObjectWithResources,
|
|
getAuthObjectForAcceptedToken: () => getAuthObjectForAcceptedToken,
|
|
getAuthObjectFromJwt: () => getAuthObjectFromJwt,
|
|
invalidTokenAuthObject: () => invalidTokenAuthObject,
|
|
isMachineToken: () => isMachineToken,
|
|
isMachineTokenByPrefix: () => isMachineTokenByPrefix,
|
|
isTokenTypeAccepted: () => isTokenTypeAccepted,
|
|
makeAuthObjectSerializable: () => makeAuthObjectSerializable,
|
|
reverificationError: () => import_authorization_errors.reverificationError,
|
|
reverificationErrorResponse: () => import_authorization_errors.reverificationErrorResponse,
|
|
signedInAuthObject: () => signedInAuthObject,
|
|
signedOutAuthObject: () => signedOutAuthObject,
|
|
stripPrivateDataFromObject: () => stripPrivateDataFromObject,
|
|
unauthenticatedMachineObject: () => unauthenticatedMachineObject,
|
|
verifyMachineAuthToken: () => verifyMachineAuthToken
|
|
});
|
|
module.exports = __toCommonJS(internal_exports);
|
|
|
|
// src/constants.ts
|
|
var API_URL = "https://api.clerk.com";
|
|
var API_VERSION = "v1";
|
|
var USER_AGENT = `${"@clerk/backend"}@${"3.4.1"}`;
|
|
var MAX_CACHE_LAST_UPDATED_AT_SECONDS = 5 * 60;
|
|
var SUPPORTED_BAPI_VERSION = "2025-11-10";
|
|
var Attributes = {
|
|
AuthToken: "__clerkAuthToken",
|
|
AuthSignature: "__clerkAuthSignature",
|
|
AuthStatus: "__clerkAuthStatus",
|
|
AuthReason: "__clerkAuthReason",
|
|
AuthMessage: "__clerkAuthMessage",
|
|
ClerkUrl: "__clerkUrl"
|
|
};
|
|
var Cookies = {
|
|
Session: "__session",
|
|
Refresh: "__refresh",
|
|
ClientUat: "__client_uat",
|
|
Handshake: "__clerk_handshake",
|
|
DevBrowser: "__clerk_db_jwt",
|
|
RedirectCount: "__clerk_redirect_count",
|
|
HandshakeNonce: "__clerk_handshake_nonce"
|
|
};
|
|
var QueryParameters = {
|
|
ClerkSynced: "__clerk_synced",
|
|
SuffixedCookies: "suffixed_cookies",
|
|
ClerkRedirectUrl: "__clerk_redirect_url",
|
|
// use the reference to Cookies to indicate that it's the same value
|
|
DevBrowser: Cookies.DevBrowser,
|
|
Handshake: Cookies.Handshake,
|
|
HandshakeHelp: "__clerk_help",
|
|
LegacyDevBrowser: "__dev_session",
|
|
HandshakeReason: "__clerk_hs_reason",
|
|
HandshakeNonce: Cookies.HandshakeNonce,
|
|
HandshakeFormat: "format",
|
|
Session: "__session"
|
|
};
|
|
var Headers2 = {
|
|
Accept: "accept",
|
|
AuthMessage: "x-clerk-auth-message",
|
|
Authorization: "authorization",
|
|
AuthReason: "x-clerk-auth-reason",
|
|
AuthSignature: "x-clerk-auth-signature",
|
|
AuthStatus: "x-clerk-auth-status",
|
|
AuthToken: "x-clerk-auth-token",
|
|
CacheControl: "cache-control",
|
|
ClerkRedirectTo: "x-clerk-redirect-to",
|
|
ClerkRequestData: "x-clerk-request-data",
|
|
ClerkUrl: "x-clerk-clerk-url",
|
|
CloudFrontForwardedProto: "cloudfront-forwarded-proto",
|
|
ContentType: "content-type",
|
|
ContentSecurityPolicy: "content-security-policy",
|
|
ContentSecurityPolicyReportOnly: "content-security-policy-report-only",
|
|
EnableDebug: "x-clerk-debug",
|
|
ForwardedHost: "x-forwarded-host",
|
|
ForwardedPort: "x-forwarded-port",
|
|
ForwardedProto: "x-forwarded-proto",
|
|
Host: "host",
|
|
Location: "location",
|
|
Nonce: "x-nonce",
|
|
Origin: "origin",
|
|
Referrer: "referer",
|
|
SecFetchDest: "sec-fetch-dest",
|
|
SecFetchSite: "sec-fetch-site",
|
|
UserAgent: "user-agent",
|
|
ReportingEndpoints: "reporting-endpoints"
|
|
};
|
|
var ContentTypes = {
|
|
Json: "application/json"
|
|
};
|
|
var ClerkSyncStatus = {
|
|
/** Not synced - satellite needs handshake after returning from primary sign-in */
|
|
NeedsSync: "false",
|
|
/** Sync completed - prevents re-sync loop after handshake completes */
|
|
Completed: "true"
|
|
};
|
|
var constants = {
|
|
Attributes,
|
|
Cookies,
|
|
Headers: Headers2,
|
|
ContentTypes,
|
|
QueryParameters,
|
|
ClerkSyncStatus
|
|
};
|
|
|
|
// src/createRedirect.ts
|
|
var import_buildAccountsBaseUrl = require("@clerk/shared/buildAccountsBaseUrl");
|
|
|
|
// src/util/shared.ts
|
|
var import_deprecated = require("@clerk/shared/deprecated");
|
|
var import_keys = require("@clerk/shared/keys");
|
|
var import_retry = require("@clerk/shared/retry");
|
|
var import_url = require("@clerk/shared/url");
|
|
var import_error = require("@clerk/shared/error");
|
|
var import_keys2 = require("@clerk/shared/keys");
|
|
var errorThrower = (0, import_error.buildErrorThrower)({ packageName: "@clerk/backend" });
|
|
var { isDevOrStagingUrl } = (0, import_keys2.createDevOrStagingUrlCache)();
|
|
|
|
// src/createRedirect.ts
|
|
var buildUrl = (_baseUrl, _targetUrl, _returnBackUrl, _devBrowserToken, _isSatellite) => {
|
|
if (_baseUrl === "") {
|
|
return legacyBuildUrl(_targetUrl.toString(), _returnBackUrl?.toString());
|
|
}
|
|
const baseUrl = new URL(_baseUrl);
|
|
const returnBackUrl = _returnBackUrl ? new URL(_returnBackUrl, baseUrl) : void 0;
|
|
const res = new URL(_targetUrl, baseUrl);
|
|
const isCrossOriginRedirect = `${baseUrl.hostname}:${baseUrl.port}` !== `${res.hostname}:${res.port}`;
|
|
if (returnBackUrl) {
|
|
if (isCrossOriginRedirect && _isSatellite) {
|
|
returnBackUrl.searchParams.set(constants.QueryParameters.ClerkSynced, ClerkSyncStatus.NeedsSync);
|
|
}
|
|
res.searchParams.set("redirect_url", returnBackUrl.toString());
|
|
}
|
|
if (isCrossOriginRedirect && _devBrowserToken) {
|
|
res.searchParams.set(constants.QueryParameters.DevBrowser, _devBrowserToken);
|
|
}
|
|
return res.toString();
|
|
};
|
|
var legacyBuildUrl = (targetUrl, redirectUrl) => {
|
|
let url;
|
|
if (!targetUrl.startsWith("http")) {
|
|
if (!redirectUrl || !redirectUrl.startsWith("http")) {
|
|
throw new Error("destination url or return back url should be an absolute path url!");
|
|
}
|
|
const baseURL = new URL(redirectUrl);
|
|
url = new URL(targetUrl, baseURL.origin);
|
|
} else {
|
|
url = new URL(targetUrl);
|
|
}
|
|
if (redirectUrl) {
|
|
url.searchParams.set("redirect_url", redirectUrl);
|
|
}
|
|
return url.toString();
|
|
};
|
|
var createRedirect = (params) => {
|
|
const { publishableKey, redirectAdapter, signInUrl, signUpUrl, baseUrl, sessionStatus, isSatellite } = params;
|
|
const parsedPublishableKey = (0, import_keys.parsePublishableKey)(publishableKey);
|
|
const frontendApi = parsedPublishableKey?.frontendApi;
|
|
const isDevelopment = parsedPublishableKey?.instanceType === "development";
|
|
const accountsBaseUrl = (0, import_buildAccountsBaseUrl.buildAccountsBaseUrl)(frontendApi);
|
|
const hasPendingStatus = sessionStatus === "pending";
|
|
const redirectToTasks = (url, { returnBackUrl }) => {
|
|
return redirectAdapter(
|
|
buildUrl(baseUrl, `${url}/tasks`, returnBackUrl, isDevelopment ? params.devBrowserToken : null, isSatellite)
|
|
);
|
|
};
|
|
const redirectToSignUp = ({ returnBackUrl } = {}) => {
|
|
if (!signUpUrl && !accountsBaseUrl) {
|
|
errorThrower.throwMissingPublishableKeyError();
|
|
}
|
|
const accountsSignUpUrl = `${accountsBaseUrl}/sign-up`;
|
|
function buildSignUpUrl(signIn) {
|
|
if (!signIn) {
|
|
return;
|
|
}
|
|
const url = new URL(signIn, baseUrl);
|
|
url.pathname = `${url.pathname}/create`;
|
|
return url.toString();
|
|
}
|
|
const targetUrl = signUpUrl || buildSignUpUrl(signInUrl) || accountsSignUpUrl;
|
|
if (hasPendingStatus) {
|
|
return redirectToTasks(targetUrl, { returnBackUrl });
|
|
}
|
|
return redirectAdapter(
|
|
buildUrl(baseUrl, targetUrl, returnBackUrl, isDevelopment ? params.devBrowserToken : null, isSatellite)
|
|
);
|
|
};
|
|
const redirectToSignIn = ({ returnBackUrl } = {}) => {
|
|
if (!signInUrl && !accountsBaseUrl) {
|
|
errorThrower.throwMissingPublishableKeyError();
|
|
}
|
|
const accountsSignInUrl = `${accountsBaseUrl}/sign-in`;
|
|
const targetUrl = signInUrl || accountsSignInUrl;
|
|
if (hasPendingStatus) {
|
|
return redirectToTasks(targetUrl, { returnBackUrl });
|
|
}
|
|
return redirectAdapter(
|
|
buildUrl(baseUrl, targetUrl, returnBackUrl, isDevelopment ? params.devBrowserToken : null, isSatellite)
|
|
);
|
|
};
|
|
return { redirectToSignUp, redirectToSignIn };
|
|
};
|
|
|
|
// src/util/mergePreDefinedOptions.ts
|
|
function mergePreDefinedOptions(preDefinedOptions, options) {
|
|
return Object.keys(preDefinedOptions).reduce(
|
|
(obj, key) => {
|
|
return { ...obj, [key]: options[key] || obj[key] };
|
|
},
|
|
{ ...preDefinedOptions }
|
|
);
|
|
}
|
|
|
|
// src/errors.ts
|
|
var import_error2 = require("@clerk/shared/error");
|
|
var import_error3 = require("@clerk/shared/error");
|
|
var TokenVerificationErrorCode = {
|
|
InvalidSecretKey: "clerk_key_invalid"
|
|
};
|
|
var TokenVerificationErrorReason = {
|
|
TokenExpired: "token-expired",
|
|
TokenInvalid: "token-invalid",
|
|
TokenInvalidAlgorithm: "token-invalid-algorithm",
|
|
TokenInvalidAuthorizedParties: "token-invalid-authorized-parties",
|
|
TokenInvalidSignature: "token-invalid-signature",
|
|
TokenNotActiveYet: "token-not-active-yet",
|
|
TokenIatInTheFuture: "token-iat-in-the-future",
|
|
TokenVerificationFailed: "token-verification-failed",
|
|
InvalidSecretKey: "secret-key-invalid",
|
|
LocalJWKMissing: "jwk-local-missing",
|
|
RemoteJWKFailedToLoad: "jwk-remote-failed-to-load",
|
|
RemoteJWKInvalid: "jwk-remote-invalid",
|
|
RemoteJWKMissing: "jwk-remote-missing",
|
|
JWKFailedToResolve: "jwk-failed-to-resolve",
|
|
JWKKidMismatch: "jwk-kid-mismatch"
|
|
};
|
|
var TokenVerificationErrorAction = {
|
|
ContactSupport: "Contact support@clerk.com",
|
|
EnsureClerkJWT: "Make sure that this is a valid Clerk-generated JWT.",
|
|
SetClerkJWTKey: "Set the CLERK_JWT_KEY environment variable.",
|
|
SetClerkSecretKey: "Set the CLERK_SECRET_KEY environment variable.",
|
|
EnsureClockSync: "Make sure your system clock is in sync (e.g. turn off and on automatic time synchronization)."
|
|
};
|
|
var TokenVerificationError = class _TokenVerificationError extends Error {
|
|
constructor({
|
|
action,
|
|
message,
|
|
reason
|
|
}) {
|
|
super(message);
|
|
Object.setPrototypeOf(this, _TokenVerificationError.prototype);
|
|
this.reason = reason;
|
|
this.message = message;
|
|
this.action = action;
|
|
}
|
|
getFullMessage() {
|
|
return `${[this.message, this.action].filter((m) => m).join(" ")} (reason=${this.reason}, token-carrier=${this.tokenCarrier})`;
|
|
}
|
|
};
|
|
var MachineTokenVerificationErrorCode = {
|
|
TokenInvalid: "token-invalid",
|
|
InvalidSecretKey: "secret-key-invalid",
|
|
UnexpectedError: "unexpected-error",
|
|
TokenVerificationFailed: "token-verification-failed"
|
|
};
|
|
var _MachineTokenVerificationError = class _MachineTokenVerificationError extends import_error2.ClerkError {
|
|
constructor({
|
|
message,
|
|
code,
|
|
status,
|
|
action
|
|
}) {
|
|
super({ message, code });
|
|
Object.setPrototypeOf(this, _MachineTokenVerificationError.prototype);
|
|
this.status = status;
|
|
this.action = action;
|
|
}
|
|
// Keep message unformatted, matching ClerkAPIResponseError's approach
|
|
static formatMessage(_name, msg, _code, _docsUrl) {
|
|
return msg;
|
|
}
|
|
getFullMessage() {
|
|
return `${this.message} (code=${this.code}, status=${this.status || "n/a"})`;
|
|
}
|
|
};
|
|
_MachineTokenVerificationError.kind = "MachineTokenVerificationError";
|
|
var MachineTokenVerificationError = _MachineTokenVerificationError;
|
|
|
|
// src/runtime.ts
|
|
var import_crypto = require("#crypto");
|
|
var globalFetch = fetch.bind(globalThis);
|
|
var runtime = {
|
|
crypto: import_crypto.webcrypto,
|
|
get fetch() {
|
|
return process.env.NODE_ENV === "test" ? fetch : globalFetch;
|
|
},
|
|
AbortController: globalThis.AbortController,
|
|
Blob: globalThis.Blob,
|
|
FormData: globalThis.FormData,
|
|
Headers: globalThis.Headers,
|
|
Request: globalThis.Request,
|
|
Response: globalThis.Response
|
|
};
|
|
|
|
// src/util/rfc4648.ts
|
|
var base64url = {
|
|
parse(string, opts) {
|
|
return parse(string, base64UrlEncoding, opts);
|
|
},
|
|
stringify(data, opts) {
|
|
return stringify(data, base64UrlEncoding, opts);
|
|
}
|
|
};
|
|
var base64UrlEncoding = {
|
|
chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
|
|
bits: 6
|
|
};
|
|
function parse(string, encoding, opts = {}) {
|
|
if (!encoding.codes) {
|
|
encoding.codes = {};
|
|
for (let i = 0; i < encoding.chars.length; ++i) {
|
|
encoding.codes[encoding.chars[i]] = i;
|
|
}
|
|
}
|
|
if (!opts.loose && string.length * encoding.bits & 7) {
|
|
throw new SyntaxError("Invalid padding");
|
|
}
|
|
let end = string.length;
|
|
while (string[end - 1] === "=") {
|
|
--end;
|
|
if (!opts.loose && !((string.length - end) * encoding.bits & 7)) {
|
|
throw new SyntaxError("Invalid padding");
|
|
}
|
|
}
|
|
const out = new (opts.out ?? Uint8Array)(end * encoding.bits / 8 | 0);
|
|
let bits = 0;
|
|
let buffer = 0;
|
|
let written = 0;
|
|
for (let i = 0; i < end; ++i) {
|
|
const value = encoding.codes[string[i]];
|
|
if (value === void 0) {
|
|
throw new SyntaxError("Invalid character " + string[i]);
|
|
}
|
|
buffer = buffer << encoding.bits | value;
|
|
bits += encoding.bits;
|
|
if (bits >= 8) {
|
|
bits -= 8;
|
|
out[written++] = 255 & buffer >> bits;
|
|
}
|
|
}
|
|
if (bits >= encoding.bits || 255 & buffer << 8 - bits) {
|
|
throw new SyntaxError("Unexpected end of data");
|
|
}
|
|
return out;
|
|
}
|
|
function stringify(data, encoding, opts = {}) {
|
|
const { pad = true } = opts;
|
|
const mask = (1 << encoding.bits) - 1;
|
|
let out = "";
|
|
let bits = 0;
|
|
let buffer = 0;
|
|
for (let i = 0; i < data.length; ++i) {
|
|
buffer = buffer << 8 | 255 & data[i];
|
|
bits += 8;
|
|
while (bits > encoding.bits) {
|
|
bits -= encoding.bits;
|
|
out += encoding.chars[mask & buffer >> bits];
|
|
}
|
|
}
|
|
if (bits) {
|
|
out += encoding.chars[mask & buffer << encoding.bits - bits];
|
|
}
|
|
if (pad) {
|
|
while (out.length * encoding.bits & 7) {
|
|
out += "=";
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// src/jwt/algorithms.ts
|
|
var algToHash = {
|
|
RS256: "SHA-256",
|
|
RS384: "SHA-384",
|
|
RS512: "SHA-512"
|
|
};
|
|
var RSA_ALGORITHM_NAME = "RSASSA-PKCS1-v1_5";
|
|
var jwksAlgToCryptoAlg = {
|
|
RS256: RSA_ALGORITHM_NAME,
|
|
RS384: RSA_ALGORITHM_NAME,
|
|
RS512: RSA_ALGORITHM_NAME
|
|
};
|
|
var algs = Object.keys(algToHash);
|
|
function getCryptoAlgorithm(algorithmName) {
|
|
const hash = algToHash[algorithmName];
|
|
const name = jwksAlgToCryptoAlg[algorithmName];
|
|
if (!hash || !name) {
|
|
throw new Error(`Unsupported algorithm ${algorithmName}, expected one of ${algs.join(",")}.`);
|
|
}
|
|
return {
|
|
hash: { name: algToHash[algorithmName] },
|
|
name: jwksAlgToCryptoAlg[algorithmName]
|
|
};
|
|
}
|
|
|
|
// src/jwt/assertions.ts
|
|
var isArrayString = (s) => {
|
|
return Array.isArray(s) && s.length > 0 && s.every((a) => typeof a === "string");
|
|
};
|
|
var assertAudienceClaim = (aud, audience) => {
|
|
const audienceList = [audience].flat().filter((a) => !!a);
|
|
const audList = [aud].flat().filter((a) => !!a);
|
|
const shouldVerifyAudience = audienceList.length > 0 && audList.length > 0;
|
|
if (!shouldVerifyAudience) {
|
|
return;
|
|
}
|
|
if (typeof aud === "string") {
|
|
if (!audienceList.includes(aud)) {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.EnsureClerkJWT,
|
|
reason: TokenVerificationErrorReason.TokenVerificationFailed,
|
|
message: `Invalid JWT audience claim (aud) ${JSON.stringify(aud)}. Is not included in "${JSON.stringify(
|
|
audienceList
|
|
)}".`
|
|
});
|
|
}
|
|
} else if (isArrayString(aud)) {
|
|
if (!aud.some((a) => audienceList.includes(a))) {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.EnsureClerkJWT,
|
|
reason: TokenVerificationErrorReason.TokenVerificationFailed,
|
|
message: `Invalid JWT audience claim array (aud) ${JSON.stringify(aud)}. Is not included in "${JSON.stringify(
|
|
audienceList
|
|
)}".`
|
|
});
|
|
}
|
|
}
|
|
};
|
|
var assertHeaderType = (typ, allowedTypes = "JWT") => {
|
|
if (typeof typ === "undefined") {
|
|
return;
|
|
}
|
|
const allowed = Array.isArray(allowedTypes) ? allowedTypes : [allowedTypes];
|
|
if (!allowed.includes(typ)) {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.EnsureClerkJWT,
|
|
reason: TokenVerificationErrorReason.TokenInvalid,
|
|
message: `Invalid JWT type ${JSON.stringify(typ)}. Expected "${allowed.join(", ")}".`
|
|
});
|
|
}
|
|
};
|
|
var assertHeaderAlgorithm = (alg) => {
|
|
if (!algs.includes(alg)) {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.EnsureClerkJWT,
|
|
reason: TokenVerificationErrorReason.TokenInvalidAlgorithm,
|
|
message: `Invalid JWT algorithm ${JSON.stringify(alg)}. Supported: ${algs}.`
|
|
});
|
|
}
|
|
};
|
|
var assertSubClaim = (sub) => {
|
|
if (typeof sub !== "string") {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.EnsureClerkJWT,
|
|
reason: TokenVerificationErrorReason.TokenVerificationFailed,
|
|
message: `Subject claim (sub) is required and must be a string. Received ${JSON.stringify(sub)}.`
|
|
});
|
|
}
|
|
};
|
|
var assertAuthorizedPartiesClaim = (azp, authorizedParties) => {
|
|
if (!azp || !authorizedParties || authorizedParties.length === 0) {
|
|
return;
|
|
}
|
|
if (!authorizedParties.includes(azp)) {
|
|
throw new TokenVerificationError({
|
|
reason: TokenVerificationErrorReason.TokenInvalidAuthorizedParties,
|
|
message: `Invalid JWT Authorized party claim (azp) ${JSON.stringify(azp)}. Expected "${authorizedParties}".`
|
|
});
|
|
}
|
|
};
|
|
var assertExpirationClaim = (exp, clockSkewInMs) => {
|
|
if (typeof exp !== "number") {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.EnsureClerkJWT,
|
|
reason: TokenVerificationErrorReason.TokenVerificationFailed,
|
|
message: `Invalid JWT expiry date claim (exp) ${JSON.stringify(exp)}. Expected number.`
|
|
});
|
|
}
|
|
const currentDate = new Date(Date.now());
|
|
const expiryDate = /* @__PURE__ */ new Date(0);
|
|
expiryDate.setUTCSeconds(exp);
|
|
const expired = expiryDate.getTime() <= currentDate.getTime() - clockSkewInMs;
|
|
if (expired) {
|
|
throw new TokenVerificationError({
|
|
reason: TokenVerificationErrorReason.TokenExpired,
|
|
message: `JWT is expired. Expiry date: ${expiryDate.toUTCString()}, Current date: ${currentDate.toUTCString()}.`
|
|
});
|
|
}
|
|
};
|
|
var assertActivationClaim = (nbf, clockSkewInMs) => {
|
|
if (typeof nbf === "undefined") {
|
|
return;
|
|
}
|
|
if (typeof nbf !== "number") {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.EnsureClerkJWT,
|
|
reason: TokenVerificationErrorReason.TokenVerificationFailed,
|
|
message: `Invalid JWT not before date claim (nbf) ${JSON.stringify(nbf)}. Expected number.`
|
|
});
|
|
}
|
|
const currentDate = new Date(Date.now());
|
|
const notBeforeDate = /* @__PURE__ */ new Date(0);
|
|
notBeforeDate.setUTCSeconds(nbf);
|
|
const early = notBeforeDate.getTime() > currentDate.getTime() + clockSkewInMs;
|
|
if (early) {
|
|
throw new TokenVerificationError({
|
|
reason: TokenVerificationErrorReason.TokenNotActiveYet,
|
|
message: `JWT cannot be used prior to not before date claim (nbf). Not before date: ${notBeforeDate.toUTCString()}; Current date: ${currentDate.toUTCString()};`
|
|
});
|
|
}
|
|
};
|
|
var assertIssuedAtClaim = (iat, clockSkewInMs) => {
|
|
if (typeof iat === "undefined") {
|
|
return;
|
|
}
|
|
if (typeof iat !== "number") {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.EnsureClerkJWT,
|
|
reason: TokenVerificationErrorReason.TokenVerificationFailed,
|
|
message: `Invalid JWT issued at date claim (iat) ${JSON.stringify(iat)}. Expected number.`
|
|
});
|
|
}
|
|
const currentDate = new Date(Date.now());
|
|
const issuedAtDate = /* @__PURE__ */ new Date(0);
|
|
issuedAtDate.setUTCSeconds(iat);
|
|
const postIssued = issuedAtDate.getTime() > currentDate.getTime() + clockSkewInMs;
|
|
if (postIssued) {
|
|
throw new TokenVerificationError({
|
|
reason: TokenVerificationErrorReason.TokenIatInTheFuture,
|
|
message: `JWT issued at date claim (iat) is in the future. Issued at date: ${issuedAtDate.toUTCString()}; Current date: ${currentDate.toUTCString()};`
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/jwt/cryptoKeys.ts
|
|
var import_isomorphicAtob = require("@clerk/shared/isomorphicAtob");
|
|
function pemToBuffer(secret) {
|
|
const trimmed = secret.replace(/-----BEGIN.*?-----/g, "").replace(/-----END.*?-----/g, "").replace(/\s/g, "");
|
|
const decoded = (0, import_isomorphicAtob.isomorphicAtob)(trimmed);
|
|
const buffer = new ArrayBuffer(decoded.length);
|
|
const bufView = new Uint8Array(buffer);
|
|
for (let i = 0, strLen = decoded.length; i < strLen; i++) {
|
|
bufView[i] = decoded.charCodeAt(i);
|
|
}
|
|
return bufView;
|
|
}
|
|
function importKey(key, algorithm, keyUsage) {
|
|
if (typeof key === "object") {
|
|
return runtime.crypto.subtle.importKey("jwk", key, algorithm, false, [keyUsage]);
|
|
}
|
|
const keyData = pemToBuffer(key);
|
|
const format = keyUsage === "sign" ? "pkcs8" : "spki";
|
|
return runtime.crypto.subtle.importKey(format, keyData, algorithm, false, [keyUsage]);
|
|
}
|
|
|
|
// src/jwt/verifyJwt.ts
|
|
var DEFAULT_CLOCK_SKEW_IN_MS = 5 * 1e3;
|
|
async function hasValidSignature(jwt, key) {
|
|
const { header, signature, raw } = jwt;
|
|
const encoder = new TextEncoder();
|
|
const data = encoder.encode([raw.header, raw.payload].join("."));
|
|
const algorithm = getCryptoAlgorithm(header.alg);
|
|
try {
|
|
const cryptoKey = await importKey(key, algorithm, "verify");
|
|
const verified = await runtime.crypto.subtle.verify(algorithm.name, cryptoKey, signature, data);
|
|
return { data: verified };
|
|
} catch (error) {
|
|
return {
|
|
errors: [
|
|
new TokenVerificationError({
|
|
reason: TokenVerificationErrorReason.TokenInvalidSignature,
|
|
message: error?.message
|
|
})
|
|
]
|
|
};
|
|
}
|
|
}
|
|
function decodeJwt(token) {
|
|
const tokenParts = (token || "").toString().split(".");
|
|
if (tokenParts.length !== 3) {
|
|
return {
|
|
errors: [
|
|
new TokenVerificationError({
|
|
reason: TokenVerificationErrorReason.TokenInvalid,
|
|
message: `Invalid JWT form. A JWT consists of three parts separated by dots.`
|
|
})
|
|
]
|
|
};
|
|
}
|
|
const [rawHeader, rawPayload, rawSignature] = tokenParts;
|
|
const decoder = new TextDecoder();
|
|
const header = JSON.parse(decoder.decode(base64url.parse(rawHeader, { loose: true })));
|
|
const payload = JSON.parse(decoder.decode(base64url.parse(rawPayload, { loose: true })));
|
|
const signature = base64url.parse(rawSignature, { loose: true });
|
|
const data = {
|
|
header,
|
|
payload,
|
|
signature,
|
|
raw: {
|
|
header: rawHeader,
|
|
payload: rawPayload,
|
|
signature: rawSignature,
|
|
text: token
|
|
}
|
|
};
|
|
return { data };
|
|
}
|
|
async function verifyJwt(token, options) {
|
|
const { audience, authorizedParties, clockSkewInMs, key, headerType } = options;
|
|
const clockSkew = typeof clockSkewInMs === "number" && Number.isFinite(clockSkewInMs) ? clockSkewInMs : DEFAULT_CLOCK_SKEW_IN_MS;
|
|
const { data: decoded, errors } = decodeJwt(token);
|
|
if (errors) {
|
|
return { errors };
|
|
}
|
|
const { header, payload } = decoded;
|
|
try {
|
|
const { typ, alg } = header;
|
|
assertHeaderType(typ, headerType);
|
|
assertHeaderAlgorithm(alg);
|
|
} catch (err) {
|
|
return { errors: [err] };
|
|
}
|
|
const { data: signatureValid, errors: signatureErrors } = await hasValidSignature(decoded, key);
|
|
if (signatureErrors) {
|
|
return {
|
|
errors: [
|
|
new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.EnsureClerkJWT,
|
|
reason: TokenVerificationErrorReason.TokenVerificationFailed,
|
|
message: `Error verifying JWT signature. ${signatureErrors[0]}`
|
|
})
|
|
]
|
|
};
|
|
}
|
|
if (!signatureValid) {
|
|
return {
|
|
errors: [
|
|
new TokenVerificationError({
|
|
reason: TokenVerificationErrorReason.TokenInvalidSignature,
|
|
message: "JWT signature is invalid."
|
|
})
|
|
]
|
|
};
|
|
}
|
|
try {
|
|
const { azp, sub, aud, iat, exp, nbf } = payload;
|
|
assertSubClaim(sub);
|
|
assertAudienceClaim([aud], [audience]);
|
|
assertAuthorizedPartiesClaim(azp, authorizedParties);
|
|
assertExpirationClaim(exp, clockSkew);
|
|
assertActivationClaim(nbf, clockSkew);
|
|
assertIssuedAtClaim(iat, clockSkew);
|
|
} catch (err) {
|
|
return { errors: [err] };
|
|
}
|
|
return { data: payload };
|
|
}
|
|
|
|
// src/util/optionsAssertions.ts
|
|
function assertValidSecretKey(val) {
|
|
if (!val || typeof val !== "string") {
|
|
throw Error("Missing Clerk Secret Key. Go to https://dashboard.clerk.com and get your key for your instance.");
|
|
}
|
|
}
|
|
function assertValidPublishableKey(val) {
|
|
(0, import_keys.parsePublishableKey)(val, { fatal: true });
|
|
}
|
|
|
|
// src/tokens/authenticateContext.ts
|
|
var import_buildAccountsBaseUrl2 = require("@clerk/shared/buildAccountsBaseUrl");
|
|
var import_url2 = require("@clerk/shared/url");
|
|
|
|
// src/tokens/tokenTypes.ts
|
|
var TokenType = {
|
|
SessionToken: "session_token",
|
|
ApiKey: "api_key",
|
|
M2MToken: "m2m_token",
|
|
OAuthToken: "oauth_token"
|
|
};
|
|
|
|
// src/tokens/authenticateContext.ts
|
|
var AuthenticateContext = class {
|
|
constructor(cookieSuffix, clerkRequest, options) {
|
|
this.cookieSuffix = cookieSuffix;
|
|
this.clerkRequest = clerkRequest;
|
|
/**
|
|
* The original Clerk frontend API URL, extracted from publishable key before proxy URL override.
|
|
* Used for backend operations like token validation and issuer checking.
|
|
*/
|
|
this.originalFrontendApi = "";
|
|
if (options.acceptsToken === TokenType.M2MToken || options.acceptsToken === TokenType.ApiKey) {
|
|
this.initHeaderValues();
|
|
} else {
|
|
this.initPublishableKeyValues(options);
|
|
this.initHeaderValues();
|
|
this.initCookieValues();
|
|
this.initHandshakeValues();
|
|
}
|
|
Object.assign(this, options);
|
|
this.clerkUrl = this.clerkRequest.clerkUrl;
|
|
if (this.proxyUrl?.startsWith("/")) {
|
|
this.proxyUrl = `${this.clerkUrl.origin}${this.proxyUrl}`;
|
|
}
|
|
}
|
|
/**
|
|
* Retrieves the session token from either the cookie or the header.
|
|
*
|
|
* @returns {string | undefined} The session token if available, otherwise undefined.
|
|
*/
|
|
get sessionToken() {
|
|
return this.sessionTokenInCookie || this.tokenInHeader;
|
|
}
|
|
usesSuffixedCookies() {
|
|
const suffixedClientUat = this.getSuffixedCookie(constants.Cookies.ClientUat);
|
|
const clientUat = this.getCookie(constants.Cookies.ClientUat);
|
|
const suffixedSession = this.getSuffixedCookie(constants.Cookies.Session) || "";
|
|
const session = this.getCookie(constants.Cookies.Session) || "";
|
|
if (session && !this.tokenHasIssuer(session)) {
|
|
return false;
|
|
}
|
|
if (session && !this.tokenBelongsToInstance(session)) {
|
|
return true;
|
|
}
|
|
if (!suffixedClientUat && !suffixedSession) {
|
|
return false;
|
|
}
|
|
const { data: sessionData } = decodeJwt(session);
|
|
const sessionIat = sessionData?.payload.iat || 0;
|
|
const { data: suffixedSessionData } = decodeJwt(suffixedSession);
|
|
const suffixedSessionIat = suffixedSessionData?.payload.iat || 0;
|
|
if (suffixedClientUat !== "0" && clientUat !== "0" && sessionIat > suffixedSessionIat) {
|
|
return false;
|
|
}
|
|
if (suffixedClientUat === "0" && clientUat !== "0") {
|
|
return false;
|
|
}
|
|
if (this.instanceType !== "production") {
|
|
const isSuffixedSessionExpired = this.sessionExpired(suffixedSessionData);
|
|
if (suffixedClientUat !== "0" && clientUat === "0" && isSuffixedSessionExpired) {
|
|
return false;
|
|
}
|
|
}
|
|
if (!suffixedClientUat && suffixedSession) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
/**
|
|
* Determines if the request came from a different origin based on the referrer header.
|
|
* Used for cross-origin detection in multi-domain authentication flows.
|
|
*
|
|
* @returns {boolean} True if referrer exists and is from a different origin, false otherwise.
|
|
*/
|
|
isCrossOriginReferrer() {
|
|
if (!this.referrer || !this.clerkUrl.origin) {
|
|
return false;
|
|
}
|
|
try {
|
|
const referrerOrigin = new URL(this.referrer).origin;
|
|
return referrerOrigin !== this.clerkUrl.origin;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
/**
|
|
* Determines if the referrer URL is from a Clerk domain (accounts portal or FAPI).
|
|
* This includes both development and production account portal domains, as well as FAPI domains
|
|
* used for redirect-based authentication flows.
|
|
*
|
|
* @returns {boolean} True if the referrer is from a Clerk accounts portal or FAPI domain, false otherwise
|
|
*/
|
|
isKnownClerkReferrer() {
|
|
if (!this.referrer) {
|
|
return false;
|
|
}
|
|
try {
|
|
const referrerOrigin = new URL(this.referrer);
|
|
const referrerHost = referrerOrigin.hostname;
|
|
if (this.frontendApi) {
|
|
const fapiHost = this.frontendApi.startsWith("http") ? new URL(this.frontendApi).hostname : this.frontendApi;
|
|
if (referrerHost === fapiHost) {
|
|
return true;
|
|
}
|
|
}
|
|
if ((0, import_url2.isLegacyDevAccountPortalOrigin)(referrerHost) || (0, import_url2.isCurrentDevAccountPortalOrigin)(referrerHost)) {
|
|
return true;
|
|
}
|
|
const expectedAccountsUrl = (0, import_buildAccountsBaseUrl2.buildAccountsBaseUrl)(this.frontendApi);
|
|
if (expectedAccountsUrl) {
|
|
const expectedAccountsOrigin = new URL(expectedAccountsUrl).origin;
|
|
if (referrerOrigin.origin === expectedAccountsOrigin) {
|
|
return true;
|
|
}
|
|
}
|
|
if (referrerHost.startsWith("accounts.")) {
|
|
return true;
|
|
}
|
|
return false;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
initPublishableKeyValues(options) {
|
|
assertValidPublishableKey(options.publishableKey);
|
|
this.publishableKey = options.publishableKey;
|
|
let resolvedProxyUrl = options.proxyUrl;
|
|
if (resolvedProxyUrl?.startsWith("/")) {
|
|
resolvedProxyUrl = `${this.clerkRequest.clerkUrl.origin}${resolvedProxyUrl}`;
|
|
}
|
|
const originalPk = (0, import_keys.parsePublishableKey)(this.publishableKey, {
|
|
fatal: true,
|
|
domain: options.domain,
|
|
isSatellite: options.isSatellite
|
|
});
|
|
this.originalFrontendApi = originalPk.frontendApi;
|
|
const pk = (0, import_keys.parsePublishableKey)(this.publishableKey, {
|
|
fatal: true,
|
|
proxyUrl: resolvedProxyUrl,
|
|
domain: options.domain,
|
|
isSatellite: options.isSatellite
|
|
});
|
|
this.instanceType = pk.instanceType;
|
|
this.frontendApi = pk.frontendApi;
|
|
}
|
|
initHeaderValues() {
|
|
this.method = this.clerkRequest.method;
|
|
this.tokenInHeader = this.parseAuthorizationHeader(this.getHeader(constants.Headers.Authorization));
|
|
this.origin = this.getHeader(constants.Headers.Origin);
|
|
this.host = this.getHeader(constants.Headers.Host);
|
|
this.forwardedHost = this.getHeader(constants.Headers.ForwardedHost);
|
|
this.forwardedProto = this.getHeader(constants.Headers.CloudFrontForwardedProto) || this.getHeader(constants.Headers.ForwardedProto);
|
|
this.referrer = this.getHeader(constants.Headers.Referrer);
|
|
this.userAgent = this.getHeader(constants.Headers.UserAgent);
|
|
this.secFetchDest = this.getHeader(constants.Headers.SecFetchDest);
|
|
this.accept = this.getHeader(constants.Headers.Accept);
|
|
}
|
|
initCookieValues() {
|
|
this.sessionTokenInCookie = this.getSuffixedOrUnSuffixedCookie(constants.Cookies.Session);
|
|
this.refreshTokenInCookie = this.getSuffixedCookie(constants.Cookies.Refresh);
|
|
this.clientUat = Number.parseInt(this.getSuffixedOrUnSuffixedCookie(constants.Cookies.ClientUat) || "") || 0;
|
|
}
|
|
initHandshakeValues() {
|
|
this.devBrowserToken = this.getQueryParam(constants.QueryParameters.DevBrowser) || this.getSuffixedOrUnSuffixedCookie(constants.Cookies.DevBrowser);
|
|
this.handshakeToken = this.getQueryParam(constants.QueryParameters.Handshake) || this.getCookie(constants.Cookies.Handshake);
|
|
this.handshakeRedirectLoopCounter = Number(this.getCookie(constants.Cookies.RedirectCount)) || 0;
|
|
this.handshakeNonce = this.getQueryParam(constants.QueryParameters.HandshakeNonce) || this.getCookie(constants.Cookies.HandshakeNonce);
|
|
}
|
|
getQueryParam(name) {
|
|
return this.clerkRequest.clerkUrl.searchParams.get(name);
|
|
}
|
|
getHeader(name) {
|
|
return this.clerkRequest.headers.get(name) || void 0;
|
|
}
|
|
getCookie(name) {
|
|
return this.clerkRequest.cookies.get(name) || void 0;
|
|
}
|
|
getSuffixedCookie(name) {
|
|
return this.getCookie((0, import_keys.getSuffixedCookieName)(name, this.cookieSuffix)) || void 0;
|
|
}
|
|
getSuffixedOrUnSuffixedCookie(cookieName) {
|
|
if (this.usesSuffixedCookies()) {
|
|
return this.getSuffixedCookie(cookieName);
|
|
}
|
|
return this.getCookie(cookieName);
|
|
}
|
|
parseAuthorizationHeader(authorizationHeader) {
|
|
if (!authorizationHeader) {
|
|
return void 0;
|
|
}
|
|
const [scheme, token] = authorizationHeader.split(" ", 2);
|
|
if (!token) {
|
|
return scheme;
|
|
}
|
|
if (scheme === "Bearer") {
|
|
return token;
|
|
}
|
|
return void 0;
|
|
}
|
|
tokenHasIssuer(token) {
|
|
const { data, errors } = decodeJwt(token);
|
|
if (errors) {
|
|
return false;
|
|
}
|
|
return !!data.payload.iss;
|
|
}
|
|
tokenBelongsToInstance(token) {
|
|
if (!token) {
|
|
return false;
|
|
}
|
|
const { data, errors } = decodeJwt(token);
|
|
if (errors) {
|
|
return false;
|
|
}
|
|
const tokenIssuer = data.payload.iss.replace(/https?:\/\//gi, "");
|
|
return this.originalFrontendApi === tokenIssuer;
|
|
}
|
|
sessionExpired(jwt) {
|
|
return !!jwt && jwt?.payload.exp <= Date.now() / 1e3 >> 0;
|
|
}
|
|
};
|
|
var createAuthenticateContext = async (clerkRequest, options) => {
|
|
const cookieSuffix = options.publishableKey ? await (0, import_keys.getCookieSuffix)(options.publishableKey, runtime.crypto.subtle) : "";
|
|
return new AuthenticateContext(cookieSuffix, clerkRequest, options);
|
|
};
|
|
|
|
// src/tokens/authObjects.ts
|
|
var import_authorization = require("@clerk/shared/authorization");
|
|
var import_jwtPayloadParser = require("@clerk/shared/jwtPayloadParser");
|
|
|
|
// src/util/path.ts
|
|
var SEPARATOR = "/";
|
|
var MULTIPLE_SEPARATOR_REGEX = new RegExp("(?<!:)" + SEPARATOR + "{1,}", "g");
|
|
var MAX_DECODES = 10;
|
|
function isDotSegment(segment) {
|
|
let candidate = segment;
|
|
for (let i = 0; i <= MAX_DECODES; i++) {
|
|
if (candidate.split(/[/\\]/).some((p) => p === "." || p === "..")) {
|
|
return true;
|
|
}
|
|
if (i === MAX_DECODES) {
|
|
throw new Error(`joinPaths: too many layers of encoding in ${segment}`);
|
|
}
|
|
try {
|
|
const next = decodeURIComponent(candidate);
|
|
if (next === candidate) {
|
|
break;
|
|
}
|
|
candidate = next;
|
|
} catch {
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
function joinPaths(...args) {
|
|
const result = args.filter((p) => p).join(SEPARATOR).replace(MULTIPLE_SEPARATOR_REGEX, SEPARATOR);
|
|
for (const segment of result.split(SEPARATOR)) {
|
|
if (isDotSegment(segment)) {
|
|
throw new Error(`joinPaths: "." and ".." path segments are not allowed (received "${result}")`);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// src/api/endpoints/AbstractApi.ts
|
|
var AbstractAPI = class {
|
|
constructor(request) {
|
|
this.request = request;
|
|
}
|
|
requireId(id) {
|
|
if (!id) {
|
|
throw new Error("A valid resource ID is required.");
|
|
}
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/ActorTokenApi.ts
|
|
var basePath = "/actor_tokens";
|
|
var ActorTokenAPI = class extends AbstractAPI {
|
|
async create(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async revoke(actorTokenId) {
|
|
this.requireId(actorTokenId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath, actorTokenId, "revoke")
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/AgentTaskApi.ts
|
|
var basePath2 = "/agents/tasks";
|
|
var AgentTaskAPI = class extends AbstractAPI {
|
|
async create(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath2,
|
|
bodyParams: params,
|
|
options: {
|
|
deepSnakecaseBodyParamKeys: true
|
|
}
|
|
});
|
|
}
|
|
async revoke(agentTaskId) {
|
|
this.requireId(agentTaskId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath2, agentTaskId, "revoke")
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/AccountlessApplicationsAPI.ts
|
|
var basePath3 = "/accountless_applications";
|
|
var AccountlessApplicationAPI = class extends AbstractAPI {
|
|
async createAccountlessApplication(params) {
|
|
const headerParams = params?.requestHeaders ? Object.fromEntries(params.requestHeaders.entries()) : void 0;
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath3,
|
|
headerParams
|
|
});
|
|
}
|
|
async completeAccountlessApplicationOnboarding(params) {
|
|
const headerParams = params?.requestHeaders ? Object.fromEntries(params.requestHeaders.entries()) : void 0;
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath3, "complete"),
|
|
headerParams
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/AllowlistIdentifierApi.ts
|
|
var basePath4 = "/allowlist_identifiers";
|
|
var AllowlistIdentifierAPI = class extends AbstractAPI {
|
|
async getAllowlistIdentifierList(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath4,
|
|
queryParams: { ...params, paginated: true }
|
|
});
|
|
}
|
|
async createAllowlistIdentifier(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath4,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async deleteAllowlistIdentifier(allowlistIdentifierId) {
|
|
this.requireId(allowlistIdentifierId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath4, allowlistIdentifierId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/APIKeysApi.ts
|
|
var basePath5 = "/api_keys";
|
|
var APIKeysAPI = class extends AbstractAPI {
|
|
async list(queryParams) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath5,
|
|
queryParams
|
|
});
|
|
}
|
|
async create(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath5,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async get(apiKeyId) {
|
|
this.requireId(apiKeyId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath5, apiKeyId)
|
|
});
|
|
}
|
|
async update(params) {
|
|
const { apiKeyId, ...bodyParams } = params;
|
|
this.requireId(apiKeyId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath5, apiKeyId),
|
|
bodyParams
|
|
});
|
|
}
|
|
async delete(apiKeyId) {
|
|
this.requireId(apiKeyId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath5, apiKeyId)
|
|
});
|
|
}
|
|
async revoke(params) {
|
|
const { apiKeyId, revocationReason = null } = params;
|
|
this.requireId(apiKeyId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath5, apiKeyId, "revoke"),
|
|
bodyParams: { revocationReason }
|
|
});
|
|
}
|
|
async getSecret(apiKeyId) {
|
|
this.requireId(apiKeyId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath5, apiKeyId, "secret")
|
|
});
|
|
}
|
|
async verify(secret) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath5, "verify"),
|
|
bodyParams: { secret }
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/BetaFeaturesApi.ts
|
|
var basePath6 = "/beta_features";
|
|
var BetaFeaturesAPI = class extends AbstractAPI {
|
|
/**
|
|
* Change the domain of a production instance.
|
|
*
|
|
* Changing the domain requires updating the DNS records accordingly, deploying new SSL certificates,
|
|
* updating your Social Connection's redirect URLs and setting the new keys in your code.
|
|
*
|
|
* @remarks
|
|
* WARNING: Changing your domain will invalidate all current user sessions (i.e. users will be logged out).
|
|
* Also, while your application is being deployed, a small downtime is expected to occur.
|
|
*/
|
|
async changeDomain(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath6, "change_domain"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/BlocklistIdentifierApi.ts
|
|
var basePath7 = "/blocklist_identifiers";
|
|
var BlocklistIdentifierAPI = class extends AbstractAPI {
|
|
async getBlocklistIdentifierList(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath7,
|
|
queryParams: params
|
|
});
|
|
}
|
|
async createBlocklistIdentifier(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath7,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async deleteBlocklistIdentifier(blocklistIdentifierId) {
|
|
this.requireId(blocklistIdentifierId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath7, blocklistIdentifierId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/ClientApi.ts
|
|
var basePath8 = "/clients";
|
|
var ClientAPI = class extends AbstractAPI {
|
|
async getClientList(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath8,
|
|
queryParams: { ...params, paginated: true }
|
|
});
|
|
}
|
|
async getClient(clientId) {
|
|
this.requireId(clientId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath8, clientId)
|
|
});
|
|
}
|
|
verifyClient(token) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath8, "verify"),
|
|
bodyParams: { token }
|
|
});
|
|
}
|
|
async getHandshakePayload(queryParams) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath8, "handshake_payload"),
|
|
queryParams
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/DomainApi.ts
|
|
var basePath9 = "/domains";
|
|
var DomainAPI = class extends AbstractAPI {
|
|
async list() {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath9
|
|
});
|
|
}
|
|
async add(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath9,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async update(params) {
|
|
const { domainId, ...bodyParams } = params;
|
|
this.requireId(domainId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath9, domainId),
|
|
bodyParams
|
|
});
|
|
}
|
|
/**
|
|
* Deletes a satellite domain for the instance.
|
|
* It is currently not possible to delete the instance's primary domain.
|
|
*/
|
|
async delete(satelliteDomainId) {
|
|
return this.deleteDomain(satelliteDomainId);
|
|
}
|
|
/**
|
|
* @deprecated Use `delete` instead
|
|
*/
|
|
async deleteDomain(satelliteDomainId) {
|
|
this.requireId(satelliteDomainId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath9, satelliteDomainId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/EmailAddressApi.ts
|
|
var basePath10 = "/email_addresses";
|
|
var EmailAddressAPI = class extends AbstractAPI {
|
|
async getEmailAddress(emailAddressId) {
|
|
this.requireId(emailAddressId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath10, emailAddressId)
|
|
});
|
|
}
|
|
async createEmailAddress(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath10,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async updateEmailAddress(emailAddressId, params = {}) {
|
|
this.requireId(emailAddressId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath10, emailAddressId),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async deleteEmailAddress(emailAddressId) {
|
|
this.requireId(emailAddressId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath10, emailAddressId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/EnterpriseConnectionApi.ts
|
|
var basePath11 = "/enterprise_connections";
|
|
var EnterpriseConnectionAPI = class extends AbstractAPI {
|
|
async createEnterpriseConnection(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath11,
|
|
bodyParams: params,
|
|
options: {
|
|
deepSnakecaseBodyParamKeys: true
|
|
}
|
|
});
|
|
}
|
|
async updateEnterpriseConnection(enterpriseConnectionId, params) {
|
|
this.requireId(enterpriseConnectionId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath11, enterpriseConnectionId),
|
|
bodyParams: params,
|
|
options: {
|
|
deepSnakecaseBodyParamKeys: true
|
|
}
|
|
});
|
|
}
|
|
async getEnterpriseConnectionList(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath11,
|
|
queryParams: params
|
|
});
|
|
}
|
|
async getEnterpriseConnection(enterpriseConnectionId) {
|
|
this.requireId(enterpriseConnectionId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath11, enterpriseConnectionId)
|
|
});
|
|
}
|
|
async deleteEnterpriseConnection(enterpriseConnectionId) {
|
|
this.requireId(enterpriseConnectionId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath11, enterpriseConnectionId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/IdPOAuthAccessTokenApi.ts
|
|
var basePath12 = "/oauth_applications/access_tokens";
|
|
var IdPOAuthAccessTokenApi = class extends AbstractAPI {
|
|
async verify(accessToken) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath12, "verify"),
|
|
bodyParams: { access_token: accessToken }
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/InstanceApi.ts
|
|
var basePath13 = "/instance";
|
|
var InstanceAPI = class extends AbstractAPI {
|
|
async get() {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath13
|
|
});
|
|
}
|
|
async update(params) {
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: basePath13,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async updateRestrictions(params) {
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath13, "restrictions"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async getOrganizationSettings() {
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath13, "organization_settings")
|
|
});
|
|
}
|
|
async updateOrganizationSettings(params) {
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath13, "organization_settings"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/InvitationApi.ts
|
|
var basePath14 = "/invitations";
|
|
var InvitationAPI = class extends AbstractAPI {
|
|
async getInvitationList(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath14,
|
|
queryParams: { ...params, paginated: true }
|
|
});
|
|
}
|
|
async createInvitation(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath14,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async createInvitationBulk(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath14, "bulk"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async revokeInvitation(invitationId) {
|
|
this.requireId(invitationId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath14, invitationId, "revoke")
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/MachineApi.ts
|
|
var basePath15 = "/machines";
|
|
var MachineApi = class extends AbstractAPI {
|
|
async get(machineId) {
|
|
this.requireId(machineId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath15, machineId)
|
|
});
|
|
}
|
|
async list(queryParams = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath15,
|
|
queryParams
|
|
});
|
|
}
|
|
async create(bodyParams) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath15,
|
|
bodyParams
|
|
});
|
|
}
|
|
async update(params) {
|
|
const { machineId, ...bodyParams } = params;
|
|
this.requireId(machineId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath15, machineId),
|
|
bodyParams
|
|
});
|
|
}
|
|
async delete(machineId) {
|
|
this.requireId(machineId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath15, machineId)
|
|
});
|
|
}
|
|
async getSecretKey(machineId) {
|
|
this.requireId(machineId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath15, machineId, "secret_key")
|
|
});
|
|
}
|
|
async rotateSecretKey(params) {
|
|
const { machineId, previousTokenTtl } = params;
|
|
this.requireId(machineId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath15, machineId, "secret_key", "rotate"),
|
|
bodyParams: {
|
|
previousTokenTtl
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Creates a new machine scope, allowing the specified machine to access another machine.
|
|
*
|
|
* @param machineId - The ID of the machine that will have access to another machine.
|
|
* @param toMachineId - The ID of the machine that will be scoped to the current machine.
|
|
*/
|
|
async createScope(machineId, toMachineId) {
|
|
this.requireId(machineId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath15, machineId, "scopes"),
|
|
bodyParams: {
|
|
toMachineId
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Deletes a machine scope, removing access from one machine to another.
|
|
*
|
|
* @param machineId - The ID of the machine that has access to another machine.
|
|
* @param otherMachineId - The ID of the machine that is being accessed.
|
|
*/
|
|
async deleteScope(machineId, otherMachineId) {
|
|
this.requireId(machineId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath15, machineId, "scopes", otherMachineId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/resources/IdPOAuthAccessToken.ts
|
|
var IdPOAuthAccessToken = class _IdPOAuthAccessToken {
|
|
constructor(id, clientId, type, subject, scopes, revoked, revocationReason, expired, expiration, createdAt, updatedAt) {
|
|
this.id = id;
|
|
this.clientId = clientId;
|
|
this.type = type;
|
|
this.subject = subject;
|
|
this.scopes = scopes;
|
|
this.revoked = revoked;
|
|
this.revocationReason = revocationReason;
|
|
this.expired = expired;
|
|
this.expiration = expiration;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _IdPOAuthAccessToken(
|
|
data.id,
|
|
data.client_id,
|
|
data.type,
|
|
data.subject,
|
|
data.scopes,
|
|
data.revoked,
|
|
data.revocation_reason,
|
|
data.expired,
|
|
data.expiration,
|
|
data.created_at,
|
|
data.updated_at
|
|
);
|
|
}
|
|
/**
|
|
* Creates an IdPOAuthAccessToken from a JWT payload.
|
|
* Maps standard JWT claims and OAuth-specific fields to token properties.
|
|
*/
|
|
static fromJwtPayload(payload, clockSkewInMs = 5e3) {
|
|
const oauthPayload = payload;
|
|
return new _IdPOAuthAccessToken(
|
|
oauthPayload.jti ?? "",
|
|
oauthPayload.client_id ?? "",
|
|
"oauth_token",
|
|
payload.sub,
|
|
oauthPayload.scp ?? oauthPayload.scope?.split(" ") ?? [],
|
|
false,
|
|
null,
|
|
payload.exp * 1e3 <= Date.now() - clockSkewInMs,
|
|
payload.exp,
|
|
payload.iat,
|
|
payload.iat
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/M2MToken.ts
|
|
var M2MToken = class _M2MToken {
|
|
constructor(id, subject, scopes, claims, revoked, revocationReason, expired, expiration, createdAt, updatedAt, token) {
|
|
this.id = id;
|
|
this.subject = subject;
|
|
this.scopes = scopes;
|
|
this.claims = claims;
|
|
this.revoked = revoked;
|
|
this.revocationReason = revocationReason;
|
|
this.expired = expired;
|
|
this.expiration = expiration;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.token = token;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _M2MToken(
|
|
data.id,
|
|
data.subject,
|
|
data.scopes,
|
|
data.claims,
|
|
data.revoked,
|
|
data.revocation_reason,
|
|
data.expired,
|
|
data.expiration,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.token
|
|
);
|
|
}
|
|
static fromJwtPayload(payload, clockSkewInMs = 5e3) {
|
|
return new _M2MToken(
|
|
payload.jti ?? "",
|
|
// jti should always be present in Clerk-issued M2M JWTs
|
|
payload.sub,
|
|
payload.scopes?.split(" ") ?? payload.aud ?? [],
|
|
null,
|
|
false,
|
|
null,
|
|
payload.exp * 1e3 <= Date.now() - clockSkewInMs,
|
|
payload.exp * 1e3,
|
|
// milliseconds — expiration, converted from JWT exp claim
|
|
payload.iat * 1e3,
|
|
// milliseconds — createdAt, converted from JWT iat claim
|
|
payload.iat * 1e3
|
|
// milliseconds — updatedAt, no JWT equivalent; defaults to iat
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/tokens/keys.ts
|
|
var cache = {};
|
|
var lastUpdatedAt = 0;
|
|
function getFromCache(kid) {
|
|
return cache[kid];
|
|
}
|
|
function getCacheValues() {
|
|
return Object.values(cache);
|
|
}
|
|
function setInCache(cacheKey, jwk, shouldExpire = true) {
|
|
cache[cacheKey] = jwk;
|
|
lastUpdatedAt = shouldExpire ? Date.now() : -1;
|
|
}
|
|
var PEM_HEADER = "-----BEGIN PUBLIC KEY-----";
|
|
var PEM_TRAILER = "-----END PUBLIC KEY-----";
|
|
var RSA_PREFIX = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA";
|
|
var RSA_SUFFIX = "IDAQAB";
|
|
function loadClerkJwkFromPem(params) {
|
|
const { kid, pem } = params;
|
|
const prefixedKid = `local-${kid}`;
|
|
const cachedJwk = getFromCache(prefixedKid);
|
|
if (cachedJwk) {
|
|
return cachedJwk;
|
|
}
|
|
if (!pem) {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.SetClerkJWTKey,
|
|
message: "Missing local JWK.",
|
|
reason: TokenVerificationErrorReason.LocalJWKMissing
|
|
});
|
|
}
|
|
const modulus = pem.replace(/\r\n|\n|\r/g, "").replace(PEM_HEADER, "").replace(PEM_TRAILER, "").replace(RSA_PREFIX, "").replace(RSA_SUFFIX, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
const jwk = { kid: prefixedKid, kty: "RSA", alg: "RS256", n: modulus, e: "AQAB" };
|
|
setInCache(prefixedKid, jwk, false);
|
|
return jwk;
|
|
}
|
|
async function loadClerkJWKFromRemote(params) {
|
|
const { secretKey, apiUrl = API_URL, apiVersion = API_VERSION, kid, skipJwksCache } = params;
|
|
if (skipJwksCache || cacheHasExpired() || !getFromCache(kid)) {
|
|
if (!secretKey) {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.ContactSupport,
|
|
message: "Failed to load JWKS from Clerk Backend or Frontend API.",
|
|
reason: TokenVerificationErrorReason.RemoteJWKFailedToLoad
|
|
});
|
|
}
|
|
const fetcher = () => fetchJWKSFromBAPI(apiUrl, secretKey, apiVersion);
|
|
const { keys } = await (0, import_retry.retry)(fetcher);
|
|
if (!keys || !keys.length) {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.ContactSupport,
|
|
message: "The JWKS endpoint did not contain any signing keys. Contact support@clerk.com.",
|
|
reason: TokenVerificationErrorReason.RemoteJWKFailedToLoad
|
|
});
|
|
}
|
|
keys.forEach((key) => setInCache(key.kid, key));
|
|
}
|
|
const jwk = getFromCache(kid);
|
|
if (!jwk) {
|
|
const cacheValues = getCacheValues();
|
|
const jwkKeys = cacheValues.map((jwk2) => jwk2.kid).sort().join(", ");
|
|
throw new TokenVerificationError({
|
|
action: `Go to your Dashboard and validate your secret and public keys are correct. ${TokenVerificationErrorAction.ContactSupport} if the issue persists.`,
|
|
message: `Unable to find a signing key in JWKS that matches the kid='${kid}' of the provided session token. Please make sure that the __session cookie or the HTTP authorization header contain a Clerk-generated session JWT. The following kid is available: ${jwkKeys}`,
|
|
reason: TokenVerificationErrorReason.JWKKidMismatch
|
|
});
|
|
}
|
|
return jwk;
|
|
}
|
|
async function fetchJWKSFromBAPI(apiUrl, key, apiVersion) {
|
|
if (!key) {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.SetClerkSecretKey,
|
|
message: "Missing Clerk Secret Key or API Key. Go to https://dashboard.clerk.com and get your key for your instance.",
|
|
reason: TokenVerificationErrorReason.RemoteJWKFailedToLoad
|
|
});
|
|
}
|
|
const url = new URL(apiUrl);
|
|
url.pathname = joinPaths(url.pathname, apiVersion, "/jwks");
|
|
const response = await runtime.fetch(url.href, {
|
|
headers: {
|
|
Authorization: `Bearer ${key}`,
|
|
"Clerk-API-Version": SUPPORTED_BAPI_VERSION,
|
|
"Content-Type": "application/json",
|
|
"User-Agent": USER_AGENT
|
|
}
|
|
});
|
|
if (!response.ok) {
|
|
const json = await response.json();
|
|
const invalidSecretKeyError = getErrorObjectByCode(json?.errors, TokenVerificationErrorCode.InvalidSecretKey);
|
|
if (invalidSecretKeyError) {
|
|
const reason = TokenVerificationErrorReason.InvalidSecretKey;
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.ContactSupport,
|
|
message: invalidSecretKeyError.message,
|
|
reason
|
|
});
|
|
}
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.ContactSupport,
|
|
message: `Error loading Clerk JWKS from ${url.href} with code=${response.status}`,
|
|
reason: TokenVerificationErrorReason.RemoteJWKFailedToLoad
|
|
});
|
|
}
|
|
return response.json();
|
|
}
|
|
function cacheHasExpired() {
|
|
if (lastUpdatedAt === -1) {
|
|
return false;
|
|
}
|
|
const isExpired = Date.now() - lastUpdatedAt >= MAX_CACHE_LAST_UPDATED_AT_SECONDS * 1e3;
|
|
if (isExpired) {
|
|
cache = {};
|
|
}
|
|
return isExpired;
|
|
}
|
|
var getErrorObjectByCode = (errors, code) => {
|
|
if (!errors) {
|
|
return null;
|
|
}
|
|
return errors.find((err) => err.code === code);
|
|
};
|
|
|
|
// src/tokens/machine.ts
|
|
var M2M_TOKEN_PREFIX = "mt_";
|
|
var M2M_SUBJECT_PREFIX = "mch_";
|
|
var OAUTH_TOKEN_PREFIX = "oat_";
|
|
var API_KEY_PREFIX = "ak_";
|
|
var MACHINE_TOKEN_PREFIXES = [M2M_TOKEN_PREFIX, OAUTH_TOKEN_PREFIX, API_KEY_PREFIX];
|
|
var JwtFormatRegExp = /^[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+$/;
|
|
function isJwtFormat(token) {
|
|
return JwtFormatRegExp.test(token);
|
|
}
|
|
var OAUTH_ACCESS_TOKEN_TYPES = ["at+jwt", "application/at+jwt"];
|
|
function isOAuthJwt(token) {
|
|
if (!isJwtFormat(token)) {
|
|
return false;
|
|
}
|
|
try {
|
|
const { data, errors } = decodeJwt(token);
|
|
return !errors && !!data && OAUTH_ACCESS_TOKEN_TYPES.includes(data.header.typ);
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
function isM2MJwt(token) {
|
|
if (!isJwtFormat(token)) {
|
|
return false;
|
|
}
|
|
try {
|
|
const { data, errors } = decodeJwt(token);
|
|
return !errors && !!data && typeof data.payload.sub === "string" && data.payload.sub.startsWith(M2M_SUBJECT_PREFIX);
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
function isMachineJwt(token) {
|
|
return isOAuthJwt(token) || isM2MJwt(token);
|
|
}
|
|
function isMachineTokenByPrefix(token) {
|
|
return MACHINE_TOKEN_PREFIXES.some((prefix) => token.startsWith(prefix));
|
|
}
|
|
function isMachineToken(token) {
|
|
return isMachineTokenByPrefix(token) || isOAuthJwt(token) || isM2MJwt(token);
|
|
}
|
|
function getMachineTokenType(token) {
|
|
if (token.startsWith(M2M_TOKEN_PREFIX) || isM2MJwt(token)) {
|
|
return TokenType.M2MToken;
|
|
}
|
|
if (token.startsWith(OAUTH_TOKEN_PREFIX) || isOAuthJwt(token)) {
|
|
return TokenType.OAuthToken;
|
|
}
|
|
if (token.startsWith(API_KEY_PREFIX)) {
|
|
return TokenType.ApiKey;
|
|
}
|
|
throw new Error("Unknown machine token type");
|
|
}
|
|
var isTokenTypeAccepted = (tokenType, acceptsToken) => {
|
|
if (!tokenType) {
|
|
return false;
|
|
}
|
|
if (acceptsToken === "any") {
|
|
return true;
|
|
}
|
|
const tokenTypes = Array.isArray(acceptsToken) ? acceptsToken : [acceptsToken];
|
|
return tokenTypes.includes(tokenType);
|
|
};
|
|
var MACHINE_TOKEN_TYPES = /* @__PURE__ */ new Set([TokenType.ApiKey, TokenType.M2MToken, TokenType.OAuthToken]);
|
|
function isMachineTokenType(type) {
|
|
return MACHINE_TOKEN_TYPES.has(type);
|
|
}
|
|
|
|
// src/jwt/verifyMachineJwt.ts
|
|
async function resolveKeyAndVerifyJwt(token, kid, options, headerType) {
|
|
try {
|
|
let key;
|
|
if (options.jwtKey) {
|
|
key = loadClerkJwkFromPem({ kid, pem: options.jwtKey });
|
|
} else if (options.secretKey) {
|
|
key = await loadClerkJWKFromRemote({ ...options, kid });
|
|
} else {
|
|
return {
|
|
error: new MachineTokenVerificationError({
|
|
action: TokenVerificationErrorAction.SetClerkJWTKey,
|
|
message: "Failed to resolve JWK during verification.",
|
|
code: MachineTokenVerificationErrorCode.TokenVerificationFailed
|
|
})
|
|
};
|
|
}
|
|
const { data: payload, errors: verifyErrors } = await verifyJwt(token, {
|
|
...options,
|
|
key,
|
|
...headerType ? { headerType } : {}
|
|
});
|
|
if (verifyErrors) {
|
|
return {
|
|
error: new MachineTokenVerificationError({
|
|
code: MachineTokenVerificationErrorCode.TokenVerificationFailed,
|
|
message: verifyErrors[0].message
|
|
})
|
|
};
|
|
}
|
|
return { payload };
|
|
} catch (error) {
|
|
return {
|
|
error: new MachineTokenVerificationError({
|
|
code: MachineTokenVerificationErrorCode.TokenVerificationFailed,
|
|
message: error.message
|
|
})
|
|
};
|
|
}
|
|
}
|
|
async function verifyM2MJwt(token, decoded, options) {
|
|
const result = await resolveKeyAndVerifyJwt(token, decoded.header.kid, options);
|
|
if ("error" in result) {
|
|
return { data: void 0, tokenType: TokenType.M2MToken, errors: [result.error] };
|
|
}
|
|
return {
|
|
data: M2MToken.fromJwtPayload(result.payload, options.clockSkewInMs),
|
|
tokenType: TokenType.M2MToken,
|
|
errors: void 0
|
|
};
|
|
}
|
|
async function verifyOAuthJwt(token, decoded, options) {
|
|
const result = await resolveKeyAndVerifyJwt(token, decoded.header.kid, options, OAUTH_ACCESS_TOKEN_TYPES);
|
|
if ("error" in result) {
|
|
return { data: void 0, tokenType: TokenType.OAuthToken, errors: [result.error] };
|
|
}
|
|
return {
|
|
data: IdPOAuthAccessToken.fromJwtPayload(result.payload, options.clockSkewInMs),
|
|
tokenType: TokenType.OAuthToken,
|
|
errors: void 0
|
|
};
|
|
}
|
|
|
|
// src/api/endpoints/M2MTokenApi.ts
|
|
var basePath16 = "/m2m_tokens";
|
|
var _verifyOptions, _M2MTokenApi_instances, createRequestOptions_fn, verifyJwtFormat_fn;
|
|
var M2MTokenApi = class extends AbstractAPI {
|
|
/**
|
|
* @param verifyOptions - JWT verification options (secretKey, apiUrl, etc.).
|
|
* Passed explicitly because BuildRequestOptions are captured inside the buildRequest closure
|
|
* and are not accessible from the RequestFunction itself.
|
|
*/
|
|
constructor(request, verifyOptions = {}) {
|
|
super(request);
|
|
__privateAdd(this, _M2MTokenApi_instances);
|
|
__privateAdd(this, _verifyOptions);
|
|
__privateSet(this, _verifyOptions, verifyOptions);
|
|
}
|
|
async list(queryParams) {
|
|
const { machineSecretKey, ...params } = queryParams;
|
|
const requestOptions = __privateMethod(this, _M2MTokenApi_instances, createRequestOptions_fn).call(this, {
|
|
method: "GET",
|
|
path: basePath16,
|
|
queryParams: params
|
|
}, machineSecretKey);
|
|
return this.request(requestOptions);
|
|
}
|
|
async createToken(params) {
|
|
const { claims = null, machineSecretKey, secondsUntilExpiration = null, tokenFormat = "opaque" } = params || {};
|
|
const requestOptions = __privateMethod(this, _M2MTokenApi_instances, createRequestOptions_fn).call(this, {
|
|
method: "POST",
|
|
path: basePath16,
|
|
bodyParams: {
|
|
secondsUntilExpiration,
|
|
claims,
|
|
tokenFormat
|
|
}
|
|
}, machineSecretKey);
|
|
return this.request(requestOptions);
|
|
}
|
|
async revokeToken(params) {
|
|
const { m2mTokenId, revocationReason = null, machineSecretKey } = params;
|
|
this.requireId(m2mTokenId);
|
|
const requestOptions = __privateMethod(this, _M2MTokenApi_instances, createRequestOptions_fn).call(this, {
|
|
method: "POST",
|
|
path: joinPaths(basePath16, m2mTokenId, "revoke"),
|
|
bodyParams: {
|
|
revocationReason
|
|
}
|
|
}, machineSecretKey);
|
|
return this.request(requestOptions);
|
|
}
|
|
async verify(params) {
|
|
const { token, machineSecretKey } = params;
|
|
if (isM2MJwt(token)) {
|
|
return __privateMethod(this, _M2MTokenApi_instances, verifyJwtFormat_fn).call(this, token);
|
|
}
|
|
const requestOptions = __privateMethod(this, _M2MTokenApi_instances, createRequestOptions_fn).call(this, {
|
|
method: "POST",
|
|
path: joinPaths(basePath16, "verify"),
|
|
bodyParams: { token }
|
|
}, machineSecretKey);
|
|
return this.request(requestOptions);
|
|
}
|
|
};
|
|
_verifyOptions = new WeakMap();
|
|
_M2MTokenApi_instances = new WeakSet();
|
|
createRequestOptions_fn = function(options, machineSecretKey) {
|
|
if (machineSecretKey) {
|
|
return {
|
|
...options,
|
|
headerParams: {
|
|
...options.headerParams,
|
|
Authorization: `Bearer ${machineSecretKey}`
|
|
}
|
|
};
|
|
}
|
|
return options;
|
|
};
|
|
verifyJwtFormat_fn = async function(token) {
|
|
let decoded;
|
|
try {
|
|
const { data, errors } = decodeJwt(token);
|
|
if (errors) {
|
|
throw errors[0];
|
|
}
|
|
decoded = data;
|
|
} catch (e) {
|
|
throw new MachineTokenVerificationError({
|
|
code: MachineTokenVerificationErrorCode.TokenInvalid,
|
|
message: e.message
|
|
});
|
|
}
|
|
const result = await verifyM2MJwt(token, decoded, __privateGet(this, _verifyOptions));
|
|
if (result.errors) {
|
|
throw result.errors[0];
|
|
}
|
|
return result.data;
|
|
};
|
|
|
|
// src/api/endpoints/JwksApi.ts
|
|
var basePath17 = "/jwks";
|
|
var JwksAPI = class extends AbstractAPI {
|
|
async getJwks() {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath17
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/JwtTemplatesApi.ts
|
|
var basePath18 = "/jwt_templates";
|
|
var JwtTemplatesApi = class extends AbstractAPI {
|
|
async list(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath18,
|
|
queryParams: { ...params, paginated: true }
|
|
});
|
|
}
|
|
async get(templateId) {
|
|
this.requireId(templateId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath18, templateId)
|
|
});
|
|
}
|
|
async create(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath18,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async update(params) {
|
|
const { templateId, ...bodyParams } = params;
|
|
this.requireId(templateId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath18, templateId),
|
|
bodyParams
|
|
});
|
|
}
|
|
async delete(templateId) {
|
|
this.requireId(templateId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath18, templateId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/OrganizationApi.ts
|
|
var basePath19 = "/organizations";
|
|
var OrganizationAPI = class extends AbstractAPI {
|
|
async getOrganizationList(params) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath19,
|
|
queryParams: params
|
|
});
|
|
}
|
|
async createOrganization(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath19,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async getOrganization(params) {
|
|
const { includeMembersCount } = params;
|
|
const organizationIdOrSlug = "organizationId" in params ? params.organizationId : params.slug;
|
|
this.requireId(organizationIdOrSlug);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath19, organizationIdOrSlug),
|
|
queryParams: {
|
|
includeMembersCount
|
|
}
|
|
});
|
|
}
|
|
async updateOrganization(organizationId, params) {
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath19, organizationId),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async updateOrganizationLogo(organizationId, params) {
|
|
this.requireId(organizationId);
|
|
const formData = new runtime.FormData();
|
|
formData.append("file", params?.file);
|
|
if (params?.uploaderUserId) {
|
|
formData.append("uploader_user_id", params?.uploaderUserId);
|
|
}
|
|
return this.request({
|
|
method: "PUT",
|
|
path: joinPaths(basePath19, organizationId, "logo"),
|
|
formData
|
|
});
|
|
}
|
|
async deleteOrganizationLogo(organizationId) {
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath19, organizationId, "logo")
|
|
});
|
|
}
|
|
async updateOrganizationMetadata(organizationId, params) {
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath19, organizationId, "metadata"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async deleteOrganization(organizationId) {
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath19, organizationId)
|
|
});
|
|
}
|
|
async getOrganizationMembershipList(params) {
|
|
const { organizationId, ...queryParams } = params;
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath19, organizationId, "memberships"),
|
|
queryParams
|
|
});
|
|
}
|
|
async getInstanceOrganizationMembershipList(params) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: "/organization_memberships",
|
|
queryParams: params
|
|
});
|
|
}
|
|
async createOrganizationMembership(params) {
|
|
const { organizationId, ...bodyParams } = params;
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath19, organizationId, "memberships"),
|
|
bodyParams
|
|
});
|
|
}
|
|
async updateOrganizationMembership(params) {
|
|
const { organizationId, userId, ...bodyParams } = params;
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath19, organizationId, "memberships", userId),
|
|
bodyParams
|
|
});
|
|
}
|
|
async updateOrganizationMembershipMetadata(params) {
|
|
const { organizationId, userId, ...bodyParams } = params;
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath19, organizationId, "memberships", userId, "metadata"),
|
|
bodyParams
|
|
});
|
|
}
|
|
async deleteOrganizationMembership(params) {
|
|
const { organizationId, userId } = params;
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath19, organizationId, "memberships", userId)
|
|
});
|
|
}
|
|
async getOrganizationInvitationList(params) {
|
|
const { organizationId, ...queryParams } = params;
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath19, organizationId, "invitations"),
|
|
queryParams
|
|
});
|
|
}
|
|
async createOrganizationInvitation(params) {
|
|
const { organizationId, ...bodyParams } = params;
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath19, organizationId, "invitations"),
|
|
bodyParams
|
|
});
|
|
}
|
|
async createOrganizationInvitationBulk(organizationId, params) {
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath19, organizationId, "invitations", "bulk"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async getOrganizationInvitation(params) {
|
|
const { organizationId, invitationId } = params;
|
|
this.requireId(organizationId);
|
|
this.requireId(invitationId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath19, organizationId, "invitations", invitationId)
|
|
});
|
|
}
|
|
async revokeOrganizationInvitation(params) {
|
|
const { organizationId, invitationId, ...bodyParams } = params;
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath19, organizationId, "invitations", invitationId, "revoke"),
|
|
bodyParams
|
|
});
|
|
}
|
|
async getOrganizationDomainList(params) {
|
|
const { organizationId, ...queryParams } = params;
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath19, organizationId, "domains"),
|
|
queryParams
|
|
});
|
|
}
|
|
async createOrganizationDomain(params) {
|
|
const { organizationId, ...bodyParams } = params;
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath19, organizationId, "domains"),
|
|
bodyParams: {
|
|
...bodyParams,
|
|
verified: bodyParams.verified ?? true
|
|
}
|
|
});
|
|
}
|
|
async updateOrganizationDomain(params) {
|
|
const { organizationId, domainId, ...bodyParams } = params;
|
|
this.requireId(organizationId);
|
|
this.requireId(domainId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath19, organizationId, "domains", domainId),
|
|
bodyParams
|
|
});
|
|
}
|
|
async deleteOrganizationDomain(params) {
|
|
const { organizationId, domainId } = params;
|
|
this.requireId(organizationId);
|
|
this.requireId(domainId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath19, organizationId, "domains", domainId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/OAuthApplicationsApi.ts
|
|
var basePath20 = "/oauth_applications";
|
|
var OAuthApplicationsApi = class extends AbstractAPI {
|
|
async list(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath20,
|
|
queryParams: params
|
|
});
|
|
}
|
|
async get(oauthApplicationId) {
|
|
this.requireId(oauthApplicationId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath20, oauthApplicationId)
|
|
});
|
|
}
|
|
async create(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath20,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async update(params) {
|
|
const { oauthApplicationId, ...bodyParams } = params;
|
|
this.requireId(oauthApplicationId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath20, oauthApplicationId),
|
|
bodyParams
|
|
});
|
|
}
|
|
async delete(oauthApplicationId) {
|
|
this.requireId(oauthApplicationId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath20, oauthApplicationId)
|
|
});
|
|
}
|
|
async rotateSecret(oauthApplicationId) {
|
|
this.requireId(oauthApplicationId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath20, oauthApplicationId, "rotate_secret")
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/PhoneNumberApi.ts
|
|
var basePath21 = "/phone_numbers";
|
|
var PhoneNumberAPI = class extends AbstractAPI {
|
|
async getPhoneNumber(phoneNumberId) {
|
|
this.requireId(phoneNumberId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath21, phoneNumberId)
|
|
});
|
|
}
|
|
async createPhoneNumber(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath21,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async updatePhoneNumber(phoneNumberId, params = {}) {
|
|
this.requireId(phoneNumberId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath21, phoneNumberId),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async deletePhoneNumber(phoneNumberId) {
|
|
this.requireId(phoneNumberId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath21, phoneNumberId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/ProxyCheckApi.ts
|
|
var basePath22 = "/proxy_checks";
|
|
var ProxyCheckAPI = class extends AbstractAPI {
|
|
async verify(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath22,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/RedirectUrlApi.ts
|
|
var basePath23 = "/redirect_urls";
|
|
var RedirectUrlAPI = class extends AbstractAPI {
|
|
async getRedirectUrlList() {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath23,
|
|
queryParams: { paginated: true }
|
|
});
|
|
}
|
|
async getRedirectUrl(redirectUrlId) {
|
|
this.requireId(redirectUrlId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath23, redirectUrlId)
|
|
});
|
|
}
|
|
async createRedirectUrl(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath23,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async deleteRedirectUrl(redirectUrlId) {
|
|
this.requireId(redirectUrlId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath23, redirectUrlId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/SamlConnectionApi.ts
|
|
var basePath24 = "/saml_connections";
|
|
var SamlConnectionAPI = class extends AbstractAPI {
|
|
async getSamlConnectionList(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath24,
|
|
queryParams: params
|
|
});
|
|
}
|
|
async createSamlConnection(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath24,
|
|
bodyParams: params,
|
|
options: {
|
|
deepSnakecaseBodyParamKeys: true
|
|
}
|
|
});
|
|
}
|
|
async getSamlConnection(samlConnectionId) {
|
|
this.requireId(samlConnectionId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath24, samlConnectionId)
|
|
});
|
|
}
|
|
async updateSamlConnection(samlConnectionId, params = {}) {
|
|
this.requireId(samlConnectionId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath24, samlConnectionId),
|
|
bodyParams: params,
|
|
options: {
|
|
deepSnakecaseBodyParamKeys: true
|
|
}
|
|
});
|
|
}
|
|
async deleteSamlConnection(samlConnectionId) {
|
|
this.requireId(samlConnectionId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath24, samlConnectionId)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/SessionApi.ts
|
|
var basePath25 = "/sessions";
|
|
var SessionAPI = class extends AbstractAPI {
|
|
async getSessionList(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath25,
|
|
queryParams: { ...params, paginated: true }
|
|
});
|
|
}
|
|
async getSession(sessionId) {
|
|
this.requireId(sessionId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath25, sessionId)
|
|
});
|
|
}
|
|
async createSession(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath25,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async revokeSession(sessionId) {
|
|
this.requireId(sessionId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath25, sessionId, "revoke")
|
|
});
|
|
}
|
|
async verifySession(sessionId, token) {
|
|
this.requireId(sessionId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath25, sessionId, "verify"),
|
|
bodyParams: { token }
|
|
});
|
|
}
|
|
/**
|
|
* Retrieves a session token or generates a JWT using a specified template.
|
|
*
|
|
* @param sessionId - The ID of the session for which to generate the token
|
|
* @param template - Optional name of the JWT template configured in the Clerk Dashboard.
|
|
* @param expiresInSeconds - Optional expiration time for the token in seconds.
|
|
* If not provided, uses the default expiration.
|
|
*
|
|
* @returns A promise that resolves to the generated token
|
|
*
|
|
* @throws {Error} When sessionId is invalid or empty
|
|
*/
|
|
async getToken(sessionId, template, expiresInSeconds) {
|
|
this.requireId(sessionId);
|
|
const path = template ? joinPaths(basePath25, sessionId, "tokens", template) : joinPaths(basePath25, sessionId, "tokens");
|
|
const requestOptions = {
|
|
method: "POST",
|
|
path
|
|
};
|
|
if (expiresInSeconds !== void 0) {
|
|
requestOptions.bodyParams = { expires_in_seconds: expiresInSeconds };
|
|
}
|
|
return this.request(requestOptions);
|
|
}
|
|
async refreshSession(sessionId, params) {
|
|
this.requireId(sessionId);
|
|
const { suffixed_cookies, ...restParams } = params;
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath25, sessionId, "refresh"),
|
|
bodyParams: restParams,
|
|
queryParams: { suffixed_cookies }
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/SignInTokenApi.ts
|
|
var basePath26 = "/sign_in_tokens";
|
|
var SignInTokenAPI = class extends AbstractAPI {
|
|
async createSignInToken(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath26,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async revokeSignInToken(signInTokenId) {
|
|
this.requireId(signInTokenId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath26, signInTokenId, "revoke")
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/SignUpApi.ts
|
|
var basePath27 = "/sign_ups";
|
|
var SignUpAPI = class extends AbstractAPI {
|
|
async get(signUpAttemptId) {
|
|
this.requireId(signUpAttemptId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath27, signUpAttemptId)
|
|
});
|
|
}
|
|
async update(params) {
|
|
const { signUpAttemptId, ...bodyParams } = params;
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath27, signUpAttemptId),
|
|
bodyParams
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/TestingTokenApi.ts
|
|
var basePath28 = "/testing_tokens";
|
|
var TestingTokenAPI = class extends AbstractAPI {
|
|
async createTestingToken() {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath28
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/UserApi.ts
|
|
var basePath29 = "/users";
|
|
var UserAPI = class extends AbstractAPI {
|
|
async getUserList(params = {}) {
|
|
const { limit, offset, orderBy, ...userCountParams } = params;
|
|
const [data, totalCount] = await Promise.all([
|
|
this.request({
|
|
method: "GET",
|
|
path: basePath29,
|
|
queryParams: params
|
|
}),
|
|
this.getCount(userCountParams)
|
|
]);
|
|
return { data, totalCount };
|
|
}
|
|
async getUser(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath29, userId)
|
|
});
|
|
}
|
|
async createUser(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath29,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async updateUser(userId, params = {}) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath29, userId),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async updateUserProfileImage(userId, params) {
|
|
this.requireId(userId);
|
|
const formData = new runtime.FormData();
|
|
formData.append("file", params?.file);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath29, userId, "profile_image"),
|
|
formData
|
|
});
|
|
}
|
|
async updateUserMetadata(userId, params) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "PATCH",
|
|
path: joinPaths(basePath29, userId, "metadata"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async deleteUser(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath29, userId)
|
|
});
|
|
}
|
|
async getCount(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath29, "count"),
|
|
queryParams: params
|
|
});
|
|
}
|
|
async getUserOauthAccessToken(userId, provider) {
|
|
this.requireId(userId);
|
|
const hasPrefix = provider.startsWith("oauth_");
|
|
const _provider = hasPrefix ? provider : `oauth_${provider}`;
|
|
if (hasPrefix) {
|
|
(0, import_deprecated.deprecated)(
|
|
"getUserOauthAccessToken(userId, provider)",
|
|
"Remove the `oauth_` prefix from the `provider` argument."
|
|
);
|
|
}
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath29, userId, "oauth_access_tokens", _provider),
|
|
queryParams: { paginated: true }
|
|
});
|
|
}
|
|
async disableUserMFA(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath29, userId, "mfa")
|
|
});
|
|
}
|
|
async getOrganizationMembershipList(params) {
|
|
const { userId, limit, offset } = params;
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath29, userId, "organization_memberships"),
|
|
queryParams: { limit, offset }
|
|
});
|
|
}
|
|
async getOrganizationInvitationList(params) {
|
|
const { userId, ...queryParams } = params;
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath29, userId, "organization_invitations"),
|
|
queryParams
|
|
});
|
|
}
|
|
async verifyPassword(params) {
|
|
const { userId, password } = params;
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath29, userId, "verify_password"),
|
|
bodyParams: { password }
|
|
});
|
|
}
|
|
async verifyTOTP(params) {
|
|
const { userId, code } = params;
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath29, userId, "verify_totp"),
|
|
bodyParams: { code }
|
|
});
|
|
}
|
|
async banUser(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath29, userId, "ban")
|
|
});
|
|
}
|
|
async unbanUser(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath29, userId, "unban")
|
|
});
|
|
}
|
|
async lockUser(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath29, userId, "lock")
|
|
});
|
|
}
|
|
async unlockUser(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath29, userId, "unlock")
|
|
});
|
|
}
|
|
async deleteUserProfileImage(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath29, userId, "profile_image")
|
|
});
|
|
}
|
|
async deleteUserPasskey(params) {
|
|
this.requireId(params.userId);
|
|
this.requireId(params.passkeyIdentificationId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath29, params.userId, "passkeys", params.passkeyIdentificationId)
|
|
});
|
|
}
|
|
async deleteUserWeb3Wallet(params) {
|
|
this.requireId(params.userId);
|
|
this.requireId(params.web3WalletIdentificationId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath29, params.userId, "web3_wallets", params.web3WalletIdentificationId)
|
|
});
|
|
}
|
|
async deleteUserExternalAccount(params) {
|
|
this.requireId(params.userId);
|
|
this.requireId(params.externalAccountId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath29, params.userId, "external_accounts", params.externalAccountId)
|
|
});
|
|
}
|
|
async deleteUserBackupCodes(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath29, userId, "backup_code")
|
|
});
|
|
}
|
|
async deleteUserTOTP(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath29, userId, "totp")
|
|
});
|
|
}
|
|
async setPasswordCompromised(userId, params = {
|
|
revokeAllSessions: false
|
|
}) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath29, userId, "password", "set_compromised"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
async unsetPasswordCompromised(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath29, userId, "password", "unset_compromised")
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/WaitlistEntryApi.ts
|
|
var basePath30 = "/waitlist_entries";
|
|
var WaitlistEntryAPI = class extends AbstractAPI {
|
|
/**
|
|
* List waitlist entries.
|
|
* @param params Optional parameters (e.g., `query`, `status`, `orderBy`).
|
|
*/
|
|
async list(params = {}) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: basePath30,
|
|
queryParams: params
|
|
});
|
|
}
|
|
/**
|
|
* Create a waitlist entry.
|
|
* @param params The parameters for creating a waitlist entry.
|
|
*/
|
|
async create(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: basePath30,
|
|
bodyParams: params
|
|
});
|
|
}
|
|
/**
|
|
* Bulk create waitlist entries.
|
|
* @param params An array of parameters for creating waitlist entries.
|
|
*/
|
|
async createBulk(params) {
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath30, "bulk"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
/**
|
|
* Invite a waitlist entry.
|
|
* @param id The waitlist entry ID.
|
|
* @param params Optional parameters (e.g., `ignoreExisting`).
|
|
*/
|
|
async invite(id, params = {}) {
|
|
this.requireId(id);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath30, id, "invite"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
/**
|
|
* Reject a waitlist entry.
|
|
* @param id The waitlist entry ID.
|
|
*/
|
|
async reject(id) {
|
|
this.requireId(id);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath30, id, "reject")
|
|
});
|
|
}
|
|
/**
|
|
* Delete a waitlist entry.
|
|
* @param id The waitlist entry ID.
|
|
*/
|
|
async delete(id) {
|
|
this.requireId(id);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath30, id)
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/WebhookApi.ts
|
|
var basePath31 = "/webhooks";
|
|
var WebhookAPI = class extends AbstractAPI {
|
|
async createSvixApp() {
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath31, "svix")
|
|
});
|
|
}
|
|
async generateSvixAuthURL() {
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths(basePath31, "svix_url")
|
|
});
|
|
}
|
|
async deleteSvixApp() {
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath31, "svix")
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/endpoints/BillingApi.ts
|
|
var basePath32 = "/billing";
|
|
var organizationBasePath = "/organizations";
|
|
var userBasePath = "/users";
|
|
var BillingAPI = class extends AbstractAPI {
|
|
/**
|
|
* @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
|
|
*/
|
|
async getPlanList(params) {
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(basePath32, "plans"),
|
|
queryParams: params
|
|
});
|
|
}
|
|
/**
|
|
* @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
|
|
*/
|
|
async cancelSubscriptionItem(subscriptionItemId, params) {
|
|
this.requireId(subscriptionItemId);
|
|
return this.request({
|
|
method: "DELETE",
|
|
path: joinPaths(basePath32, "subscription_items", subscriptionItemId),
|
|
queryParams: params
|
|
});
|
|
}
|
|
/**
|
|
* @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
|
|
*/
|
|
async extendSubscriptionItemFreeTrial(subscriptionItemId, params) {
|
|
this.requireId(subscriptionItemId);
|
|
return this.request({
|
|
method: "POST",
|
|
path: joinPaths("/billing", "subscription_items", subscriptionItemId, "extend_free_trial"),
|
|
bodyParams: params
|
|
});
|
|
}
|
|
/**
|
|
* @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
|
|
*/
|
|
async getOrganizationBillingSubscription(organizationId) {
|
|
this.requireId(organizationId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(organizationBasePath, organizationId, "billing", "subscription")
|
|
});
|
|
}
|
|
/**
|
|
* @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
|
|
*/
|
|
async getUserBillingSubscription(userId) {
|
|
this.requireId(userId);
|
|
return this.request({
|
|
method: "GET",
|
|
path: joinPaths(userBasePath, userId, "billing", "subscription")
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/api/request.ts
|
|
var import_error4 = require("@clerk/shared/error");
|
|
|
|
// ../../node_modules/.pnpm/map-obj@5.0.2/node_modules/map-obj/index.js
|
|
var isObject = (value) => typeof value === "object" && value !== null;
|
|
var isObjectCustom = (value) => isObject(value) && !(value instanceof RegExp) && !(value instanceof Error) && !(value instanceof Date) && !(globalThis.Blob && value instanceof globalThis.Blob);
|
|
var mapObjectSkip = /* @__PURE__ */ Symbol("mapObjectSkip");
|
|
var _mapObject = (object, mapper, options, isSeen = /* @__PURE__ */ new WeakMap()) => {
|
|
options = {
|
|
deep: false,
|
|
target: {},
|
|
...options
|
|
};
|
|
if (isSeen.has(object)) {
|
|
return isSeen.get(object);
|
|
}
|
|
isSeen.set(object, options.target);
|
|
const { target } = options;
|
|
delete options.target;
|
|
const mapArray = (array) => array.map((element) => isObjectCustom(element) ? _mapObject(element, mapper, options, isSeen) : element);
|
|
if (Array.isArray(object)) {
|
|
return mapArray(object);
|
|
}
|
|
for (const [key, value] of Object.entries(object)) {
|
|
const mapResult = mapper(key, value, object);
|
|
if (mapResult === mapObjectSkip) {
|
|
continue;
|
|
}
|
|
let [newKey, newValue, { shouldRecurse = true } = {}] = mapResult;
|
|
if (newKey === "__proto__") {
|
|
continue;
|
|
}
|
|
if (options.deep && shouldRecurse && isObjectCustom(newValue)) {
|
|
newValue = Array.isArray(newValue) ? mapArray(newValue) : _mapObject(newValue, mapper, options, isSeen);
|
|
}
|
|
target[newKey] = newValue;
|
|
}
|
|
return target;
|
|
};
|
|
function mapObject(object, mapper, options) {
|
|
if (!isObject(object)) {
|
|
throw new TypeError(`Expected an object, got \`${object}\` (${typeof object})`);
|
|
}
|
|
if (Array.isArray(object)) {
|
|
throw new TypeError("Expected an object, got an array");
|
|
}
|
|
return _mapObject(object, mapper, options);
|
|
}
|
|
|
|
// ../../node_modules/.pnpm/change-case@5.4.4/node_modules/change-case/dist/index.js
|
|
var SPLIT_LOWER_UPPER_RE = /([\p{Ll}\d])(\p{Lu})/gu;
|
|
var SPLIT_UPPER_UPPER_RE = /(\p{Lu})([\p{Lu}][\p{Ll}])/gu;
|
|
var SPLIT_SEPARATE_NUMBER_RE = /(\d)\p{Ll}|(\p{L})\d/u;
|
|
var DEFAULT_STRIP_REGEXP = /[^\p{L}\d]+/giu;
|
|
var SPLIT_REPLACE_VALUE = "$1\0$2";
|
|
var DEFAULT_PREFIX_SUFFIX_CHARACTERS = "";
|
|
function split(value) {
|
|
let result = value.trim();
|
|
result = result.replace(SPLIT_LOWER_UPPER_RE, SPLIT_REPLACE_VALUE).replace(SPLIT_UPPER_UPPER_RE, SPLIT_REPLACE_VALUE);
|
|
result = result.replace(DEFAULT_STRIP_REGEXP, "\0");
|
|
let start = 0;
|
|
let end = result.length;
|
|
while (result.charAt(start) === "\0")
|
|
start++;
|
|
if (start === end)
|
|
return [];
|
|
while (result.charAt(end - 1) === "\0")
|
|
end--;
|
|
return result.slice(start, end).split(/\0/g);
|
|
}
|
|
function splitSeparateNumbers(value) {
|
|
const words = split(value);
|
|
for (let i = 0; i < words.length; i++) {
|
|
const word = words[i];
|
|
const match2 = SPLIT_SEPARATE_NUMBER_RE.exec(word);
|
|
if (match2) {
|
|
const offset = match2.index + (match2[1] ?? match2[2]).length;
|
|
words.splice(i, 1, word.slice(0, offset), word.slice(offset));
|
|
}
|
|
}
|
|
return words;
|
|
}
|
|
function noCase(input, options) {
|
|
const [prefix, words, suffix] = splitPrefixSuffix(input, options);
|
|
return prefix + words.map(lowerFactory(options?.locale)).join(options?.delimiter ?? " ") + suffix;
|
|
}
|
|
function snakeCase(input, options) {
|
|
return noCase(input, { delimiter: "_", ...options });
|
|
}
|
|
function lowerFactory(locale) {
|
|
return locale === false ? (input) => input.toLowerCase() : (input) => input.toLocaleLowerCase(locale);
|
|
}
|
|
function splitPrefixSuffix(input, options = {}) {
|
|
const splitFn = options.split ?? (options.separateNumbers ? splitSeparateNumbers : split);
|
|
const prefixCharacters = options.prefixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS;
|
|
const suffixCharacters = options.suffixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS;
|
|
let prefixIndex = 0;
|
|
let suffixIndex = input.length;
|
|
while (prefixIndex < input.length) {
|
|
const char = input.charAt(prefixIndex);
|
|
if (!prefixCharacters.includes(char))
|
|
break;
|
|
prefixIndex++;
|
|
}
|
|
while (suffixIndex > prefixIndex) {
|
|
const index = suffixIndex - 1;
|
|
const char = input.charAt(index);
|
|
if (!suffixCharacters.includes(char))
|
|
break;
|
|
suffixIndex = index;
|
|
}
|
|
return [
|
|
input.slice(0, prefixIndex),
|
|
splitFn(input.slice(prefixIndex, suffixIndex)),
|
|
input.slice(suffixIndex)
|
|
];
|
|
}
|
|
|
|
// ../../node_modules/.pnpm/snakecase-keys@9.0.2/node_modules/snakecase-keys/index.js
|
|
var PlainObjectConstructor = {}.constructor;
|
|
function snakecaseKeys(obj, options) {
|
|
if (Array.isArray(obj)) {
|
|
if (obj.some((item) => item.constructor !== PlainObjectConstructor)) {
|
|
throw new Error("obj must be array of plain objects");
|
|
}
|
|
options = { deep: true, exclude: [], parsingOptions: {}, ...options };
|
|
const convertCase2 = options.snakeCase || ((key) => snakeCase(key, options.parsingOptions));
|
|
return obj.map((item) => {
|
|
return mapObject(item, (key, val) => {
|
|
return [
|
|
matches(options.exclude, key) ? key : convertCase2(key),
|
|
val,
|
|
mapperOptions(key, val, options)
|
|
];
|
|
}, options);
|
|
});
|
|
} else {
|
|
if (obj.constructor !== PlainObjectConstructor) {
|
|
throw new Error("obj must be an plain object");
|
|
}
|
|
}
|
|
options = { deep: true, exclude: [], parsingOptions: {}, ...options };
|
|
const convertCase = options.snakeCase || ((key) => snakeCase(key, options.parsingOptions));
|
|
return mapObject(obj, (key, val) => {
|
|
return [
|
|
matches(options.exclude, key) ? key : convertCase(key),
|
|
val,
|
|
mapperOptions(key, val, options)
|
|
];
|
|
}, options);
|
|
}
|
|
function matches(patterns, value) {
|
|
return patterns.some((pattern) => {
|
|
return typeof pattern === "string" ? pattern === value : pattern.test(value);
|
|
});
|
|
}
|
|
function mapperOptions(key, val, options) {
|
|
return options.shouldRecurse ? { shouldRecurse: options.shouldRecurse(key, val) } : void 0;
|
|
}
|
|
var snakecase_keys_default = snakecaseKeys;
|
|
|
|
// src/api/resources/AccountlessApplication.ts
|
|
var AccountlessApplication = class _AccountlessApplication {
|
|
constructor(publishableKey, secretKey, claimUrl, apiKeysUrl) {
|
|
this.publishableKey = publishableKey;
|
|
this.secretKey = secretKey;
|
|
this.claimUrl = claimUrl;
|
|
this.apiKeysUrl = apiKeysUrl;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _AccountlessApplication(data.publishable_key, data.secret_key, data.claim_url, data.api_keys_url);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/AgentTask.ts
|
|
var AgentTask = class _AgentTask {
|
|
constructor(agentId, taskId, url) {
|
|
this.agentId = agentId;
|
|
this.taskId = taskId;
|
|
this.url = url;
|
|
}
|
|
/**
|
|
* Creates a AgentTask instance from a JSON object.
|
|
*
|
|
* @param data - The JSON object containing agent task data
|
|
* @returns A new AgentTask instance
|
|
*/
|
|
static fromJSON(data) {
|
|
return new _AgentTask(data.agent_id, data.task_id, data.url);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/ActorToken.ts
|
|
var ActorToken = class _ActorToken {
|
|
constructor(id, status, userId, actor, token, url, createdAt, updatedAt) {
|
|
this.id = id;
|
|
this.status = status;
|
|
this.userId = userId;
|
|
this.actor = actor;
|
|
this.token = token;
|
|
this.url = url;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _ActorToken(
|
|
data.id,
|
|
data.status,
|
|
data.user_id,
|
|
data.actor,
|
|
data.token,
|
|
data.url,
|
|
data.created_at,
|
|
data.updated_at
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/AllowlistIdentifier.ts
|
|
var AllowlistIdentifier = class _AllowlistIdentifier {
|
|
constructor(id, identifier, identifierType, createdAt, updatedAt, instanceId, invitationId) {
|
|
this.id = id;
|
|
this.identifier = identifier;
|
|
this.identifierType = identifierType;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.instanceId = instanceId;
|
|
this.invitationId = invitationId;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _AllowlistIdentifier(
|
|
data.id,
|
|
data.identifier,
|
|
data.identifier_type,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.instance_id,
|
|
data.invitation_id
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/APIKey.ts
|
|
var APIKey = class _APIKey {
|
|
constructor(id, type, name, subject, scopes, claims, revoked, revocationReason, expired, expiration, createdBy, description, lastUsedAt, createdAt, updatedAt, secret) {
|
|
this.id = id;
|
|
this.type = type;
|
|
this.name = name;
|
|
this.subject = subject;
|
|
this.scopes = scopes;
|
|
this.claims = claims;
|
|
this.revoked = revoked;
|
|
this.revocationReason = revocationReason;
|
|
this.expired = expired;
|
|
this.expiration = expiration;
|
|
this.createdBy = createdBy;
|
|
this.description = description;
|
|
this.lastUsedAt = lastUsedAt;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.secret = secret;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _APIKey(
|
|
data.id,
|
|
data.type,
|
|
data.name,
|
|
data.subject,
|
|
data.scopes,
|
|
data.claims,
|
|
data.revoked,
|
|
data.revocation_reason,
|
|
data.expired,
|
|
data.expiration,
|
|
data.created_by,
|
|
data.description,
|
|
data.last_used_at,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.secret
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/BlocklistIdentifier.ts
|
|
var BlocklistIdentifier = class _BlocklistIdentifier {
|
|
constructor(id, identifier, identifierType, createdAt, updatedAt, instanceId) {
|
|
this.id = id;
|
|
this.identifier = identifier;
|
|
this.identifierType = identifierType;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.instanceId = instanceId;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _BlocklistIdentifier(
|
|
data.id,
|
|
data.identifier,
|
|
data.identifier_type,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.instance_id
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Session.ts
|
|
var SessionActivity = class _SessionActivity {
|
|
constructor(id, isMobile, ipAddress, city, country, browserVersion, browserName, deviceType) {
|
|
this.id = id;
|
|
this.isMobile = isMobile;
|
|
this.ipAddress = ipAddress;
|
|
this.city = city;
|
|
this.country = country;
|
|
this.browserVersion = browserVersion;
|
|
this.browserName = browserName;
|
|
this.deviceType = deviceType;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _SessionActivity(
|
|
data.id,
|
|
data.is_mobile,
|
|
data.ip_address,
|
|
data.city,
|
|
data.country,
|
|
data.browser_version,
|
|
data.browser_name,
|
|
data.device_type
|
|
);
|
|
}
|
|
};
|
|
var Session = class _Session {
|
|
constructor(id, clientId, userId, status, lastActiveAt, expireAt, abandonAt, createdAt, updatedAt, lastActiveOrganizationId, latestActivity, actor = null) {
|
|
this.id = id;
|
|
this.clientId = clientId;
|
|
this.userId = userId;
|
|
this.status = status;
|
|
this.lastActiveAt = lastActiveAt;
|
|
this.expireAt = expireAt;
|
|
this.abandonAt = abandonAt;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.lastActiveOrganizationId = lastActiveOrganizationId;
|
|
this.latestActivity = latestActivity;
|
|
this.actor = actor;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Session(
|
|
data.id,
|
|
data.client_id,
|
|
data.user_id,
|
|
data.status,
|
|
data.last_active_at,
|
|
data.expire_at,
|
|
data.abandon_at,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.last_active_organization_id,
|
|
data.latest_activity && SessionActivity.fromJSON(data.latest_activity),
|
|
data.actor
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Client.ts
|
|
var Client = class _Client {
|
|
constructor(id, sessionIds, sessions, signInId, signUpId, lastActiveSessionId, lastAuthenticationStrategy, createdAt, updatedAt) {
|
|
this.id = id;
|
|
this.sessionIds = sessionIds;
|
|
this.sessions = sessions;
|
|
this.signInId = signInId;
|
|
this.signUpId = signUpId;
|
|
this.lastActiveSessionId = lastActiveSessionId;
|
|
this.lastAuthenticationStrategy = lastAuthenticationStrategy;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Client(
|
|
data.id,
|
|
data.session_ids,
|
|
data.sessions.map((x) => Session.fromJSON(x)),
|
|
data.sign_in_id,
|
|
data.sign_up_id,
|
|
data.last_active_session_id,
|
|
data.last_authentication_strategy,
|
|
data.created_at,
|
|
data.updated_at
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/CnameTarget.ts
|
|
var CnameTarget = class _CnameTarget {
|
|
constructor(host, value, required) {
|
|
this.host = host;
|
|
this.value = value;
|
|
this.required = required;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _CnameTarget(data.host, data.value, data.required);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Cookies.ts
|
|
var Cookies2 = class _Cookies {
|
|
constructor(cookies) {
|
|
this.cookies = cookies;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Cookies(data.cookies);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/DeletedObject.ts
|
|
var DeletedObject = class _DeletedObject {
|
|
constructor(object, id, slug, deleted) {
|
|
this.object = object;
|
|
this.id = id;
|
|
this.slug = slug;
|
|
this.deleted = deleted;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _DeletedObject(data.object, data.id || null, data.slug || null, data.deleted);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Domain.ts
|
|
var Domain = class _Domain {
|
|
constructor(id, name, isSatellite, frontendApiUrl, developmentOrigin, cnameTargets, accountsPortalUrl, proxyUrl) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.isSatellite = isSatellite;
|
|
this.frontendApiUrl = frontendApiUrl;
|
|
this.developmentOrigin = developmentOrigin;
|
|
this.cnameTargets = cnameTargets;
|
|
this.accountsPortalUrl = accountsPortalUrl;
|
|
this.proxyUrl = proxyUrl;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Domain(
|
|
data.id,
|
|
data.name,
|
|
data.is_satellite,
|
|
data.frontend_api_url,
|
|
data.development_origin,
|
|
data.cname_targets && data.cname_targets.map((x) => CnameTarget.fromJSON(x)),
|
|
data.accounts_portal_url,
|
|
data.proxy_url
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Email.ts
|
|
var Email = class _Email {
|
|
constructor(id, fromEmailName, emailAddressId, toEmailAddress, subject, body, bodyPlain, status, slug, data, deliveredByClerk) {
|
|
this.id = id;
|
|
this.fromEmailName = fromEmailName;
|
|
this.emailAddressId = emailAddressId;
|
|
this.toEmailAddress = toEmailAddress;
|
|
this.subject = subject;
|
|
this.body = body;
|
|
this.bodyPlain = bodyPlain;
|
|
this.status = status;
|
|
this.slug = slug;
|
|
this.data = data;
|
|
this.deliveredByClerk = deliveredByClerk;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Email(
|
|
data.id,
|
|
data.from_email_name,
|
|
data.email_address_id,
|
|
data.to_email_address,
|
|
data.subject,
|
|
data.body,
|
|
data.body_plain,
|
|
data.status,
|
|
data.slug,
|
|
data.data,
|
|
data.delivered_by_clerk
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/IdentificationLink.ts
|
|
var IdentificationLink = class _IdentificationLink {
|
|
constructor(id, type) {
|
|
this.id = id;
|
|
this.type = type;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _IdentificationLink(data.id, data.type);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Verification.ts
|
|
var Verification = class _Verification {
|
|
constructor(status, strategy, externalVerificationRedirectURL = null, attempts = null, expireAt = null, nonce = null, message = null) {
|
|
this.status = status;
|
|
this.strategy = strategy;
|
|
this.externalVerificationRedirectURL = externalVerificationRedirectURL;
|
|
this.attempts = attempts;
|
|
this.expireAt = expireAt;
|
|
this.nonce = nonce;
|
|
this.message = message;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Verification(
|
|
data.status,
|
|
data.strategy,
|
|
data.external_verification_redirect_url ? new URL(data.external_verification_redirect_url) : null,
|
|
data.attempts,
|
|
data.expire_at,
|
|
data.nonce
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/EmailAddress.ts
|
|
var EmailAddress = class _EmailAddress {
|
|
constructor(id, emailAddress, verification, linkedTo) {
|
|
this.id = id;
|
|
this.emailAddress = emailAddress;
|
|
this.verification = verification;
|
|
this.linkedTo = linkedTo;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _EmailAddress(
|
|
data.id,
|
|
data.email_address,
|
|
data.verification && Verification.fromJSON(data.verification),
|
|
data.linked_to.map((link) => IdentificationLink.fromJSON(link))
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Feature.ts
|
|
var Feature = class _Feature {
|
|
constructor(id, name, description, slug, avatarUrl) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.description = description;
|
|
this.slug = slug;
|
|
this.avatarUrl = avatarUrl;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Feature(data.id, data.name, data.description ?? null, data.slug, data.avatar_url ?? null);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/CommercePlan.ts
|
|
var BillingPlan = class _BillingPlan {
|
|
constructor(id, name, slug, description, isDefault, isRecurring, hasBaseFee, publiclyVisible, fee, annualFee, annualMonthlyFee, forPayerType, features, avatarUrl, freeTrialDays, freeTrialEnabled) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.slug = slug;
|
|
this.description = description;
|
|
this.isDefault = isDefault;
|
|
this.isRecurring = isRecurring;
|
|
this.hasBaseFee = hasBaseFee;
|
|
this.publiclyVisible = publiclyVisible;
|
|
this.fee = fee;
|
|
this.annualFee = annualFee;
|
|
this.annualMonthlyFee = annualMonthlyFee;
|
|
this.forPayerType = forPayerType;
|
|
this.features = features;
|
|
this.avatarUrl = avatarUrl;
|
|
this.freeTrialDays = freeTrialDays;
|
|
this.freeTrialEnabled = freeTrialEnabled;
|
|
}
|
|
static fromJSON(data) {
|
|
const formatAmountJSON = (fee) => {
|
|
return fee ? {
|
|
amount: fee.amount,
|
|
amountFormatted: fee.amount_formatted,
|
|
currency: fee.currency,
|
|
currencySymbol: fee.currency_symbol
|
|
} : null;
|
|
};
|
|
return new _BillingPlan(
|
|
data.id,
|
|
data.name,
|
|
data.slug,
|
|
data.description ?? null,
|
|
data.is_default,
|
|
data.is_recurring,
|
|
data.has_base_fee,
|
|
data.publicly_visible,
|
|
formatAmountJSON(data.fee),
|
|
formatAmountJSON(data.annual_fee),
|
|
formatAmountJSON(data.annual_monthly_fee),
|
|
data.for_payer_type,
|
|
(data.features ?? []).map((feature) => Feature.fromJSON(feature)),
|
|
data.avatar_url,
|
|
data.free_trial_days,
|
|
data.free_trial_enabled
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/CommerceSubscriptionItem.ts
|
|
var BillingSubscriptionItem = class _BillingSubscriptionItem {
|
|
constructor(id, status, planPeriod, periodStart, nextPayment, amount, plan, planId, createdAt, updatedAt, periodEnd, canceledAt, pastDueAt, endedAt, payerId, isFreeTrial, lifetimePaid) {
|
|
this.id = id;
|
|
this.status = status;
|
|
this.planPeriod = planPeriod;
|
|
this.periodStart = periodStart;
|
|
this.nextPayment = nextPayment;
|
|
this.amount = amount;
|
|
this.plan = plan;
|
|
this.planId = planId;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.periodEnd = periodEnd;
|
|
this.canceledAt = canceledAt;
|
|
this.pastDueAt = pastDueAt;
|
|
this.endedAt = endedAt;
|
|
this.payerId = payerId;
|
|
this.isFreeTrial = isFreeTrial;
|
|
this.lifetimePaid = lifetimePaid;
|
|
}
|
|
static fromJSON(data) {
|
|
function formatAmountJSON(amount) {
|
|
if (!amount) {
|
|
return amount;
|
|
}
|
|
return {
|
|
amount: amount.amount,
|
|
amountFormatted: amount.amount_formatted,
|
|
currency: amount.currency,
|
|
currencySymbol: amount.currency_symbol
|
|
};
|
|
}
|
|
return new _BillingSubscriptionItem(
|
|
data.id,
|
|
data.status,
|
|
data.plan_period,
|
|
data.period_start,
|
|
data.next_payment,
|
|
formatAmountJSON(data.amount) ?? void 0,
|
|
data.plan ? BillingPlan.fromJSON(data.plan) : null,
|
|
data.plan_id ?? null,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.period_end,
|
|
data.canceled_at,
|
|
data.past_due_at,
|
|
data.ended_at,
|
|
data.payer_id,
|
|
data.is_free_trial,
|
|
formatAmountJSON(data.lifetime_paid) ?? void 0
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/CommerceSubscription.ts
|
|
var BillingSubscription = class _BillingSubscription {
|
|
constructor(id, status, payerId, createdAt, updatedAt, activeAt, pastDueAt, subscriptionItems, nextPayment, eligibleForFreeTrial) {
|
|
this.id = id;
|
|
this.status = status;
|
|
this.payerId = payerId;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.activeAt = activeAt;
|
|
this.pastDueAt = pastDueAt;
|
|
this.subscriptionItems = subscriptionItems;
|
|
this.nextPayment = nextPayment;
|
|
this.eligibleForFreeTrial = eligibleForFreeTrial;
|
|
}
|
|
static fromJSON(data) {
|
|
const nextPayment = data.next_payment ? {
|
|
date: data.next_payment.date,
|
|
amount: {
|
|
amount: data.next_payment.amount.amount,
|
|
amountFormatted: data.next_payment.amount.amount_formatted,
|
|
currency: data.next_payment.amount.currency,
|
|
currencySymbol: data.next_payment.amount.currency_symbol
|
|
}
|
|
} : null;
|
|
return new _BillingSubscription(
|
|
data.id,
|
|
data.status,
|
|
data.payer_id,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.active_at ?? null,
|
|
data.past_due_at ?? null,
|
|
(data.subscription_items ?? []).map((item) => BillingSubscriptionItem.fromJSON(item)),
|
|
nextPayment,
|
|
data.eligible_for_free_trial ?? false
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/EnterpriseAccount.ts
|
|
var EnterpriseAccountConnection = class _EnterpriseAccountConnection {
|
|
constructor(id, active, allowIdpInitiated, allowSubdomains, disableAdditionalIdentifications, domain, logoPublicUrl, name, protocol, provider, syncUserAttributes, createdAt, updatedAt) {
|
|
this.id = id;
|
|
this.active = active;
|
|
this.allowIdpInitiated = allowIdpInitiated;
|
|
this.allowSubdomains = allowSubdomains;
|
|
this.disableAdditionalIdentifications = disableAdditionalIdentifications;
|
|
this.domain = domain;
|
|
this.logoPublicUrl = logoPublicUrl;
|
|
this.name = name;
|
|
this.protocol = protocol;
|
|
this.provider = provider;
|
|
this.syncUserAttributes = syncUserAttributes;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _EnterpriseAccountConnection(
|
|
data.id,
|
|
data.active,
|
|
data.allow_idp_initiated,
|
|
data.allow_subdomains,
|
|
data.disable_additional_identifications,
|
|
data.domain,
|
|
data.logo_public_url,
|
|
data.name,
|
|
data.protocol,
|
|
data.provider,
|
|
data.sync_user_attributes,
|
|
data.created_at,
|
|
data.updated_at
|
|
);
|
|
}
|
|
};
|
|
var EnterpriseAccount = class _EnterpriseAccount {
|
|
constructor(id, active, emailAddress, enterpriseConnection, firstName, lastName, protocol, provider, providerUserId, publicMetadata, verification, lastAuthenticatedAt, enterpriseConnectionId) {
|
|
this.id = id;
|
|
this.active = active;
|
|
this.emailAddress = emailAddress;
|
|
this.enterpriseConnection = enterpriseConnection;
|
|
this.firstName = firstName;
|
|
this.lastName = lastName;
|
|
this.protocol = protocol;
|
|
this.provider = provider;
|
|
this.providerUserId = providerUserId;
|
|
this.publicMetadata = publicMetadata;
|
|
this.verification = verification;
|
|
this.lastAuthenticatedAt = lastAuthenticatedAt;
|
|
this.enterpriseConnectionId = enterpriseConnectionId;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _EnterpriseAccount(
|
|
data.id,
|
|
data.active,
|
|
data.email_address,
|
|
data.enterprise_connection && EnterpriseAccountConnection.fromJSON(data.enterprise_connection),
|
|
data.first_name,
|
|
data.last_name,
|
|
data.protocol,
|
|
data.provider,
|
|
data.provider_user_id,
|
|
data.public_metadata,
|
|
data.verification && Verification.fromJSON(data.verification),
|
|
data.last_authenticated_at,
|
|
data.enterprise_connection_id
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/EnterpriseConnection.ts
|
|
var EnterpriseConnectionSamlConnection = class _EnterpriseConnectionSamlConnection {
|
|
constructor(id, name, idpEntityId, idpSsoUrl, idpCertificate, idpMetadataUrl, idpMetadata, acsUrl, spEntityId, spMetadataUrl, syncUserAttributes, allowSubdomains, allowIdpInitiated) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.idpEntityId = idpEntityId;
|
|
this.idpSsoUrl = idpSsoUrl;
|
|
this.idpCertificate = idpCertificate;
|
|
this.idpMetadataUrl = idpMetadataUrl;
|
|
this.idpMetadata = idpMetadata;
|
|
this.acsUrl = acsUrl;
|
|
this.spEntityId = spEntityId;
|
|
this.spMetadataUrl = spMetadataUrl;
|
|
this.syncUserAttributes = syncUserAttributes;
|
|
this.allowSubdomains = allowSubdomains;
|
|
this.allowIdpInitiated = allowIdpInitiated;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _EnterpriseConnectionSamlConnection(
|
|
data.id,
|
|
data.name,
|
|
data.idp_entity_id,
|
|
data.idp_sso_url,
|
|
data.idp_certificate,
|
|
data.idp_metadata_url,
|
|
data.idp_metadata,
|
|
data.acs_url,
|
|
data.sp_entity_id,
|
|
data.sp_metadata_url,
|
|
data.sync_user_attributes,
|
|
data.allow_subdomains,
|
|
data.allow_idp_initiated
|
|
);
|
|
}
|
|
};
|
|
var EnterpriseConnectionOauthConfig = class _EnterpriseConnectionOauthConfig {
|
|
constructor(id, name, clientId, discoveryUrl, logoPublicUrl, createdAt, updatedAt) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.clientId = clientId;
|
|
this.discoveryUrl = discoveryUrl;
|
|
this.logoPublicUrl = logoPublicUrl;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _EnterpriseConnectionOauthConfig(
|
|
data.id,
|
|
data.name,
|
|
data.client_id,
|
|
data.discovery_url,
|
|
data.logo_public_url,
|
|
data.created_at,
|
|
data.updated_at
|
|
);
|
|
}
|
|
};
|
|
var EnterpriseConnection = class _EnterpriseConnection {
|
|
constructor(id, name, domains, organizationId, active, syncUserAttributes, allowSubdomains, disableAdditionalIdentifications, createdAt, updatedAt, samlConnection, oauthConfig) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.domains = domains;
|
|
this.organizationId = organizationId;
|
|
this.active = active;
|
|
this.syncUserAttributes = syncUserAttributes;
|
|
this.allowSubdomains = allowSubdomains;
|
|
this.disableAdditionalIdentifications = disableAdditionalIdentifications;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.samlConnection = samlConnection;
|
|
this.oauthConfig = oauthConfig;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _EnterpriseConnection(
|
|
data.id,
|
|
data.name,
|
|
data.domains,
|
|
data.organization_id,
|
|
data.active,
|
|
data.sync_user_attributes,
|
|
data.allow_subdomains,
|
|
data.disable_additional_identifications,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.saml_connection != null ? EnterpriseConnectionSamlConnection.fromJSON(data.saml_connection) : null,
|
|
data.oauth_config != null ? EnterpriseConnectionOauthConfig.fromJSON(data.oauth_config) : null
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/ExternalAccount.ts
|
|
var ExternalAccount = class _ExternalAccount {
|
|
constructor(id, provider, providerUserId, identificationId, externalId, approvedScopes, emailAddress, firstName, lastName, imageUrl, username, phoneNumber, publicMetadata = {}, label, verification) {
|
|
this.id = id;
|
|
this.provider = provider;
|
|
this.providerUserId = providerUserId;
|
|
this.identificationId = identificationId;
|
|
this.externalId = externalId;
|
|
this.approvedScopes = approvedScopes;
|
|
this.emailAddress = emailAddress;
|
|
this.firstName = firstName;
|
|
this.lastName = lastName;
|
|
this.imageUrl = imageUrl;
|
|
this.username = username;
|
|
this.phoneNumber = phoneNumber;
|
|
this.publicMetadata = publicMetadata;
|
|
this.label = label;
|
|
this.verification = verification;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _ExternalAccount(
|
|
data.id,
|
|
data.provider,
|
|
data.provider_user_id,
|
|
data.identification_id,
|
|
data.provider_user_id,
|
|
data.approved_scopes,
|
|
data.email_address,
|
|
data.first_name,
|
|
data.last_name,
|
|
data.image_url || "",
|
|
data.username,
|
|
data.phone_number,
|
|
data.public_metadata,
|
|
data.label,
|
|
data.verification && Verification.fromJSON(data.verification)
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Instance.ts
|
|
var Instance = class _Instance {
|
|
constructor(id, environmentType, allowedOrigins) {
|
|
this.id = id;
|
|
this.environmentType = environmentType;
|
|
this.allowedOrigins = allowedOrigins;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Instance(data.id, data.environment_type, data.allowed_origins);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/InstanceRestrictions.ts
|
|
var InstanceRestrictions = class _InstanceRestrictions {
|
|
constructor(allowlist, blocklist, blockEmailSubaddresses, blockDisposableEmailDomains, ignoreDotsForGmailAddresses) {
|
|
this.allowlist = allowlist;
|
|
this.blocklist = blocklist;
|
|
this.blockEmailSubaddresses = blockEmailSubaddresses;
|
|
this.blockDisposableEmailDomains = blockDisposableEmailDomains;
|
|
this.ignoreDotsForGmailAddresses = ignoreDotsForGmailAddresses;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _InstanceRestrictions(
|
|
data.allowlist,
|
|
data.blocklist,
|
|
data.block_email_subaddresses,
|
|
data.block_disposable_email_domains,
|
|
data.ignore_dots_for_gmail_addresses
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/InstanceSettings.ts
|
|
var InstanceSettings = class _InstanceSettings {
|
|
constructor(id, restrictedToAllowlist, fromEmailAddress, progressiveSignUp, enhancedEmailDeliverability) {
|
|
this.id = id;
|
|
this.restrictedToAllowlist = restrictedToAllowlist;
|
|
this.fromEmailAddress = fromEmailAddress;
|
|
this.progressiveSignUp = progressiveSignUp;
|
|
this.enhancedEmailDeliverability = enhancedEmailDeliverability;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _InstanceSettings(
|
|
data.id,
|
|
data.restricted_to_allowlist,
|
|
data.from_email_address,
|
|
data.progressive_sign_up,
|
|
data.enhanced_email_deliverability
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Invitation.ts
|
|
var Invitation = class _Invitation {
|
|
constructor(id, emailAddress, publicMetadata, createdAt, updatedAt, status, url, revoked) {
|
|
this.id = id;
|
|
this.emailAddress = emailAddress;
|
|
this.publicMetadata = publicMetadata;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.status = status;
|
|
this.url = url;
|
|
this.revoked = revoked;
|
|
this._raw = null;
|
|
}
|
|
get raw() {
|
|
return this._raw;
|
|
}
|
|
static fromJSON(data) {
|
|
const res = new _Invitation(
|
|
data.id,
|
|
data.email_address,
|
|
data.public_metadata,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.status,
|
|
data.url,
|
|
data.revoked
|
|
);
|
|
res._raw = data;
|
|
return res;
|
|
}
|
|
};
|
|
|
|
// src/api/resources/JSON.ts
|
|
var ObjectType = {
|
|
AccountlessApplication: "accountless_application",
|
|
ActorToken: "actor_token",
|
|
AgentTask: "agent_task",
|
|
AllowlistIdentifier: "allowlist_identifier",
|
|
ApiKey: "api_key",
|
|
BlocklistIdentifier: "blocklist_identifier",
|
|
Client: "client",
|
|
Cookies: "cookies",
|
|
Domain: "domain",
|
|
Email: "email",
|
|
EnterpriseAccount: "enterprise_account",
|
|
EnterpriseConnection: "enterprise_connection",
|
|
EmailAddress: "email_address",
|
|
ExternalAccount: "external_account",
|
|
FacebookAccount: "facebook_account",
|
|
GoogleAccount: "google_account",
|
|
Instance: "instance",
|
|
InstanceRestrictions: "instance_restrictions",
|
|
InstanceSettings: "instance_settings",
|
|
Invitation: "invitation",
|
|
Machine: "machine",
|
|
MachineScope: "machine_scope",
|
|
MachineSecretKey: "machine_secret_key",
|
|
M2MToken: "machine_to_machine_token",
|
|
JwtTemplate: "jwt_template",
|
|
OauthAccessToken: "oauth_access_token",
|
|
IdpOAuthAccessToken: "clerk_idp_oauth_access_token",
|
|
OAuthApplication: "oauth_application",
|
|
Organization: "organization",
|
|
OrganizationDomain: "organization_domain",
|
|
OrganizationInvitation: "organization_invitation",
|
|
OrganizationMembership: "organization_membership",
|
|
OrganizationSettings: "organization_settings",
|
|
PhoneNumber: "phone_number",
|
|
ProxyCheck: "proxy_check",
|
|
RedirectUrl: "redirect_url",
|
|
SamlConnection: "saml_connection",
|
|
Session: "session",
|
|
SignInAttempt: "sign_in_attempt",
|
|
SignInToken: "sign_in_token",
|
|
SignUpAttempt: "sign_up_attempt",
|
|
SmsMessage: "sms_message",
|
|
User: "user",
|
|
WaitlistEntry: "waitlist_entry",
|
|
Web3Wallet: "web3_wallet",
|
|
Token: "token",
|
|
TotalCount: "total_count",
|
|
TestingToken: "testing_token",
|
|
Role: "role",
|
|
Permission: "permission",
|
|
BillingPayer: "commerce_payer",
|
|
BillingPaymentAttempt: "commerce_payment_attempt",
|
|
BillingSubscription: "commerce_subscription",
|
|
BillingSubscriptionItem: "commerce_subscription_item",
|
|
BillingPlan: "commerce_plan",
|
|
Feature: "feature"
|
|
};
|
|
|
|
// src/api/resources/JwtTemplate.ts
|
|
var JwtTemplate = class _JwtTemplate {
|
|
constructor(id, name, claims, lifetime, allowedClockSkew, customSigningKey, signingAlgorithm, createdAt, updatedAt) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.claims = claims;
|
|
this.lifetime = lifetime;
|
|
this.allowedClockSkew = allowedClockSkew;
|
|
this.customSigningKey = customSigningKey;
|
|
this.signingAlgorithm = signingAlgorithm;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _JwtTemplate(
|
|
data.id,
|
|
data.name,
|
|
data.claims,
|
|
data.lifetime,
|
|
data.allowed_clock_skew,
|
|
data.custom_signing_key,
|
|
data.signing_algorithm,
|
|
data.created_at,
|
|
data.updated_at
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Machine.ts
|
|
var Machine = class _Machine {
|
|
constructor(id, name, instanceId, createdAt, updatedAt, scopedMachines, defaultTokenTtl, secretKey) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.instanceId = instanceId;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.scopedMachines = scopedMachines;
|
|
this.defaultTokenTtl = defaultTokenTtl;
|
|
this.secretKey = secretKey;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Machine(
|
|
data.id,
|
|
data.name,
|
|
data.instance_id,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.scoped_machines.map(
|
|
(m) => new _Machine(
|
|
m.id,
|
|
m.name,
|
|
m.instance_id,
|
|
m.created_at,
|
|
m.updated_at,
|
|
[],
|
|
// Nested machines don't have scoped_machines
|
|
m.default_token_ttl
|
|
)
|
|
),
|
|
data.default_token_ttl,
|
|
data.secret_key
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/MachineScope.ts
|
|
var MachineScope = class _MachineScope {
|
|
constructor(fromMachineId, toMachineId, createdAt, deleted) {
|
|
this.fromMachineId = fromMachineId;
|
|
this.toMachineId = toMachineId;
|
|
this.createdAt = createdAt;
|
|
this.deleted = deleted;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _MachineScope(data.from_machine_id, data.to_machine_id, data.created_at, data.deleted);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/MachineSecretKey.ts
|
|
var MachineSecretKey = class _MachineSecretKey {
|
|
constructor(secret) {
|
|
this.secret = secret;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _MachineSecretKey(data.secret);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/OauthAccessToken.ts
|
|
var OauthAccessToken = class _OauthAccessToken {
|
|
constructor(externalAccountId, provider, token, publicMetadata = {}, label, scopes, tokenSecret, expiresAt, idToken) {
|
|
this.externalAccountId = externalAccountId;
|
|
this.provider = provider;
|
|
this.token = token;
|
|
this.publicMetadata = publicMetadata;
|
|
this.label = label;
|
|
this.scopes = scopes;
|
|
this.tokenSecret = tokenSecret;
|
|
this.expiresAt = expiresAt;
|
|
this.idToken = idToken;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _OauthAccessToken(
|
|
data.external_account_id,
|
|
data.provider,
|
|
data.token,
|
|
data.public_metadata,
|
|
data.label || "",
|
|
data.scopes,
|
|
data.token_secret,
|
|
data.expires_at,
|
|
data.id_token
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/OAuthApplication.ts
|
|
var OAuthApplication = class _OAuthApplication {
|
|
constructor(id, instanceId, name, clientId, clientUri, clientImageUrl, dynamicallyRegistered, consentScreenEnabled, pkceRequired, isPublic, scopes, redirectUris, authorizeUrl, tokenFetchUrl, userInfoUrl, discoveryUrl, tokenIntrospectionUrl, createdAt, updatedAt, clientSecret) {
|
|
this.id = id;
|
|
this.instanceId = instanceId;
|
|
this.name = name;
|
|
this.clientId = clientId;
|
|
this.clientUri = clientUri;
|
|
this.clientImageUrl = clientImageUrl;
|
|
this.dynamicallyRegistered = dynamicallyRegistered;
|
|
this.consentScreenEnabled = consentScreenEnabled;
|
|
this.pkceRequired = pkceRequired;
|
|
this.isPublic = isPublic;
|
|
this.scopes = scopes;
|
|
this.redirectUris = redirectUris;
|
|
this.authorizeUrl = authorizeUrl;
|
|
this.tokenFetchUrl = tokenFetchUrl;
|
|
this.userInfoUrl = userInfoUrl;
|
|
this.discoveryUrl = discoveryUrl;
|
|
this.tokenIntrospectionUrl = tokenIntrospectionUrl;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.clientSecret = clientSecret;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _OAuthApplication(
|
|
data.id,
|
|
data.instance_id,
|
|
data.name,
|
|
data.client_id,
|
|
data.client_uri,
|
|
data.client_image_url,
|
|
data.dynamically_registered,
|
|
data.consent_screen_enabled,
|
|
data.pkce_required,
|
|
data.public,
|
|
data.scopes,
|
|
data.redirect_uris,
|
|
data.authorize_url,
|
|
data.token_fetch_url,
|
|
data.user_info_url,
|
|
data.discovery_url,
|
|
data.token_introspection_url,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.client_secret
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Organization.ts
|
|
var Organization = class _Organization {
|
|
constructor(id, name, slug, imageUrl, hasImage, createdAt, updatedAt, publicMetadata = {}, privateMetadata = {}, maxAllowedMemberships, adminDeleteEnabled, membersCount, createdBy) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.slug = slug;
|
|
this.imageUrl = imageUrl;
|
|
this.hasImage = hasImage;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.publicMetadata = publicMetadata;
|
|
this.privateMetadata = privateMetadata;
|
|
this.maxAllowedMemberships = maxAllowedMemberships;
|
|
this.adminDeleteEnabled = adminDeleteEnabled;
|
|
this.membersCount = membersCount;
|
|
this.createdBy = createdBy;
|
|
this._raw = null;
|
|
}
|
|
get raw() {
|
|
return this._raw;
|
|
}
|
|
static fromJSON(data) {
|
|
const res = new _Organization(
|
|
data.id,
|
|
data.name,
|
|
data.slug,
|
|
data.image_url || "",
|
|
data.has_image,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.public_metadata,
|
|
data.private_metadata,
|
|
data.max_allowed_memberships,
|
|
data.admin_delete_enabled,
|
|
data.members_count,
|
|
data.created_by
|
|
);
|
|
res._raw = data;
|
|
return res;
|
|
}
|
|
};
|
|
|
|
// src/api/resources/OrganizationInvitation.ts
|
|
var OrganizationInvitation = class _OrganizationInvitation {
|
|
constructor(id, emailAddress, role, roleName, organizationId, createdAt, updatedAt, expiresAt, url, status, publicMetadata = {}, privateMetadata = {}, publicOrganizationData) {
|
|
this.id = id;
|
|
this.emailAddress = emailAddress;
|
|
this.role = role;
|
|
this.roleName = roleName;
|
|
this.organizationId = organizationId;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.expiresAt = expiresAt;
|
|
this.url = url;
|
|
this.status = status;
|
|
this.publicMetadata = publicMetadata;
|
|
this.privateMetadata = privateMetadata;
|
|
this.publicOrganizationData = publicOrganizationData;
|
|
this._raw = null;
|
|
}
|
|
get raw() {
|
|
return this._raw;
|
|
}
|
|
static fromJSON(data) {
|
|
const res = new _OrganizationInvitation(
|
|
data.id,
|
|
data.email_address,
|
|
data.role,
|
|
data.role_name,
|
|
data.organization_id,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.expires_at,
|
|
data.url,
|
|
data.status,
|
|
data.public_metadata,
|
|
data.private_metadata,
|
|
data.public_organization_data
|
|
);
|
|
res._raw = data;
|
|
return res;
|
|
}
|
|
};
|
|
|
|
// src/api/resources/OrganizationMembership.ts
|
|
var OrganizationMembership = class _OrganizationMembership {
|
|
constructor(id, role, permissions, publicMetadata = {}, privateMetadata = {}, createdAt, updatedAt, organization, publicUserData) {
|
|
this.id = id;
|
|
this.role = role;
|
|
this.permissions = permissions;
|
|
this.publicMetadata = publicMetadata;
|
|
this.privateMetadata = privateMetadata;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.organization = organization;
|
|
this.publicUserData = publicUserData;
|
|
this._raw = null;
|
|
}
|
|
get raw() {
|
|
return this._raw;
|
|
}
|
|
static fromJSON(data) {
|
|
const res = new _OrganizationMembership(
|
|
data.id,
|
|
data.role,
|
|
data.permissions,
|
|
data.public_metadata,
|
|
data.private_metadata,
|
|
data.created_at,
|
|
data.updated_at,
|
|
Organization.fromJSON(data.organization),
|
|
OrganizationMembershipPublicUserData.fromJSON(data.public_user_data)
|
|
);
|
|
res._raw = data;
|
|
return res;
|
|
}
|
|
};
|
|
var OrganizationMembershipPublicUserData = class _OrganizationMembershipPublicUserData {
|
|
constructor(identifier, firstName, lastName, imageUrl, hasImage, userId) {
|
|
this.identifier = identifier;
|
|
this.firstName = firstName;
|
|
this.lastName = lastName;
|
|
this.imageUrl = imageUrl;
|
|
this.hasImage = hasImage;
|
|
this.userId = userId;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _OrganizationMembershipPublicUserData(
|
|
data.identifier,
|
|
data.first_name,
|
|
data.last_name,
|
|
data.image_url,
|
|
data.has_image,
|
|
data.user_id
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/OrganizationSettings.ts
|
|
var OrganizationSettings = class _OrganizationSettings {
|
|
constructor(enabled, maxAllowedMemberships, maxAllowedRoles, maxAllowedPermissions, creatorRole, adminDeleteEnabled, domainsEnabled, slugDisabled, domainsEnrollmentModes, domainsDefaultRole) {
|
|
this.enabled = enabled;
|
|
this.maxAllowedMemberships = maxAllowedMemberships;
|
|
this.maxAllowedRoles = maxAllowedRoles;
|
|
this.maxAllowedPermissions = maxAllowedPermissions;
|
|
this.creatorRole = creatorRole;
|
|
this.adminDeleteEnabled = adminDeleteEnabled;
|
|
this.domainsEnabled = domainsEnabled;
|
|
this.slugDisabled = slugDisabled;
|
|
this.domainsEnrollmentModes = domainsEnrollmentModes;
|
|
this.domainsDefaultRole = domainsDefaultRole;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _OrganizationSettings(
|
|
data.enabled,
|
|
data.max_allowed_memberships,
|
|
data.max_allowed_roles,
|
|
data.max_allowed_permissions,
|
|
data.creator_role,
|
|
data.admin_delete_enabled,
|
|
data.domains_enabled,
|
|
data.slug_disabled,
|
|
data.domains_enrollment_modes,
|
|
data.domains_default_role
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/PhoneNumber.ts
|
|
var PhoneNumber = class _PhoneNumber {
|
|
constructor(id, phoneNumber, reservedForSecondFactor, defaultSecondFactor, verification, linkedTo) {
|
|
this.id = id;
|
|
this.phoneNumber = phoneNumber;
|
|
this.reservedForSecondFactor = reservedForSecondFactor;
|
|
this.defaultSecondFactor = defaultSecondFactor;
|
|
this.verification = verification;
|
|
this.linkedTo = linkedTo;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _PhoneNumber(
|
|
data.id,
|
|
data.phone_number,
|
|
data.reserved_for_second_factor,
|
|
data.default_second_factor,
|
|
data.verification && Verification.fromJSON(data.verification),
|
|
data.linked_to.map((link) => IdentificationLink.fromJSON(link))
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/ProxyCheck.ts
|
|
var ProxyCheck = class _ProxyCheck {
|
|
constructor(id, domainId, lastRunAt, proxyUrl, successful, createdAt, updatedAt) {
|
|
this.id = id;
|
|
this.domainId = domainId;
|
|
this.lastRunAt = lastRunAt;
|
|
this.proxyUrl = proxyUrl;
|
|
this.successful = successful;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _ProxyCheck(
|
|
data.id,
|
|
data.domain_id,
|
|
data.last_run_at,
|
|
data.proxy_url,
|
|
data.successful,
|
|
data.created_at,
|
|
data.updated_at
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/RedirectUrl.ts
|
|
var RedirectUrl = class _RedirectUrl {
|
|
constructor(id, url, createdAt, updatedAt) {
|
|
this.id = id;
|
|
this.url = url;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _RedirectUrl(data.id, data.url, data.created_at, data.updated_at);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/SamlConnection.ts
|
|
var SamlConnection = class _SamlConnection {
|
|
constructor(id, name, domain, organizationId, idpEntityId, idpSsoUrl, idpCertificate, idpMetadataUrl, idpMetadata, acsUrl, spEntityId, spMetadataUrl, active, provider, userCount, syncUserAttributes, allowSubdomains, allowIdpInitiated, createdAt, updatedAt, attributeMapping) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.domain = domain;
|
|
this.organizationId = organizationId;
|
|
this.idpEntityId = idpEntityId;
|
|
this.idpSsoUrl = idpSsoUrl;
|
|
this.idpCertificate = idpCertificate;
|
|
this.idpMetadataUrl = idpMetadataUrl;
|
|
this.idpMetadata = idpMetadata;
|
|
this.acsUrl = acsUrl;
|
|
this.spEntityId = spEntityId;
|
|
this.spMetadataUrl = spMetadataUrl;
|
|
this.active = active;
|
|
this.provider = provider;
|
|
this.userCount = userCount;
|
|
this.syncUserAttributes = syncUserAttributes;
|
|
this.allowSubdomains = allowSubdomains;
|
|
this.allowIdpInitiated = allowIdpInitiated;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.attributeMapping = attributeMapping;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _SamlConnection(
|
|
data.id,
|
|
data.name,
|
|
data.domain,
|
|
data.organization_id,
|
|
data.idp_entity_id,
|
|
data.idp_sso_url,
|
|
data.idp_certificate,
|
|
data.idp_metadata_url,
|
|
data.idp_metadata,
|
|
data.acs_url,
|
|
data.sp_entity_id,
|
|
data.sp_metadata_url,
|
|
data.active,
|
|
data.provider,
|
|
data.user_count,
|
|
data.sync_user_attributes,
|
|
data.allow_subdomains,
|
|
data.allow_idp_initiated,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.attribute_mapping && AttributeMapping.fromJSON(data.attribute_mapping)
|
|
);
|
|
}
|
|
};
|
|
var AttributeMapping = class _AttributeMapping {
|
|
constructor(userId, emailAddress, firstName, lastName) {
|
|
this.userId = userId;
|
|
this.emailAddress = emailAddress;
|
|
this.firstName = firstName;
|
|
this.lastName = lastName;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _AttributeMapping(data.user_id, data.email_address, data.first_name, data.last_name);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/SignInTokens.ts
|
|
var SignInToken = class _SignInToken {
|
|
constructor(id, userId, token, status, url, createdAt, updatedAt) {
|
|
this.id = id;
|
|
this.userId = userId;
|
|
this.token = token;
|
|
this.status = status;
|
|
this.url = url;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _SignInToken(data.id, data.user_id, data.token, data.status, data.url, data.created_at, data.updated_at);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/SignUpAttempt.ts
|
|
var SignUpAttemptVerification = class _SignUpAttemptVerification {
|
|
constructor(nextAction, supportedStrategies) {
|
|
this.nextAction = nextAction;
|
|
this.supportedStrategies = supportedStrategies;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _SignUpAttemptVerification(data.next_action, data.supported_strategies);
|
|
}
|
|
};
|
|
var SignUpAttemptVerifications = class _SignUpAttemptVerifications {
|
|
constructor(emailAddress, phoneNumber, web3Wallet, externalAccount) {
|
|
this.emailAddress = emailAddress;
|
|
this.phoneNumber = phoneNumber;
|
|
this.web3Wallet = web3Wallet;
|
|
this.externalAccount = externalAccount;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _SignUpAttemptVerifications(
|
|
data.email_address && SignUpAttemptVerification.fromJSON(data.email_address),
|
|
data.phone_number && SignUpAttemptVerification.fromJSON(data.phone_number),
|
|
data.web3_wallet && SignUpAttemptVerification.fromJSON(data.web3_wallet),
|
|
data.external_account
|
|
);
|
|
}
|
|
};
|
|
var SignUpAttempt = class _SignUpAttempt {
|
|
constructor(id, status, requiredFields, optionalFields, missingFields, unverifiedFields, verifications, username, emailAddress, phoneNumber, web3Wallet, passwordEnabled, firstName, lastName, customAction, externalId, createdSessionId, createdUserId, abandonAt, legalAcceptedAt, publicMetadata, unsafeMetadata) {
|
|
this.id = id;
|
|
this.status = status;
|
|
this.requiredFields = requiredFields;
|
|
this.optionalFields = optionalFields;
|
|
this.missingFields = missingFields;
|
|
this.unverifiedFields = unverifiedFields;
|
|
this.verifications = verifications;
|
|
this.username = username;
|
|
this.emailAddress = emailAddress;
|
|
this.phoneNumber = phoneNumber;
|
|
this.web3Wallet = web3Wallet;
|
|
this.passwordEnabled = passwordEnabled;
|
|
this.firstName = firstName;
|
|
this.lastName = lastName;
|
|
this.customAction = customAction;
|
|
this.externalId = externalId;
|
|
this.createdSessionId = createdSessionId;
|
|
this.createdUserId = createdUserId;
|
|
this.abandonAt = abandonAt;
|
|
this.legalAcceptedAt = legalAcceptedAt;
|
|
this.publicMetadata = publicMetadata;
|
|
this.unsafeMetadata = unsafeMetadata;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _SignUpAttempt(
|
|
data.id,
|
|
data.status,
|
|
data.required_fields,
|
|
data.optional_fields,
|
|
data.missing_fields,
|
|
data.unverified_fields,
|
|
data.verifications ? SignUpAttemptVerifications.fromJSON(data.verifications) : null,
|
|
data.username,
|
|
data.email_address,
|
|
data.phone_number,
|
|
data.web3_wallet,
|
|
data.password_enabled,
|
|
data.first_name,
|
|
data.last_name,
|
|
data.custom_action,
|
|
data.external_id,
|
|
data.created_session_id,
|
|
data.created_user_id,
|
|
data.abandon_at,
|
|
data.legal_accepted_at,
|
|
data.public_metadata,
|
|
data.unsafe_metadata
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/SMSMessage.ts
|
|
var SMSMessage = class _SMSMessage {
|
|
constructor(id, fromPhoneNumber, toPhoneNumber, message, status, phoneNumberId, data) {
|
|
this.id = id;
|
|
this.fromPhoneNumber = fromPhoneNumber;
|
|
this.toPhoneNumber = toPhoneNumber;
|
|
this.message = message;
|
|
this.status = status;
|
|
this.phoneNumberId = phoneNumberId;
|
|
this.data = data;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _SMSMessage(
|
|
data.id,
|
|
data.from_phone_number,
|
|
data.to_phone_number,
|
|
data.message,
|
|
data.status,
|
|
data.phone_number_id,
|
|
data.data
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Token.ts
|
|
var Token = class _Token {
|
|
constructor(jwt) {
|
|
this.jwt = jwt;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Token(data.jwt);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Web3Wallet.ts
|
|
var Web3Wallet = class _Web3Wallet {
|
|
constructor(id, web3Wallet, verification) {
|
|
this.id = id;
|
|
this.web3Wallet = web3Wallet;
|
|
this.verification = verification;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _Web3Wallet(data.id, data.web3_wallet, data.verification && Verification.fromJSON(data.verification));
|
|
}
|
|
};
|
|
|
|
// src/api/resources/User.ts
|
|
var User = class _User {
|
|
constructor(id, passwordEnabled, totpEnabled, backupCodeEnabled, twoFactorEnabled, banned, locked, createdAt, updatedAt, imageUrl, hasImage, primaryEmailAddressId, primaryPhoneNumberId, primaryWeb3WalletId, lastSignInAt, externalId, username, firstName, lastName, publicMetadata = {}, privateMetadata = {}, unsafeMetadata = {}, emailAddresses = [], phoneNumbers = [], web3Wallets = [], externalAccounts = [], enterpriseAccounts = [], lastActiveAt, createOrganizationEnabled, createOrganizationsLimit = null, deleteSelfEnabled, legalAcceptedAt, locale) {
|
|
this.id = id;
|
|
this.passwordEnabled = passwordEnabled;
|
|
this.totpEnabled = totpEnabled;
|
|
this.backupCodeEnabled = backupCodeEnabled;
|
|
this.twoFactorEnabled = twoFactorEnabled;
|
|
this.banned = banned;
|
|
this.locked = locked;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.imageUrl = imageUrl;
|
|
this.hasImage = hasImage;
|
|
this.primaryEmailAddressId = primaryEmailAddressId;
|
|
this.primaryPhoneNumberId = primaryPhoneNumberId;
|
|
this.primaryWeb3WalletId = primaryWeb3WalletId;
|
|
this.lastSignInAt = lastSignInAt;
|
|
this.externalId = externalId;
|
|
this.username = username;
|
|
this.firstName = firstName;
|
|
this.lastName = lastName;
|
|
this.publicMetadata = publicMetadata;
|
|
this.privateMetadata = privateMetadata;
|
|
this.unsafeMetadata = unsafeMetadata;
|
|
this.emailAddresses = emailAddresses;
|
|
this.phoneNumbers = phoneNumbers;
|
|
this.web3Wallets = web3Wallets;
|
|
this.externalAccounts = externalAccounts;
|
|
this.enterpriseAccounts = enterpriseAccounts;
|
|
this.lastActiveAt = lastActiveAt;
|
|
this.createOrganizationEnabled = createOrganizationEnabled;
|
|
this.createOrganizationsLimit = createOrganizationsLimit;
|
|
this.deleteSelfEnabled = deleteSelfEnabled;
|
|
this.legalAcceptedAt = legalAcceptedAt;
|
|
this.locale = locale;
|
|
this._raw = null;
|
|
}
|
|
get raw() {
|
|
return this._raw;
|
|
}
|
|
static fromJSON(data) {
|
|
const res = new _User(
|
|
data.id,
|
|
data.password_enabled,
|
|
data.totp_enabled,
|
|
data.backup_code_enabled,
|
|
data.two_factor_enabled,
|
|
data.banned,
|
|
data.locked,
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.image_url,
|
|
data.has_image,
|
|
data.primary_email_address_id,
|
|
data.primary_phone_number_id,
|
|
data.primary_web3_wallet_id,
|
|
data.last_sign_in_at,
|
|
data.external_id,
|
|
data.username,
|
|
data.first_name,
|
|
data.last_name,
|
|
data.public_metadata,
|
|
data.private_metadata,
|
|
data.unsafe_metadata,
|
|
(data.email_addresses || []).map((x) => EmailAddress.fromJSON(x)),
|
|
(data.phone_numbers || []).map((x) => PhoneNumber.fromJSON(x)),
|
|
(data.web3_wallets || []).map((x) => Web3Wallet.fromJSON(x)),
|
|
(data.external_accounts || []).map((x) => ExternalAccount.fromJSON(x)),
|
|
(data.enterprise_accounts || []).map((x) => EnterpriseAccount.fromJSON(x)),
|
|
data.last_active_at,
|
|
data.create_organization_enabled,
|
|
data.create_organizations_limit,
|
|
data.delete_self_enabled,
|
|
data.legal_accepted_at,
|
|
data.locale
|
|
);
|
|
res._raw = data;
|
|
return res;
|
|
}
|
|
/**
|
|
* The primary email address of the user.
|
|
*/
|
|
get primaryEmailAddress() {
|
|
return this.emailAddresses.find(({ id }) => id === this.primaryEmailAddressId) ?? null;
|
|
}
|
|
/**
|
|
* The primary phone number of the user.
|
|
*/
|
|
get primaryPhoneNumber() {
|
|
return this.phoneNumbers.find(({ id }) => id === this.primaryPhoneNumberId) ?? null;
|
|
}
|
|
/**
|
|
* The primary web3 wallet of the user.
|
|
*/
|
|
get primaryWeb3Wallet() {
|
|
return this.web3Wallets.find(({ id }) => id === this.primaryWeb3WalletId) ?? null;
|
|
}
|
|
/**
|
|
* The full name of the user.
|
|
*/
|
|
get fullName() {
|
|
return [this.firstName, this.lastName].join(" ").trim() || null;
|
|
}
|
|
};
|
|
|
|
// src/api/resources/WaitlistEntry.ts
|
|
var WaitlistEntry = class _WaitlistEntry {
|
|
constructor(id, emailAddress, status, invitation, createdAt, updatedAt, isLocked) {
|
|
this.id = id;
|
|
this.emailAddress = emailAddress;
|
|
this.status = status;
|
|
this.invitation = invitation;
|
|
this.createdAt = createdAt;
|
|
this.updatedAt = updatedAt;
|
|
this.isLocked = isLocked;
|
|
}
|
|
static fromJSON(data) {
|
|
return new _WaitlistEntry(
|
|
data.id,
|
|
data.email_address,
|
|
data.status,
|
|
data.invitation && Invitation.fromJSON(data.invitation),
|
|
data.created_at,
|
|
data.updated_at,
|
|
data.is_locked
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/api/resources/Deserializer.ts
|
|
function deserialize(payload) {
|
|
let data, totalCount;
|
|
if (Array.isArray(payload)) {
|
|
const data2 = payload.map((item) => jsonToObject(item));
|
|
return { data: data2 };
|
|
} else if (isM2MTokenResponse(payload)) {
|
|
data = payload.m2m_tokens.map((item) => jsonToObject(item));
|
|
totalCount = payload.total_count;
|
|
return { data, totalCount };
|
|
} else if (isPaginated(payload)) {
|
|
data = payload.data.map((item) => jsonToObject(item));
|
|
totalCount = payload.total_count;
|
|
return { data, totalCount };
|
|
} else {
|
|
return { data: jsonToObject(payload) };
|
|
}
|
|
}
|
|
function isPaginated(payload) {
|
|
if (!payload || typeof payload !== "object" || !("data" in payload)) {
|
|
return false;
|
|
}
|
|
return Array.isArray(payload.data) && payload.data !== void 0;
|
|
}
|
|
function isM2MTokenResponse(payload) {
|
|
if (!payload || typeof payload !== "object" || !("m2m_tokens" in payload)) {
|
|
return false;
|
|
}
|
|
return Array.isArray(payload.m2m_tokens);
|
|
}
|
|
function getCount(item) {
|
|
return item.total_count;
|
|
}
|
|
function jsonToObject(item) {
|
|
if (typeof item !== "string" && "object" in item && "deleted" in item) {
|
|
return DeletedObject.fromJSON(item);
|
|
}
|
|
switch (item.object) {
|
|
case ObjectType.AccountlessApplication:
|
|
return AccountlessApplication.fromJSON(item);
|
|
case ObjectType.ActorToken:
|
|
return ActorToken.fromJSON(item);
|
|
case ObjectType.AllowlistIdentifier:
|
|
return AllowlistIdentifier.fromJSON(item);
|
|
case ObjectType.ApiKey:
|
|
return APIKey.fromJSON(item);
|
|
case ObjectType.BlocklistIdentifier:
|
|
return BlocklistIdentifier.fromJSON(item);
|
|
case ObjectType.Client:
|
|
return Client.fromJSON(item);
|
|
case ObjectType.Cookies:
|
|
return Cookies2.fromJSON(item);
|
|
case ObjectType.Domain:
|
|
return Domain.fromJSON(item);
|
|
case ObjectType.EmailAddress:
|
|
return EmailAddress.fromJSON(item);
|
|
case ObjectType.EnterpriseAccount:
|
|
return EnterpriseAccount.fromJSON(item);
|
|
case ObjectType.Email:
|
|
return Email.fromJSON(item);
|
|
case ObjectType.IdpOAuthAccessToken:
|
|
return IdPOAuthAccessToken.fromJSON(item);
|
|
case ObjectType.Instance:
|
|
return Instance.fromJSON(item);
|
|
case ObjectType.InstanceRestrictions:
|
|
return InstanceRestrictions.fromJSON(item);
|
|
case ObjectType.InstanceSettings:
|
|
return InstanceSettings.fromJSON(item);
|
|
case ObjectType.Invitation:
|
|
return Invitation.fromJSON(item);
|
|
case ObjectType.JwtTemplate:
|
|
return JwtTemplate.fromJSON(item);
|
|
case ObjectType.Machine:
|
|
return Machine.fromJSON(item);
|
|
case ObjectType.MachineScope:
|
|
return MachineScope.fromJSON(item);
|
|
case ObjectType.MachineSecretKey:
|
|
return MachineSecretKey.fromJSON(item);
|
|
case ObjectType.M2MToken:
|
|
return M2MToken.fromJSON(item);
|
|
case ObjectType.OauthAccessToken:
|
|
return OauthAccessToken.fromJSON(item);
|
|
case ObjectType.OAuthApplication:
|
|
return OAuthApplication.fromJSON(item);
|
|
case ObjectType.Organization:
|
|
return Organization.fromJSON(item);
|
|
case ObjectType.OrganizationInvitation:
|
|
return OrganizationInvitation.fromJSON(item);
|
|
case ObjectType.OrganizationMembership:
|
|
return OrganizationMembership.fromJSON(item);
|
|
case ObjectType.OrganizationSettings:
|
|
return OrganizationSettings.fromJSON(item);
|
|
case ObjectType.PhoneNumber:
|
|
return PhoneNumber.fromJSON(item);
|
|
case ObjectType.ProxyCheck:
|
|
return ProxyCheck.fromJSON(item);
|
|
case ObjectType.RedirectUrl:
|
|
return RedirectUrl.fromJSON(item);
|
|
case ObjectType.EnterpriseConnection:
|
|
return EnterpriseConnection.fromJSON(item);
|
|
case ObjectType.SamlConnection:
|
|
return SamlConnection.fromJSON(item);
|
|
case ObjectType.SignInToken:
|
|
return SignInToken.fromJSON(item);
|
|
case ObjectType.AgentTask:
|
|
return AgentTask.fromJSON(item);
|
|
case ObjectType.SignUpAttempt:
|
|
return SignUpAttempt.fromJSON(item);
|
|
case ObjectType.Session:
|
|
return Session.fromJSON(item);
|
|
case ObjectType.SmsMessage:
|
|
return SMSMessage.fromJSON(item);
|
|
case ObjectType.Token:
|
|
return Token.fromJSON(item);
|
|
case ObjectType.TotalCount:
|
|
return getCount(item);
|
|
case ObjectType.User:
|
|
return User.fromJSON(item);
|
|
case ObjectType.WaitlistEntry:
|
|
return WaitlistEntry.fromJSON(item);
|
|
case ObjectType.BillingPlan:
|
|
return BillingPlan.fromJSON(item);
|
|
case ObjectType.BillingSubscription:
|
|
return BillingSubscription.fromJSON(item);
|
|
case ObjectType.BillingSubscriptionItem:
|
|
return BillingSubscriptionItem.fromJSON(item);
|
|
case ObjectType.Feature:
|
|
return Feature.fromJSON(item);
|
|
default:
|
|
return item;
|
|
}
|
|
}
|
|
|
|
// src/api/request.ts
|
|
function buildRequest(options) {
|
|
const requestFn = async (requestOptions) => {
|
|
const {
|
|
secretKey,
|
|
machineSecretKey,
|
|
useMachineSecretKey = false,
|
|
requireSecretKey = true,
|
|
apiUrl = API_URL,
|
|
apiVersion = API_VERSION,
|
|
userAgent = USER_AGENT,
|
|
skipApiVersionInUrl = false
|
|
} = options;
|
|
const { path, method, queryParams, headerParams, bodyParams, formData, options: opts } = requestOptions;
|
|
const { deepSnakecaseBodyParamKeys = false } = opts || {};
|
|
if (requireSecretKey) {
|
|
assertValidSecretKey(secretKey);
|
|
}
|
|
const url = skipApiVersionInUrl ? joinPaths(apiUrl, path) : joinPaths(apiUrl, apiVersion, path);
|
|
const finalUrl = new URL(url);
|
|
if (queryParams) {
|
|
const snakecasedQueryParams = snakecase_keys_default({ ...queryParams });
|
|
for (const [key, val] of Object.entries(snakecasedQueryParams)) {
|
|
if (val) {
|
|
[val].flat().forEach((v) => finalUrl.searchParams.append(key, v));
|
|
}
|
|
}
|
|
}
|
|
const headers = new Headers({
|
|
"Clerk-API-Version": SUPPORTED_BAPI_VERSION,
|
|
[constants.Headers.UserAgent]: userAgent,
|
|
...headerParams
|
|
});
|
|
const authorizationHeader = constants.Headers.Authorization;
|
|
if (!headers.has(authorizationHeader)) {
|
|
if (useMachineSecretKey && machineSecretKey) {
|
|
headers.set(authorizationHeader, `Bearer ${machineSecretKey}`);
|
|
} else if (secretKey) {
|
|
headers.set(authorizationHeader, `Bearer ${secretKey}`);
|
|
}
|
|
}
|
|
let res;
|
|
try {
|
|
if (formData) {
|
|
res = await runtime.fetch(finalUrl.href, {
|
|
method,
|
|
headers,
|
|
body: formData
|
|
});
|
|
} else {
|
|
headers.set("Content-Type", "application/json");
|
|
const buildBody = () => {
|
|
const hasBody = method !== "GET" && bodyParams && Object.keys(bodyParams).length > 0;
|
|
if (!hasBody) {
|
|
return null;
|
|
}
|
|
const formatKeys = (object) => snakecase_keys_default(object, { deep: deepSnakecaseBodyParamKeys });
|
|
return {
|
|
body: JSON.stringify(Array.isArray(bodyParams) ? bodyParams.map(formatKeys) : formatKeys(bodyParams))
|
|
};
|
|
};
|
|
res = await runtime.fetch(finalUrl.href, {
|
|
method,
|
|
headers,
|
|
...buildBody()
|
|
});
|
|
}
|
|
const isJSONResponse = res?.headers && res.headers?.get(constants.Headers.ContentType) === constants.ContentTypes.Json;
|
|
const responseBody = await (isJSONResponse ? res.json() : res.text());
|
|
if (!res.ok) {
|
|
return {
|
|
data: null,
|
|
errors: parseErrors(responseBody),
|
|
status: res?.status,
|
|
statusText: res?.statusText,
|
|
clerkTraceId: getTraceId(responseBody, res?.headers),
|
|
retryAfter: getRetryAfter(res?.headers)
|
|
};
|
|
}
|
|
return {
|
|
...deserialize(responseBody),
|
|
errors: null
|
|
};
|
|
} catch (err) {
|
|
if (err instanceof Error) {
|
|
return {
|
|
data: null,
|
|
errors: [
|
|
{
|
|
code: "unexpected_error",
|
|
message: err.message || "Unexpected error"
|
|
}
|
|
],
|
|
clerkTraceId: getTraceId(err, res?.headers)
|
|
};
|
|
}
|
|
return {
|
|
data: null,
|
|
errors: parseErrors(err),
|
|
status: res?.status,
|
|
statusText: res?.statusText,
|
|
clerkTraceId: getTraceId(err, res?.headers),
|
|
retryAfter: getRetryAfter(res?.headers)
|
|
};
|
|
}
|
|
};
|
|
return withLegacyRequestReturn(requestFn);
|
|
}
|
|
function getTraceId(data, headers) {
|
|
if (data && typeof data === "object" && "clerk_trace_id" in data && typeof data.clerk_trace_id === "string") {
|
|
return data.clerk_trace_id;
|
|
}
|
|
const cfRay = headers?.get("cf-ray");
|
|
return cfRay || "";
|
|
}
|
|
function getRetryAfter(headers) {
|
|
const retryAfter = headers?.get("Retry-After");
|
|
if (!retryAfter) {
|
|
return;
|
|
}
|
|
const value = parseInt(retryAfter, 10);
|
|
if (isNaN(value)) {
|
|
return;
|
|
}
|
|
return value;
|
|
}
|
|
function parseErrors(data) {
|
|
if (!!data && typeof data === "object" && "errors" in data) {
|
|
const errors = data.errors;
|
|
return errors.length > 0 ? errors.map(import_error4.parseError) : [];
|
|
}
|
|
return [];
|
|
}
|
|
function withLegacyRequestReturn(cb) {
|
|
return async (...args) => {
|
|
const { data, errors, totalCount, status, statusText, clerkTraceId, retryAfter } = await cb(...args);
|
|
if (errors) {
|
|
const error = new import_error4.ClerkAPIResponseError(statusText || "", {
|
|
data: [],
|
|
status,
|
|
clerkTraceId,
|
|
retryAfter
|
|
});
|
|
error.errors = errors;
|
|
throw error;
|
|
}
|
|
if (typeof totalCount !== "undefined") {
|
|
return { data, totalCount };
|
|
}
|
|
return data;
|
|
};
|
|
}
|
|
|
|
// src/api/factory.ts
|
|
function createBackendApiClient(options) {
|
|
const request = buildRequest(options);
|
|
return {
|
|
__experimental_accountlessApplications: new AccountlessApplicationAPI(
|
|
buildRequest({ ...options, requireSecretKey: false })
|
|
),
|
|
actorTokens: new ActorTokenAPI(request),
|
|
/**
|
|
* @experimental This is an experimental API for the Agent Tasks feature that is available under a private beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
|
|
*/
|
|
agentTasks: new AgentTaskAPI(request),
|
|
allowlistIdentifiers: new AllowlistIdentifierAPI(request),
|
|
apiKeys: new APIKeysAPI(
|
|
buildRequest({
|
|
...options,
|
|
skipApiVersionInUrl: true
|
|
})
|
|
),
|
|
betaFeatures: new BetaFeaturesAPI(request),
|
|
blocklistIdentifiers: new BlocklistIdentifierAPI(request),
|
|
/**
|
|
* @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
|
|
*/
|
|
billing: new BillingAPI(request),
|
|
clients: new ClientAPI(request),
|
|
domains: new DomainAPI(request),
|
|
emailAddresses: new EmailAddressAPI(request),
|
|
enterpriseConnections: new EnterpriseConnectionAPI(request),
|
|
idPOAuthAccessToken: new IdPOAuthAccessTokenApi(
|
|
buildRequest({
|
|
...options,
|
|
skipApiVersionInUrl: true
|
|
})
|
|
),
|
|
instance: new InstanceAPI(request),
|
|
invitations: new InvitationAPI(request),
|
|
jwks: new JwksAPI(request),
|
|
jwtTemplates: new JwtTemplatesApi(request),
|
|
machines: new MachineApi(request),
|
|
m2m: new M2MTokenApi(
|
|
buildRequest({
|
|
...options,
|
|
skipApiVersionInUrl: true,
|
|
requireSecretKey: false,
|
|
useMachineSecretKey: true
|
|
}),
|
|
{
|
|
secretKey: options.secretKey,
|
|
apiUrl: options.apiUrl,
|
|
jwtKey: options.jwtKey
|
|
}
|
|
),
|
|
oauthApplications: new OAuthApplicationsApi(request),
|
|
organizations: new OrganizationAPI(request),
|
|
phoneNumbers: new PhoneNumberAPI(request),
|
|
proxyChecks: new ProxyCheckAPI(request),
|
|
redirectUrls: new RedirectUrlAPI(request),
|
|
sessions: new SessionAPI(request),
|
|
signInTokens: new SignInTokenAPI(request),
|
|
signUps: new SignUpAPI(request),
|
|
testingTokens: new TestingTokenAPI(request),
|
|
users: new UserAPI(request),
|
|
waitlistEntries: new WaitlistEntryAPI(request),
|
|
webhooks: new WebhookAPI(request),
|
|
/**
|
|
* @deprecated Use `enterpriseConnections` instead.
|
|
*/
|
|
samlConnections: new SamlConnectionAPI(request)
|
|
};
|
|
}
|
|
|
|
// src/tokens/authObjects.ts
|
|
var createDebug = (data) => {
|
|
return () => {
|
|
const res = { ...data };
|
|
res.secretKey = (res.secretKey || "").substring(0, 7);
|
|
res.jwtKey = (res.jwtKey || "").substring(0, 7);
|
|
return { ...res };
|
|
};
|
|
};
|
|
function signedInAuthObject(authenticateContext, sessionToken, sessionClaims) {
|
|
const { actor, sessionId, sessionStatus, userId, orgId, orgRole, orgSlug, orgPermissions, factorVerificationAge } = (0, import_jwtPayloadParser.__experimental_JWTPayloadToAuthObjectProperties)(sessionClaims);
|
|
const apiClient = createBackendApiClient(authenticateContext);
|
|
const getToken = createGetToken({
|
|
sessionId,
|
|
sessionToken,
|
|
fetcher: async (sessionId2, template, expiresInSeconds) => (await apiClient.sessions.getToken(sessionId2, template || "", expiresInSeconds)).jwt
|
|
});
|
|
return {
|
|
tokenType: TokenType.SessionToken,
|
|
actor,
|
|
sessionClaims,
|
|
sessionId,
|
|
sessionStatus,
|
|
userId,
|
|
orgId,
|
|
orgRole,
|
|
orgSlug,
|
|
orgPermissions,
|
|
factorVerificationAge,
|
|
getToken,
|
|
has: (0, import_authorization.createCheckAuthorization)({
|
|
orgId,
|
|
orgRole,
|
|
orgPermissions,
|
|
userId,
|
|
factorVerificationAge,
|
|
features: sessionClaims.fea || "",
|
|
plans: sessionClaims.pla || ""
|
|
}),
|
|
debug: createDebug({ ...authenticateContext, sessionToken }),
|
|
isAuthenticated: true
|
|
};
|
|
}
|
|
function signedOutAuthObject(debugData, initialSessionStatus) {
|
|
return {
|
|
tokenType: TokenType.SessionToken,
|
|
sessionClaims: null,
|
|
sessionId: null,
|
|
sessionStatus: initialSessionStatus ?? null,
|
|
userId: null,
|
|
actor: null,
|
|
orgId: null,
|
|
orgRole: null,
|
|
orgSlug: null,
|
|
orgPermissions: null,
|
|
factorVerificationAge: null,
|
|
getToken: () => Promise.resolve(null),
|
|
has: () => false,
|
|
debug: createDebug(debugData),
|
|
isAuthenticated: false
|
|
};
|
|
}
|
|
function authenticatedMachineObject(tokenType, token, verificationResult, debugData) {
|
|
const baseObject = {
|
|
id: verificationResult.id,
|
|
subject: verificationResult.subject,
|
|
getToken: () => Promise.resolve(token),
|
|
has: () => false,
|
|
debug: createDebug(debugData),
|
|
isAuthenticated: true
|
|
};
|
|
switch (tokenType) {
|
|
case TokenType.ApiKey: {
|
|
const result = verificationResult;
|
|
return {
|
|
...baseObject,
|
|
tokenType,
|
|
name: result.name,
|
|
claims: result.claims,
|
|
scopes: result.scopes,
|
|
userId: result.subject.startsWith("user_") ? result.subject : null,
|
|
orgId: result.subject.startsWith("org_") ? result.subject : null
|
|
};
|
|
}
|
|
case TokenType.M2MToken: {
|
|
const result = verificationResult;
|
|
return {
|
|
...baseObject,
|
|
tokenType,
|
|
claims: result.claims,
|
|
scopes: result.scopes,
|
|
machineId: result.subject
|
|
};
|
|
}
|
|
case TokenType.OAuthToken: {
|
|
const result = verificationResult;
|
|
return {
|
|
...baseObject,
|
|
tokenType,
|
|
scopes: result.scopes,
|
|
userId: result.subject,
|
|
clientId: result.clientId
|
|
};
|
|
}
|
|
default:
|
|
throw new Error(`Invalid token type: ${tokenType}`);
|
|
}
|
|
}
|
|
function unauthenticatedMachineObject(tokenType, debugData) {
|
|
const baseObject = {
|
|
id: null,
|
|
subject: null,
|
|
scopes: null,
|
|
has: () => false,
|
|
getToken: () => Promise.resolve(null),
|
|
debug: createDebug(debugData),
|
|
isAuthenticated: false
|
|
};
|
|
switch (tokenType) {
|
|
case TokenType.ApiKey: {
|
|
return {
|
|
...baseObject,
|
|
tokenType,
|
|
name: null,
|
|
claims: null,
|
|
scopes: null,
|
|
userId: null,
|
|
orgId: null
|
|
};
|
|
}
|
|
case TokenType.M2MToken: {
|
|
return {
|
|
...baseObject,
|
|
tokenType,
|
|
claims: null,
|
|
scopes: null,
|
|
machineId: null
|
|
};
|
|
}
|
|
case TokenType.OAuthToken: {
|
|
return {
|
|
...baseObject,
|
|
tokenType,
|
|
scopes: null,
|
|
userId: null,
|
|
clientId: null
|
|
};
|
|
}
|
|
default:
|
|
throw new Error(`Invalid token type: ${tokenType}`);
|
|
}
|
|
}
|
|
function invalidTokenAuthObject() {
|
|
return {
|
|
isAuthenticated: false,
|
|
tokenType: null,
|
|
getToken: () => Promise.resolve(null),
|
|
has: () => false,
|
|
debug: () => ({})
|
|
};
|
|
}
|
|
var makeAuthObjectSerializable = (obj) => {
|
|
const { debug, getToken, has, ...rest } = obj;
|
|
return rest;
|
|
};
|
|
var createGetToken = (params) => {
|
|
const { fetcher, sessionToken, sessionId } = params || {};
|
|
return async (options = {}) => {
|
|
if (!sessionId) {
|
|
return null;
|
|
}
|
|
if (options.template || options.expiresInSeconds !== void 0) {
|
|
return fetcher(sessionId, options.template, options.expiresInSeconds);
|
|
}
|
|
return sessionToken;
|
|
};
|
|
};
|
|
var getAuthObjectFromJwt = (jwt, { treatPendingAsSignedOut = true, ...options }) => {
|
|
const authObject = signedInAuthObject(options, jwt.raw.text, jwt.payload);
|
|
if (treatPendingAsSignedOut && authObject.sessionStatus === "pending") {
|
|
return signedOutAuthObject(options, authObject.sessionStatus);
|
|
}
|
|
return authObject;
|
|
};
|
|
var getAuthObjectForAcceptedToken = ({
|
|
authObject,
|
|
acceptsToken = TokenType.SessionToken
|
|
}) => {
|
|
if (acceptsToken === "any") {
|
|
return authObject;
|
|
}
|
|
if (Array.isArray(acceptsToken)) {
|
|
if (!isTokenTypeAccepted(authObject.tokenType, acceptsToken)) {
|
|
return invalidTokenAuthObject();
|
|
}
|
|
return authObject;
|
|
}
|
|
if (!isTokenTypeAccepted(authObject.tokenType, acceptsToken)) {
|
|
if (isMachineTokenType(acceptsToken)) {
|
|
return unauthenticatedMachineObject(acceptsToken, authObject.debug);
|
|
}
|
|
return signedOutAuthObject(authObject.debug);
|
|
}
|
|
return authObject;
|
|
};
|
|
|
|
// src/tokens/authStatus.ts
|
|
var AuthStatus = {
|
|
SignedIn: "signed-in",
|
|
SignedOut: "signed-out",
|
|
Handshake: "handshake"
|
|
};
|
|
var AuthErrorReason = {
|
|
ClientUATWithoutSessionToken: "client-uat-but-no-session-token",
|
|
DevBrowserMissing: "dev-browser-missing",
|
|
DevBrowserSync: "dev-browser-sync",
|
|
PrimaryRespondsToSyncing: "primary-responds-to-syncing",
|
|
PrimaryDomainCrossOriginSync: "primary-domain-cross-origin-sync",
|
|
SatelliteCookieNeedsSyncing: "satellite-needs-syncing",
|
|
SessionTokenAndUATMissing: "session-token-and-uat-missing",
|
|
SessionTokenMissing: "session-token-missing",
|
|
SessionTokenExpired: "session-token-expired",
|
|
SessionTokenIATBeforeClientUAT: "session-token-iat-before-client-uat",
|
|
SessionTokenNBF: "session-token-nbf",
|
|
SessionTokenIatInTheFuture: "session-token-iat-in-the-future",
|
|
SessionTokenWithoutClientUAT: "session-token-but-no-client-uat",
|
|
ActiveOrganizationMismatch: "active-organization-mismatch",
|
|
TokenTypeMismatch: "token-type-mismatch",
|
|
UnexpectedError: "unexpected-error"
|
|
};
|
|
function signedIn(params) {
|
|
const { authenticateContext, headers = new Headers(), token } = params;
|
|
const toAuth = (({ treatPendingAsSignedOut = true } = {}) => {
|
|
if (params.tokenType === TokenType.SessionToken) {
|
|
const { sessionClaims } = params;
|
|
const authObject = signedInAuthObject(authenticateContext, token, sessionClaims);
|
|
if (treatPendingAsSignedOut && authObject.sessionStatus === "pending") {
|
|
return signedOutAuthObject(void 0, authObject.sessionStatus);
|
|
}
|
|
return authObject;
|
|
}
|
|
const { machineData } = params;
|
|
return authenticatedMachineObject(params.tokenType, token, machineData, authenticateContext);
|
|
});
|
|
return {
|
|
status: AuthStatus.SignedIn,
|
|
reason: null,
|
|
message: null,
|
|
proxyUrl: authenticateContext.proxyUrl || "",
|
|
publishableKey: authenticateContext.publishableKey || "",
|
|
isSatellite: authenticateContext.isSatellite || false,
|
|
domain: authenticateContext.domain || "",
|
|
signInUrl: authenticateContext.signInUrl || "",
|
|
signUpUrl: authenticateContext.signUpUrl || "",
|
|
afterSignInUrl: authenticateContext.afterSignInUrl || "",
|
|
afterSignUpUrl: authenticateContext.afterSignUpUrl || "",
|
|
isSignedIn: true,
|
|
isAuthenticated: true,
|
|
tokenType: params.tokenType,
|
|
toAuth,
|
|
headers,
|
|
token
|
|
};
|
|
}
|
|
function signedOut(params) {
|
|
const { authenticateContext, headers = new Headers(), reason, message = "", tokenType } = params;
|
|
const toAuth = (() => {
|
|
if (tokenType === TokenType.SessionToken) {
|
|
return signedOutAuthObject({ ...authenticateContext, status: AuthStatus.SignedOut, reason, message });
|
|
}
|
|
return unauthenticatedMachineObject(tokenType, { reason, message, headers });
|
|
});
|
|
return withDebugHeaders({
|
|
status: AuthStatus.SignedOut,
|
|
reason,
|
|
message,
|
|
proxyUrl: authenticateContext.proxyUrl || "",
|
|
publishableKey: authenticateContext.publishableKey || "",
|
|
isSatellite: authenticateContext.isSatellite || false,
|
|
domain: authenticateContext.domain || "",
|
|
signInUrl: authenticateContext.signInUrl || "",
|
|
signUpUrl: authenticateContext.signUpUrl || "",
|
|
afterSignInUrl: authenticateContext.afterSignInUrl || "",
|
|
afterSignUpUrl: authenticateContext.afterSignUpUrl || "",
|
|
isSignedIn: false,
|
|
isAuthenticated: false,
|
|
tokenType,
|
|
toAuth,
|
|
headers,
|
|
token: null
|
|
});
|
|
}
|
|
function handshake(authenticateContext, reason, message = "", headers) {
|
|
return withDebugHeaders({
|
|
status: AuthStatus.Handshake,
|
|
reason,
|
|
message,
|
|
publishableKey: authenticateContext.publishableKey || "",
|
|
isSatellite: authenticateContext.isSatellite || false,
|
|
domain: authenticateContext.domain || "",
|
|
proxyUrl: authenticateContext.proxyUrl || "",
|
|
signInUrl: authenticateContext.signInUrl || "",
|
|
signUpUrl: authenticateContext.signUpUrl || "",
|
|
afterSignInUrl: authenticateContext.afterSignInUrl || "",
|
|
afterSignUpUrl: authenticateContext.afterSignUpUrl || "",
|
|
isSignedIn: false,
|
|
isAuthenticated: false,
|
|
tokenType: TokenType.SessionToken,
|
|
toAuth: () => null,
|
|
headers,
|
|
token: null
|
|
});
|
|
}
|
|
function signedOutInvalidToken() {
|
|
const authObject = invalidTokenAuthObject();
|
|
return withDebugHeaders({
|
|
status: AuthStatus.SignedOut,
|
|
reason: AuthErrorReason.TokenTypeMismatch,
|
|
message: "",
|
|
proxyUrl: "",
|
|
publishableKey: "",
|
|
isSatellite: false,
|
|
domain: "",
|
|
signInUrl: "",
|
|
signUpUrl: "",
|
|
afterSignInUrl: "",
|
|
afterSignUpUrl: "",
|
|
isSignedIn: false,
|
|
isAuthenticated: false,
|
|
tokenType: null,
|
|
toAuth: () => authObject,
|
|
headers: new Headers(),
|
|
token: null
|
|
});
|
|
}
|
|
function createBootstrapSignedOutState({
|
|
signInUrl = "",
|
|
signUpUrl = "",
|
|
isSatellite = false,
|
|
domain = "",
|
|
proxyUrl = "",
|
|
reason = AuthErrorReason.SessionTokenAndUATMissing,
|
|
message = "",
|
|
headers = new Headers()
|
|
} = {}) {
|
|
return withDebugHeaders({
|
|
status: AuthStatus.SignedOut,
|
|
reason,
|
|
message,
|
|
proxyUrl,
|
|
publishableKey: "",
|
|
isSatellite,
|
|
domain,
|
|
signInUrl,
|
|
signUpUrl,
|
|
afterSignInUrl: "",
|
|
afterSignUpUrl: "",
|
|
isSignedIn: false,
|
|
isAuthenticated: false,
|
|
tokenType: TokenType.SessionToken,
|
|
toAuth: () => signedOutAuthObject({ status: AuthStatus.SignedOut, reason, message }),
|
|
headers,
|
|
token: null
|
|
});
|
|
}
|
|
var withDebugHeaders = (requestState) => {
|
|
const headers = new Headers(requestState.headers || {});
|
|
if (requestState.message) {
|
|
try {
|
|
headers.set(constants.Headers.AuthMessage, requestState.message);
|
|
} catch {
|
|
}
|
|
}
|
|
if (requestState.reason) {
|
|
try {
|
|
headers.set(constants.Headers.AuthReason, requestState.reason);
|
|
} catch {
|
|
}
|
|
}
|
|
if (requestState.status) {
|
|
try {
|
|
headers.set(constants.Headers.AuthStatus, requestState.status);
|
|
} catch {
|
|
}
|
|
}
|
|
requestState.headers = headers;
|
|
return requestState;
|
|
};
|
|
|
|
// src/tokens/clerkRequest.ts
|
|
var import_cookie = __toESM(require_dist());
|
|
|
|
// src/tokens/clerkUrl.ts
|
|
var ClerkUrl = class extends URL {
|
|
isCrossOrigin(other) {
|
|
return this.origin !== new URL(other.toString()).origin;
|
|
}
|
|
};
|
|
var createClerkUrl = (...args) => {
|
|
return new ClerkUrl(...args);
|
|
};
|
|
|
|
// src/tokens/clerkRequest.ts
|
|
var ClerkRequest = class extends Request {
|
|
constructor(input, init) {
|
|
const url = typeof input !== "string" && "url" in input ? input.url : String(input);
|
|
super(url, init || typeof input === "string" ? void 0 : input);
|
|
this.clerkUrl = this.deriveUrlFromHeaders(this);
|
|
this.cookies = this.parseCookies(this);
|
|
}
|
|
toJSON() {
|
|
return {
|
|
url: this.clerkUrl.href,
|
|
method: this.method,
|
|
headers: JSON.stringify(Object.fromEntries(this.headers)),
|
|
clerkUrl: this.clerkUrl.toString(),
|
|
cookies: JSON.stringify(Object.fromEntries(this.cookies))
|
|
};
|
|
}
|
|
/**
|
|
* Used to fix request.url using the x-forwarded-* headers
|
|
* TODO add detailed description of the issues this solves
|
|
*/
|
|
deriveUrlFromHeaders(req) {
|
|
const initialUrl = new URL(req.url);
|
|
const forwardedProto = req.headers.get(constants.Headers.ForwardedProto);
|
|
const forwardedHost = req.headers.get(constants.Headers.ForwardedHost);
|
|
const host = req.headers.get(constants.Headers.Host);
|
|
const protocol = initialUrl.protocol;
|
|
const resolvedHost = this.getFirstValueFromHeader(forwardedHost) ?? host;
|
|
const resolvedProtocol = this.getFirstValueFromHeader(forwardedProto) ?? protocol?.replace(/[:/]/, "");
|
|
const origin = resolvedHost && resolvedProtocol ? `${resolvedProtocol}://${resolvedHost}` : initialUrl.origin;
|
|
if (origin === initialUrl.origin) {
|
|
return createClerkUrl(initialUrl);
|
|
}
|
|
try {
|
|
return createClerkUrl(initialUrl.pathname + initialUrl.search, origin);
|
|
} catch {
|
|
return createClerkUrl(initialUrl);
|
|
}
|
|
}
|
|
getFirstValueFromHeader(value) {
|
|
return value?.split(",")[0];
|
|
}
|
|
parseCookies(req) {
|
|
const cookiesRecord = (0, import_cookie.parse)(this.decodeCookieValue(req.headers.get("cookie") || ""));
|
|
return new Map(Object.entries(cookiesRecord));
|
|
}
|
|
decodeCookieValue(str) {
|
|
return str ? str.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent) : str;
|
|
}
|
|
};
|
|
var createClerkRequest = (...args) => {
|
|
const isClerkRequest = args[0] && typeof args[0] === "object" && "clerkUrl" in args[0] && "cookies" in args[0];
|
|
return isClerkRequest ? args[0] : new ClerkRequest(...args);
|
|
};
|
|
|
|
// src/tokens/cookie.ts
|
|
var getCookieName = (cookieDirective) => {
|
|
return cookieDirective.split(";")[0]?.split("=")[0];
|
|
};
|
|
var getCookieValue = (cookieDirective) => {
|
|
return cookieDirective.split(";")[0]?.split("=")[1];
|
|
};
|
|
|
|
// src/tokens/verify.ts
|
|
var import_error5 = require("@clerk/shared/error");
|
|
async function verifyToken(token, options) {
|
|
const { data: decodedResult, errors } = decodeJwt(token);
|
|
if (errors) {
|
|
return { errors };
|
|
}
|
|
const { header } = decodedResult;
|
|
const { kid } = header;
|
|
try {
|
|
let key;
|
|
if (options.jwtKey) {
|
|
key = loadClerkJwkFromPem({ kid, pem: options.jwtKey });
|
|
} else if (options.secretKey) {
|
|
key = await loadClerkJWKFromRemote({ ...options, kid });
|
|
} else {
|
|
return {
|
|
errors: [
|
|
new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.SetClerkJWTKey,
|
|
message: "Failed to resolve JWK during verification.",
|
|
reason: TokenVerificationErrorReason.JWKFailedToResolve
|
|
})
|
|
]
|
|
};
|
|
}
|
|
return await verifyJwt(token, { ...options, key });
|
|
} catch (error) {
|
|
return { errors: [error] };
|
|
}
|
|
}
|
|
function handleClerkAPIError(tokenType, err, notFoundMessage) {
|
|
if ((0, import_error5.isClerkAPIResponseError)(err)) {
|
|
let code;
|
|
let message;
|
|
switch (err.status) {
|
|
case 401:
|
|
code = MachineTokenVerificationErrorCode.InvalidSecretKey;
|
|
message = err.errors[0]?.message || "Invalid secret key";
|
|
break;
|
|
case 404:
|
|
code = MachineTokenVerificationErrorCode.TokenInvalid;
|
|
message = notFoundMessage;
|
|
break;
|
|
default:
|
|
code = MachineTokenVerificationErrorCode.UnexpectedError;
|
|
message = "Unexpected error";
|
|
}
|
|
return {
|
|
data: void 0,
|
|
tokenType,
|
|
errors: [
|
|
new MachineTokenVerificationError({
|
|
message,
|
|
code,
|
|
status: err.status
|
|
})
|
|
]
|
|
};
|
|
}
|
|
return {
|
|
data: void 0,
|
|
tokenType,
|
|
errors: [
|
|
new MachineTokenVerificationError({
|
|
message: "Unexpected error",
|
|
code: MachineTokenVerificationErrorCode.UnexpectedError,
|
|
status: err.status
|
|
})
|
|
]
|
|
};
|
|
}
|
|
async function verifyM2MToken(token, options) {
|
|
try {
|
|
const client = createBackendApiClient(options);
|
|
const verifiedToken = await client.m2m.verify({ token });
|
|
return { data: verifiedToken, tokenType: TokenType.M2MToken, errors: void 0 };
|
|
} catch (err) {
|
|
return handleClerkAPIError(TokenType.M2MToken, err, "Machine token not found");
|
|
}
|
|
}
|
|
async function verifyOAuthToken(accessToken, options) {
|
|
try {
|
|
const client = createBackendApiClient(options);
|
|
const verifiedToken = await client.idPOAuthAccessToken.verify(accessToken);
|
|
return { data: verifiedToken, tokenType: TokenType.OAuthToken, errors: void 0 };
|
|
} catch (err) {
|
|
return handleClerkAPIError(TokenType.OAuthToken, err, "OAuth token not found");
|
|
}
|
|
}
|
|
async function verifyAPIKey(secret, options) {
|
|
try {
|
|
const client = createBackendApiClient(options);
|
|
const verifiedToken = await client.apiKeys.verify(secret);
|
|
return { data: verifiedToken, tokenType: TokenType.ApiKey, errors: void 0 };
|
|
} catch (err) {
|
|
return handleClerkAPIError(TokenType.ApiKey, err, "API key not found");
|
|
}
|
|
}
|
|
async function verifyMachineAuthToken(token, options) {
|
|
if (isJwtFormat(token)) {
|
|
let decodedResult;
|
|
try {
|
|
const { data, errors: decodeErrors } = decodeJwt(token);
|
|
if (decodeErrors) {
|
|
throw decodeErrors[0];
|
|
}
|
|
decodedResult = data;
|
|
} catch (e) {
|
|
return {
|
|
data: void 0,
|
|
tokenType: TokenType.M2MToken,
|
|
errors: [
|
|
new MachineTokenVerificationError({
|
|
code: MachineTokenVerificationErrorCode.TokenInvalid,
|
|
message: e.message
|
|
})
|
|
]
|
|
};
|
|
}
|
|
if (decodedResult.payload.sub.startsWith(M2M_SUBJECT_PREFIX)) {
|
|
return verifyM2MJwt(token, decodedResult, options);
|
|
}
|
|
if (OAUTH_ACCESS_TOKEN_TYPES.includes(decodedResult.header.typ)) {
|
|
return verifyOAuthJwt(token, decodedResult, options);
|
|
}
|
|
return {
|
|
data: void 0,
|
|
tokenType: TokenType.OAuthToken,
|
|
errors: [
|
|
new MachineTokenVerificationError({
|
|
code: MachineTokenVerificationErrorCode.TokenVerificationFailed,
|
|
message: `Invalid JWT type: ${decodedResult.header.typ ?? "missing"}. Expected one of: ${OAUTH_ACCESS_TOKEN_TYPES.join(", ")} for OAuth, or sub starting with 'mch_' for M2M`
|
|
})
|
|
]
|
|
};
|
|
}
|
|
if (token.startsWith(M2M_TOKEN_PREFIX)) {
|
|
return verifyM2MToken(token, options);
|
|
}
|
|
if (token.startsWith(OAUTH_TOKEN_PREFIX)) {
|
|
return verifyOAuthToken(token, options);
|
|
}
|
|
if (token.startsWith(API_KEY_PREFIX)) {
|
|
return verifyAPIKey(token, options);
|
|
}
|
|
throw new Error("Unknown machine token type");
|
|
}
|
|
|
|
// src/tokens/handshake.ts
|
|
async function verifyHandshakeJwt(token, { key }) {
|
|
const { data: decoded, errors } = decodeJwt(token);
|
|
if (errors) {
|
|
throw errors[0];
|
|
}
|
|
const { header, payload } = decoded;
|
|
const { typ, alg } = header;
|
|
assertHeaderType(typ);
|
|
assertHeaderAlgorithm(alg);
|
|
const { data: signatureValid, errors: signatureErrors } = await hasValidSignature(decoded, key);
|
|
if (signatureErrors) {
|
|
throw new TokenVerificationError({
|
|
reason: TokenVerificationErrorReason.TokenVerificationFailed,
|
|
message: `Error verifying handshake token. ${signatureErrors[0]}`
|
|
});
|
|
}
|
|
if (!signatureValid) {
|
|
throw new TokenVerificationError({
|
|
reason: TokenVerificationErrorReason.TokenInvalidSignature,
|
|
message: "Handshake signature is invalid."
|
|
});
|
|
}
|
|
return payload;
|
|
}
|
|
async function verifyHandshakeToken(token, options) {
|
|
const { secretKey, apiUrl, apiVersion, jwksCacheTtlInMs, jwtKey, skipJwksCache } = options;
|
|
const { data, errors } = decodeJwt(token);
|
|
if (errors) {
|
|
throw errors[0];
|
|
}
|
|
const { kid } = data.header;
|
|
let key;
|
|
if (jwtKey) {
|
|
key = loadClerkJwkFromPem({ kid, pem: jwtKey });
|
|
} else if (secretKey) {
|
|
key = await loadClerkJWKFromRemote({ secretKey, apiUrl, apiVersion, kid, jwksCacheTtlInMs, skipJwksCache });
|
|
} else {
|
|
throw new TokenVerificationError({
|
|
action: TokenVerificationErrorAction.SetClerkJWTKey,
|
|
message: "Failed to resolve JWK during handshake verification.",
|
|
reason: TokenVerificationErrorReason.JWKFailedToResolve
|
|
});
|
|
}
|
|
return verifyHandshakeJwt(token, { key });
|
|
}
|
|
var HandshakeService = class {
|
|
constructor(authenticateContext, options, organizationMatcher) {
|
|
this.authenticateContext = authenticateContext;
|
|
this.options = options;
|
|
this.organizationMatcher = organizationMatcher;
|
|
}
|
|
/**
|
|
* Determines if a request is eligible for handshake based on its headers
|
|
*
|
|
* Currently, a request is only eligible for a handshake if we can say it's *probably* a request for a document, not a fetch or some other exotic request.
|
|
* This heuristic should give us a reliable enough signal for browsers that support `Sec-Fetch-Dest` and for those that don't.
|
|
*
|
|
* @returns boolean indicating if the request is eligible for handshake
|
|
*/
|
|
isRequestEligibleForHandshake() {
|
|
const { accept, method, secFetchDest } = this.authenticateContext;
|
|
if (method !== "GET") {
|
|
return false;
|
|
}
|
|
if (secFetchDest === "document" || secFetchDest === "iframe") {
|
|
return true;
|
|
}
|
|
if (!secFetchDest && accept?.startsWith("text/html")) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* Builds the redirect headers for a handshake request
|
|
* @param reason - The reason for the handshake (e.g. 'session-token-expired')
|
|
* @returns Headers object containing the Location header for redirect
|
|
* @throws Error if clerkUrl is missing in authenticateContext
|
|
*/
|
|
buildRedirectToHandshake(reason) {
|
|
if (!this.authenticateContext?.clerkUrl) {
|
|
throw new Error("Missing clerkUrl in authenticateContext");
|
|
}
|
|
const redirectUrl = this.removeDevBrowserFromURL(this.authenticateContext.clerkUrl);
|
|
let baseUrl = this.authenticateContext.frontendApi.startsWith("http") ? this.authenticateContext.frontendApi : `https://${this.authenticateContext.frontendApi}`;
|
|
baseUrl = baseUrl.replace(/\/+$/, "") + "/";
|
|
const url = new URL("v1/client/handshake", baseUrl);
|
|
url.searchParams.append("redirect_url", redirectUrl?.href || "");
|
|
url.searchParams.append("__clerk_api_version", SUPPORTED_BAPI_VERSION);
|
|
url.searchParams.append(
|
|
constants.QueryParameters.SuffixedCookies,
|
|
this.authenticateContext.usesSuffixedCookies().toString()
|
|
);
|
|
url.searchParams.append(constants.QueryParameters.HandshakeReason, reason);
|
|
url.searchParams.append(constants.QueryParameters.HandshakeFormat, "nonce");
|
|
if (this.authenticateContext.sessionToken) {
|
|
url.searchParams.append(constants.QueryParameters.Session, this.authenticateContext.sessionToken);
|
|
}
|
|
if (this.authenticateContext.instanceType === "development" && this.authenticateContext.devBrowserToken) {
|
|
url.searchParams.append(constants.QueryParameters.DevBrowser, this.authenticateContext.devBrowserToken);
|
|
}
|
|
const toActivate = this.getOrganizationSyncTarget(this.authenticateContext.clerkUrl, this.organizationMatcher);
|
|
if (toActivate) {
|
|
const params = this.getOrganizationSyncQueryParams(toActivate);
|
|
params.forEach((value, key) => {
|
|
url.searchParams.append(key, value);
|
|
});
|
|
}
|
|
return new Headers({ [constants.Headers.Location]: url.href });
|
|
}
|
|
/**
|
|
* Gets cookies from either a handshake nonce or a handshake token
|
|
* @returns Promise resolving to string array of cookie directives
|
|
*/
|
|
async getCookiesFromHandshake() {
|
|
const cookiesToSet = [];
|
|
if (this.authenticateContext.handshakeNonce) {
|
|
try {
|
|
const handshakePayload = await this.authenticateContext.apiClient?.clients.getHandshakePayload({
|
|
nonce: this.authenticateContext.handshakeNonce
|
|
});
|
|
if (handshakePayload) {
|
|
cookiesToSet.push(...handshakePayload.directives);
|
|
}
|
|
} catch (error) {
|
|
console.error("Clerk: HandshakeService: error getting handshake payload:", error);
|
|
}
|
|
} else if (this.authenticateContext.handshakeToken) {
|
|
const handshakePayload = await verifyHandshakeToken(
|
|
this.authenticateContext.handshakeToken,
|
|
this.authenticateContext
|
|
);
|
|
if (handshakePayload && Array.isArray(handshakePayload.handshake)) {
|
|
cookiesToSet.push(...handshakePayload.handshake);
|
|
}
|
|
}
|
|
return cookiesToSet;
|
|
}
|
|
/**
|
|
* Resolves a handshake request by verifying the handshake token and setting appropriate cookies
|
|
* @returns Promise resolving to either a SignedInState or SignedOutState
|
|
* @throws Error if handshake verification fails or if there are issues with the session token
|
|
*/
|
|
async resolveHandshake() {
|
|
const headers = new Headers({
|
|
"Access-Control-Allow-Origin": "null",
|
|
"Access-Control-Allow-Credentials": "true"
|
|
});
|
|
const cookiesToSet = await this.getCookiesFromHandshake();
|
|
let sessionToken = "";
|
|
cookiesToSet.forEach((x) => {
|
|
headers.append("Set-Cookie", x);
|
|
if (getCookieName(x).startsWith(constants.Cookies.Session)) {
|
|
sessionToken = getCookieValue(x);
|
|
}
|
|
});
|
|
if (this.authenticateContext.instanceType === "development") {
|
|
const newUrl = new URL(this.authenticateContext.clerkUrl);
|
|
newUrl.searchParams.delete(constants.QueryParameters.Handshake);
|
|
newUrl.searchParams.delete(constants.QueryParameters.HandshakeHelp);
|
|
newUrl.searchParams.delete(constants.QueryParameters.DevBrowser);
|
|
newUrl.searchParams.delete(constants.QueryParameters.HandshakeNonce);
|
|
headers.append(constants.Headers.Location, newUrl.toString());
|
|
headers.set(constants.Headers.CacheControl, "no-store");
|
|
}
|
|
if (sessionToken === "") {
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext: this.authenticateContext,
|
|
reason: AuthErrorReason.SessionTokenMissing,
|
|
message: "",
|
|
headers
|
|
});
|
|
}
|
|
const { data, errors: [error] = [] } = await verifyToken(sessionToken, this.authenticateContext);
|
|
if (data) {
|
|
return signedIn({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext: this.authenticateContext,
|
|
sessionClaims: data,
|
|
headers,
|
|
token: sessionToken
|
|
});
|
|
}
|
|
if (this.authenticateContext.instanceType === "development" && (error?.reason === TokenVerificationErrorReason.TokenExpired || error?.reason === TokenVerificationErrorReason.TokenNotActiveYet || error?.reason === TokenVerificationErrorReason.TokenIatInTheFuture)) {
|
|
const developmentError = new TokenVerificationError({
|
|
action: error.action,
|
|
message: error.message,
|
|
reason: error.reason
|
|
});
|
|
developmentError.tokenCarrier = "cookie";
|
|
console.error(
|
|
`Clerk: Clock skew detected. This usually means that your system clock is inaccurate. Clerk will attempt to account for the clock skew in development.
|
|
|
|
To resolve this issue, make sure your system's clock is set to the correct time (e.g. turn off and on automatic time synchronization).
|
|
|
|
---
|
|
|
|
${developmentError.getFullMessage()}`
|
|
);
|
|
const { data: retryResult, errors: [retryError] = [] } = await verifyToken(sessionToken, {
|
|
...this.authenticateContext,
|
|
clockSkewInMs: 864e5
|
|
});
|
|
if (retryResult) {
|
|
return signedIn({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext: this.authenticateContext,
|
|
sessionClaims: retryResult,
|
|
headers,
|
|
token: sessionToken
|
|
});
|
|
}
|
|
throw new Error(retryError?.message || "Clerk: Handshake retry failed.");
|
|
}
|
|
throw new Error(error?.message || "Clerk: Handshake failed.");
|
|
}
|
|
/**
|
|
* Handles handshake token verification errors in development mode
|
|
* @param error - The TokenVerificationError that occurred
|
|
* @throws Error with a descriptive message about the verification failure
|
|
*/
|
|
handleTokenVerificationErrorInDevelopment(error) {
|
|
if (error.reason === TokenVerificationErrorReason.TokenInvalidSignature) {
|
|
const msg = `Clerk: Handshake token verification failed due to an invalid signature. If you have switched Clerk keys locally, clear your cookies and try again.`;
|
|
throw new Error(msg);
|
|
}
|
|
throw new Error(`Clerk: Handshake token verification failed: ${error.getFullMessage()}.`);
|
|
}
|
|
/**
|
|
* Checks if a redirect loop is detected and sets headers to track redirect count
|
|
* @param headers - The Headers object to modify
|
|
* @returns boolean indicating if a redirect loop was detected (true) or if the request can proceed (false)
|
|
*/
|
|
checkAndTrackRedirectLoop(headers) {
|
|
if (this.authenticateContext.handshakeRedirectLoopCounter === 3) {
|
|
return true;
|
|
}
|
|
const newCounterValue = this.authenticateContext.handshakeRedirectLoopCounter + 1;
|
|
const cookieName = constants.Cookies.RedirectCount;
|
|
headers.append("Set-Cookie", `${cookieName}=${newCounterValue}; SameSite=Lax; HttpOnly; Max-Age=2`);
|
|
return false;
|
|
}
|
|
removeDevBrowserFromURL(url) {
|
|
const updatedURL = new URL(url);
|
|
updatedURL.searchParams.delete(constants.QueryParameters.DevBrowser);
|
|
updatedURL.searchParams.delete(constants.QueryParameters.LegacyDevBrowser);
|
|
return updatedURL;
|
|
}
|
|
getOrganizationSyncTarget(url, matchers) {
|
|
return matchers.findTarget(url);
|
|
}
|
|
getOrganizationSyncQueryParams(toActivate) {
|
|
const ret = /* @__PURE__ */ new Map();
|
|
if (toActivate.type === "personalAccount") {
|
|
ret.set("organization_id", "");
|
|
}
|
|
if (toActivate.type === "organization") {
|
|
if (toActivate.organizationId) {
|
|
ret.set("organization_id", toActivate.organizationId);
|
|
}
|
|
if (toActivate.organizationSlug) {
|
|
ret.set("organization_id", toActivate.organizationSlug);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
// src/tokens/organizationMatcher.ts
|
|
var import_pathToRegexp = require("@clerk/shared/pathToRegexp");
|
|
var OrganizationMatcher = class {
|
|
constructor(options) {
|
|
this.organizationPattern = this.createMatcher(options?.organizationPatterns);
|
|
this.personalAccountPattern = this.createMatcher(options?.personalAccountPatterns);
|
|
}
|
|
createMatcher(pattern) {
|
|
if (!pattern) {
|
|
return null;
|
|
}
|
|
try {
|
|
return (0, import_pathToRegexp.match)(pattern);
|
|
} catch (e) {
|
|
throw new Error(`Invalid pattern "${pattern}": ${e}`);
|
|
}
|
|
}
|
|
findTarget(url) {
|
|
const orgTarget = this.findOrganizationTarget(url);
|
|
if (orgTarget) {
|
|
return orgTarget;
|
|
}
|
|
return this.findPersonalAccountTarget(url);
|
|
}
|
|
findOrganizationTarget(url) {
|
|
if (!this.organizationPattern) {
|
|
return null;
|
|
}
|
|
try {
|
|
const result = this.organizationPattern(url.pathname);
|
|
if (!result || !("params" in result)) {
|
|
return null;
|
|
}
|
|
const params = result.params;
|
|
if (params.id) {
|
|
return { type: "organization", organizationId: params.id };
|
|
}
|
|
if (params.slug) {
|
|
return { type: "organization", organizationSlug: params.slug };
|
|
}
|
|
return null;
|
|
} catch (e) {
|
|
console.error("Failed to match organization pattern:", e);
|
|
return null;
|
|
}
|
|
}
|
|
findPersonalAccountTarget(url) {
|
|
if (!this.personalAccountPattern) {
|
|
return null;
|
|
}
|
|
try {
|
|
const result = this.personalAccountPattern(url.pathname);
|
|
return result ? { type: "personalAccount" } : null;
|
|
} catch (e) {
|
|
console.error("Failed to match personal account pattern:", e);
|
|
return null;
|
|
}
|
|
}
|
|
};
|
|
|
|
// src/tokens/request.ts
|
|
var RefreshTokenErrorReason = {
|
|
NonEligibleNoCookie: "non-eligible-no-refresh-cookie",
|
|
NonEligibleNonGet: "non-eligible-non-get",
|
|
InvalidSessionToken: "invalid-session-token",
|
|
MissingApiClient: "missing-api-client",
|
|
MissingSessionToken: "missing-session-token",
|
|
MissingRefreshToken: "missing-refresh-token",
|
|
ExpiredSessionTokenDecodeFailed: "expired-session-token-decode-failed",
|
|
ExpiredSessionTokenMissingSidClaim: "expired-session-token-missing-sid-claim",
|
|
FetchError: "fetch-error",
|
|
UnexpectedSDKError: "unexpected-sdk-error",
|
|
UnexpectedBAPIError: "unexpected-bapi-error"
|
|
};
|
|
function assertSignInUrlExists(signInUrl, key) {
|
|
if (!signInUrl && (0, import_keys.isDevelopmentFromSecretKey)(key)) {
|
|
throw new Error(`Missing signInUrl. Pass a signInUrl for dev instances if an app is satellite`);
|
|
}
|
|
}
|
|
function assertProxyUrlOrDomain(proxyUrlOrDomain) {
|
|
if (!proxyUrlOrDomain) {
|
|
throw new Error(`Missing domain and proxyUrl. A satellite application needs to specify a domain or a proxyUrl`);
|
|
}
|
|
}
|
|
function assertSignInUrlFormatAndOrigin(_signInUrl, origin) {
|
|
let signInUrl;
|
|
try {
|
|
signInUrl = new URL(_signInUrl);
|
|
} catch {
|
|
throw new Error(`The signInUrl needs to have a absolute url format.`);
|
|
}
|
|
if (signInUrl.origin === origin) {
|
|
throw new Error(`The signInUrl needs to be on a different origin than your satellite application.`);
|
|
}
|
|
}
|
|
function assertMachineSecretOrSecretKey(authenticateContext) {
|
|
if (!authenticateContext.machineSecretKey && !authenticateContext.secretKey) {
|
|
throw new Error(
|
|
"Machine token authentication requires either a Machine secret key or a Clerk secret key. Ensure a Clerk secret key or Machine secret key is set."
|
|
);
|
|
}
|
|
}
|
|
function isRequestEligibleForRefresh(err, authenticateContext, request) {
|
|
return err.reason === TokenVerificationErrorReason.TokenExpired && !!authenticateContext.refreshTokenInCookie && request.method === "GET";
|
|
}
|
|
function checkTokenTypeMismatch(parsedTokenType, acceptsToken, authenticateContext) {
|
|
const mismatch = !isTokenTypeAccepted(parsedTokenType, acceptsToken);
|
|
if (mismatch) {
|
|
const tokenTypeToReturn = typeof acceptsToken === "string" ? acceptsToken : parsedTokenType;
|
|
return signedOut({
|
|
tokenType: tokenTypeToReturn,
|
|
authenticateContext,
|
|
reason: AuthErrorReason.TokenTypeMismatch
|
|
});
|
|
}
|
|
return null;
|
|
}
|
|
function isTokenTypeInAcceptedArray(acceptsToken, authenticateContext) {
|
|
let parsedTokenType = null;
|
|
const { tokenInHeader } = authenticateContext;
|
|
if (tokenInHeader) {
|
|
if (isMachineToken(tokenInHeader)) {
|
|
parsedTokenType = getMachineTokenType(tokenInHeader);
|
|
} else {
|
|
parsedTokenType = TokenType.SessionToken;
|
|
}
|
|
}
|
|
const typeToCheck = parsedTokenType ?? TokenType.SessionToken;
|
|
return isTokenTypeAccepted(typeToCheck, acceptsToken);
|
|
}
|
|
var authenticateRequest = (async (request, options) => {
|
|
const authenticateContext = await createAuthenticateContext(createClerkRequest(request), options);
|
|
const acceptsToken = options.acceptsToken ?? TokenType.SessionToken;
|
|
if (acceptsToken !== TokenType.M2MToken) {
|
|
assertValidSecretKey(authenticateContext.secretKey);
|
|
if (authenticateContext.isSatellite) {
|
|
assertSignInUrlExists(authenticateContext.signInUrl, authenticateContext.secretKey);
|
|
if (authenticateContext.signInUrl && authenticateContext.origin) {
|
|
assertSignInUrlFormatAndOrigin(authenticateContext.signInUrl, authenticateContext.origin);
|
|
}
|
|
assertProxyUrlOrDomain(authenticateContext.proxyUrl || authenticateContext.domain);
|
|
}
|
|
}
|
|
if (acceptsToken === TokenType.M2MToken) {
|
|
assertMachineSecretOrSecretKey(authenticateContext);
|
|
}
|
|
const organizationMatcher = new OrganizationMatcher(options.organizationSyncOptions);
|
|
const handshakeService = new HandshakeService(
|
|
authenticateContext,
|
|
{ organizationSyncOptions: options.organizationSyncOptions },
|
|
organizationMatcher
|
|
);
|
|
async function refreshToken(authenticateContext2) {
|
|
if (!options.apiClient) {
|
|
return {
|
|
data: null,
|
|
error: {
|
|
message: "An apiClient is needed to perform token refresh.",
|
|
cause: { reason: RefreshTokenErrorReason.MissingApiClient }
|
|
}
|
|
};
|
|
}
|
|
const { sessionToken: expiredSessionToken, refreshTokenInCookie: refreshToken2 } = authenticateContext2;
|
|
if (!expiredSessionToken) {
|
|
return {
|
|
data: null,
|
|
error: {
|
|
message: "Session token must be provided.",
|
|
cause: { reason: RefreshTokenErrorReason.MissingSessionToken }
|
|
}
|
|
};
|
|
}
|
|
if (!refreshToken2) {
|
|
return {
|
|
data: null,
|
|
error: {
|
|
message: "Refresh token must be provided.",
|
|
cause: { reason: RefreshTokenErrorReason.MissingRefreshToken }
|
|
}
|
|
};
|
|
}
|
|
const { data: decodeResult, errors: decodedErrors } = decodeJwt(expiredSessionToken);
|
|
if (!decodeResult || decodedErrors) {
|
|
return {
|
|
data: null,
|
|
error: {
|
|
message: "Unable to decode the expired session token.",
|
|
cause: { reason: RefreshTokenErrorReason.ExpiredSessionTokenDecodeFailed, errors: decodedErrors }
|
|
}
|
|
};
|
|
}
|
|
if (!decodeResult?.payload?.sid) {
|
|
return {
|
|
data: null,
|
|
error: {
|
|
message: "Expired session token is missing the `sid` claim.",
|
|
cause: { reason: RefreshTokenErrorReason.ExpiredSessionTokenMissingSidClaim }
|
|
}
|
|
};
|
|
}
|
|
try {
|
|
const response = await options.apiClient.sessions.refreshSession(decodeResult.payload.sid, {
|
|
format: "cookie",
|
|
suffixed_cookies: authenticateContext2.usesSuffixedCookies(),
|
|
expired_token: expiredSessionToken || "",
|
|
refresh_token: refreshToken2 || "",
|
|
request_origin: authenticateContext2.clerkUrl.origin,
|
|
// The refresh endpoint expects headers as Record<string, string[]>, so we need to transform it.
|
|
request_headers: Object.fromEntries(Array.from(request.headers.entries()).map(([k, v]) => [k, [v]]))
|
|
});
|
|
return { data: response.cookies, error: null };
|
|
} catch (err) {
|
|
if (err?.errors?.length) {
|
|
if (err.errors[0].code === "unexpected_error") {
|
|
return {
|
|
data: null,
|
|
error: {
|
|
message: `Fetch unexpected error`,
|
|
cause: { reason: RefreshTokenErrorReason.FetchError, errors: err.errors }
|
|
}
|
|
};
|
|
}
|
|
return {
|
|
data: null,
|
|
error: {
|
|
message: err.errors[0].code,
|
|
cause: { reason: err.errors[0].code, errors: err.errors }
|
|
}
|
|
};
|
|
} else {
|
|
return {
|
|
data: null,
|
|
error: {
|
|
message: `Unexpected Server/BAPI error`,
|
|
cause: { reason: RefreshTokenErrorReason.UnexpectedBAPIError, errors: [err] }
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
async function attemptRefresh(authenticateContext2) {
|
|
const { data: cookiesToSet, error } = await refreshToken(authenticateContext2);
|
|
if (!cookiesToSet || cookiesToSet.length === 0) {
|
|
return { data: null, error };
|
|
}
|
|
const headers = new Headers();
|
|
let sessionToken = "";
|
|
cookiesToSet.forEach((x) => {
|
|
headers.append("Set-Cookie", x);
|
|
if (getCookieName(x).startsWith(constants.Cookies.Session)) {
|
|
sessionToken = getCookieValue(x);
|
|
}
|
|
});
|
|
const { data: jwtPayload, errors } = await verifyToken(sessionToken, authenticateContext2);
|
|
if (errors) {
|
|
return {
|
|
data: null,
|
|
error: {
|
|
message: `Clerk: unable to verify refreshed session token.`,
|
|
cause: { reason: RefreshTokenErrorReason.InvalidSessionToken, errors }
|
|
}
|
|
};
|
|
}
|
|
return { data: { jwtPayload, sessionToken, headers }, error: null };
|
|
}
|
|
function handleMaybeHandshakeStatus(authenticateContext2, reason, message, headers) {
|
|
if (!handshakeService.isRequestEligibleForHandshake()) {
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext: authenticateContext2,
|
|
reason,
|
|
message
|
|
});
|
|
}
|
|
const handshakeHeaders = headers ?? handshakeService.buildRedirectToHandshake(reason);
|
|
if (handshakeHeaders.get(constants.Headers.Location)) {
|
|
handshakeHeaders.set(constants.Headers.CacheControl, "no-store");
|
|
}
|
|
const isRedirectLoop = handshakeService.checkAndTrackRedirectLoop(handshakeHeaders);
|
|
if (isRedirectLoop) {
|
|
const msg = `Clerk: Refreshing the session token resulted in an infinite redirect loop. This usually means that your Clerk instance keys do not match - make sure to copy the correct publishable and secret keys from the Clerk dashboard.`;
|
|
console.log(msg);
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext: authenticateContext2,
|
|
reason,
|
|
message
|
|
});
|
|
}
|
|
return handshake(authenticateContext2, reason, message, handshakeHeaders);
|
|
}
|
|
function handleMaybeOrganizationSyncHandshake(authenticateContext2, auth) {
|
|
const organizationSyncTarget = organizationMatcher.findTarget(authenticateContext2.clerkUrl);
|
|
if (!organizationSyncTarget) {
|
|
return null;
|
|
}
|
|
let mustActivate = false;
|
|
if (organizationSyncTarget.type === "organization") {
|
|
if (organizationSyncTarget.organizationSlug && organizationSyncTarget.organizationSlug !== auth.orgSlug) {
|
|
mustActivate = true;
|
|
}
|
|
if (organizationSyncTarget.organizationId && organizationSyncTarget.organizationId !== auth.orgId) {
|
|
mustActivate = true;
|
|
}
|
|
}
|
|
if (organizationSyncTarget.type === "personalAccount" && auth.orgId) {
|
|
mustActivate = true;
|
|
}
|
|
if (!mustActivate) {
|
|
return null;
|
|
}
|
|
if (authenticateContext2.handshakeRedirectLoopCounter >= 3) {
|
|
console.warn(
|
|
"Clerk: Organization activation handshake loop detected. This is likely due to an invalid organization ID or slug. Skipping organization activation."
|
|
);
|
|
return null;
|
|
}
|
|
const handshakeState = handleMaybeHandshakeStatus(
|
|
authenticateContext2,
|
|
AuthErrorReason.ActiveOrganizationMismatch,
|
|
""
|
|
);
|
|
if (handshakeState.status !== "handshake") {
|
|
return null;
|
|
}
|
|
return handshakeState;
|
|
}
|
|
async function authenticateRequestWithTokenInHeader() {
|
|
const { tokenInHeader } = authenticateContext;
|
|
if (isMachineJwt(tokenInHeader)) {
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
reason: AuthErrorReason.TokenTypeMismatch,
|
|
message: ""
|
|
});
|
|
}
|
|
try {
|
|
const { data, errors } = await verifyToken(tokenInHeader, authenticateContext);
|
|
if (errors) {
|
|
throw errors[0];
|
|
}
|
|
return signedIn({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
sessionClaims: data,
|
|
headers: new Headers(),
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
token: tokenInHeader
|
|
});
|
|
} catch (err) {
|
|
return handleSessionTokenError(err, "header");
|
|
}
|
|
}
|
|
async function authenticateRequestWithTokenInCookie() {
|
|
const hasActiveClient = authenticateContext.clientUat;
|
|
const hasSessionToken = !!authenticateContext.sessionTokenInCookie;
|
|
const hasDevBrowserToken = !!authenticateContext.devBrowserToken;
|
|
if (authenticateContext.handshakeNonce || authenticateContext.handshakeToken) {
|
|
try {
|
|
return await handshakeService.resolveHandshake();
|
|
} catch (error) {
|
|
if (error instanceof TokenVerificationError && authenticateContext.instanceType === "development") {
|
|
handshakeService.handleTokenVerificationErrorInDevelopment(error);
|
|
} else {
|
|
console.error("Clerk: unable to resolve handshake:", error);
|
|
}
|
|
}
|
|
}
|
|
const isRequestEligibleForMultiDomainSync = authenticateContext.isSatellite && authenticateContext.secFetchDest === "document" && authenticateContext.method === "GET";
|
|
const syncedParam = authenticateContext.clerkUrl.searchParams.get(constants.QueryParameters.ClerkSynced);
|
|
const needsSync = syncedParam === constants.ClerkSyncStatus.NeedsSync;
|
|
const syncCompleted = syncedParam === constants.ClerkSyncStatus.Completed;
|
|
const hasCookies = hasSessionToken || hasActiveClient;
|
|
const shouldSkipSatelliteHandshake = authenticateContext.satelliteAutoSync !== true && !hasCookies && !needsSync;
|
|
if (authenticateContext.instanceType === "production" && isRequestEligibleForMultiDomainSync && !syncCompleted) {
|
|
if (shouldSkipSatelliteHandshake) {
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
reason: AuthErrorReason.SessionTokenAndUATMissing
|
|
});
|
|
}
|
|
if (!hasCookies || needsSync) {
|
|
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.SatelliteCookieNeedsSyncing, "");
|
|
}
|
|
}
|
|
if (authenticateContext.instanceType === "development" && isRequestEligibleForMultiDomainSync && !syncCompleted) {
|
|
if (shouldSkipSatelliteHandshake) {
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
reason: AuthErrorReason.SessionTokenAndUATMissing
|
|
});
|
|
}
|
|
if (!hasCookies || needsSync) {
|
|
const redirectURL = new URL(authenticateContext.signInUrl);
|
|
redirectURL.searchParams.append(
|
|
constants.QueryParameters.ClerkRedirectUrl,
|
|
authenticateContext.clerkUrl.toString()
|
|
);
|
|
const headers = new Headers({ [constants.Headers.Location]: redirectURL.toString() });
|
|
return handleMaybeHandshakeStatus(
|
|
authenticateContext,
|
|
AuthErrorReason.SatelliteCookieNeedsSyncing,
|
|
"",
|
|
headers
|
|
);
|
|
}
|
|
}
|
|
const redirectUrl = new URL(authenticateContext.clerkUrl).searchParams.get(
|
|
constants.QueryParameters.ClerkRedirectUrl
|
|
);
|
|
if (authenticateContext.instanceType === "development" && !authenticateContext.isSatellite && redirectUrl) {
|
|
const redirectBackToSatelliteUrl = new URL(redirectUrl);
|
|
if (authenticateContext.devBrowserToken) {
|
|
redirectBackToSatelliteUrl.searchParams.append(
|
|
constants.QueryParameters.DevBrowser,
|
|
authenticateContext.devBrowserToken
|
|
);
|
|
}
|
|
redirectBackToSatelliteUrl.searchParams.set(
|
|
constants.QueryParameters.ClerkSynced,
|
|
constants.ClerkSyncStatus.Completed
|
|
);
|
|
const headers = new Headers({ [constants.Headers.Location]: redirectBackToSatelliteUrl.toString() });
|
|
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.PrimaryRespondsToSyncing, "", headers);
|
|
}
|
|
if (authenticateContext.instanceType === "development" && authenticateContext.clerkUrl.searchParams.has(constants.QueryParameters.DevBrowser)) {
|
|
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.DevBrowserSync, "");
|
|
}
|
|
if (authenticateContext.instanceType === "development" && !hasDevBrowserToken) {
|
|
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.DevBrowserMissing, "");
|
|
}
|
|
if (!hasActiveClient && !hasSessionToken) {
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
reason: AuthErrorReason.SessionTokenAndUATMissing
|
|
});
|
|
}
|
|
if (!hasActiveClient && hasSessionToken) {
|
|
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.SessionTokenWithoutClientUAT, "");
|
|
}
|
|
if (hasActiveClient && !hasSessionToken) {
|
|
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.ClientUATWithoutSessionToken, "");
|
|
}
|
|
const { data: decodeResult, errors: decodedErrors } = decodeJwt(authenticateContext.sessionTokenInCookie);
|
|
if (decodedErrors) {
|
|
return handleSessionTokenError(decodedErrors[0], "cookie");
|
|
}
|
|
if (decodeResult.payload.iat < authenticateContext.clientUat) {
|
|
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.SessionTokenIATBeforeClientUAT, "");
|
|
}
|
|
try {
|
|
const { data, errors } = await verifyToken(authenticateContext.sessionTokenInCookie, authenticateContext);
|
|
if (errors) {
|
|
throw errors[0];
|
|
}
|
|
if (!data.azp) {
|
|
console.warn(
|
|
"Clerk: Session token from cookie is missing the azp claim. In a future version of Clerk, this token will be considered invalid. Please contact Clerk support if you see this warning."
|
|
);
|
|
}
|
|
const signedInRequestState = signedIn({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
sessionClaims: data,
|
|
headers: new Headers(),
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
token: authenticateContext.sessionTokenInCookie
|
|
});
|
|
const shouldForceHandshakeForCrossDomain = !authenticateContext.isSatellite && // We're on primary
|
|
authenticateContext.method === "GET" && // Only GET navigations (POST form submissions set sec-fetch-dest: document too)
|
|
authenticateContext.secFetchDest === "document" && // Document navigation
|
|
authenticateContext.isCrossOriginReferrer() && // Came from different domain
|
|
!authenticateContext.isKnownClerkReferrer() && // Not from Clerk accounts portal or FAPI
|
|
authenticateContext.handshakeRedirectLoopCounter === 0;
|
|
if (shouldForceHandshakeForCrossDomain) {
|
|
return handleMaybeHandshakeStatus(
|
|
authenticateContext,
|
|
AuthErrorReason.PrimaryDomainCrossOriginSync,
|
|
"Cross-origin request from satellite domain requires handshake"
|
|
);
|
|
}
|
|
const authObject = signedInRequestState.toAuth();
|
|
if (authObject.userId) {
|
|
const handshakeRequestState = handleMaybeOrganizationSyncHandshake(authenticateContext, authObject);
|
|
if (handshakeRequestState) {
|
|
return handshakeRequestState;
|
|
}
|
|
}
|
|
return signedInRequestState;
|
|
} catch (err) {
|
|
return handleSessionTokenError(err, "cookie");
|
|
}
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
reason: AuthErrorReason.UnexpectedError
|
|
});
|
|
}
|
|
async function handleSessionTokenError(err, tokenCarrier) {
|
|
if (!(err instanceof TokenVerificationError)) {
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
reason: AuthErrorReason.UnexpectedError
|
|
});
|
|
}
|
|
let refreshError;
|
|
if (isRequestEligibleForRefresh(err, authenticateContext, request)) {
|
|
const { data, error } = await attemptRefresh(authenticateContext);
|
|
if (data) {
|
|
return signedIn({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
sessionClaims: data.jwtPayload,
|
|
headers: data.headers,
|
|
token: data.sessionToken
|
|
});
|
|
}
|
|
if (error?.cause?.reason) {
|
|
refreshError = error.cause.reason;
|
|
} else {
|
|
refreshError = RefreshTokenErrorReason.UnexpectedSDKError;
|
|
}
|
|
} else {
|
|
if (request.method !== "GET") {
|
|
refreshError = RefreshTokenErrorReason.NonEligibleNonGet;
|
|
} else if (!authenticateContext.refreshTokenInCookie) {
|
|
refreshError = RefreshTokenErrorReason.NonEligibleNoCookie;
|
|
} else {
|
|
refreshError = null;
|
|
}
|
|
}
|
|
err.tokenCarrier = tokenCarrier;
|
|
const reasonToHandshake = [
|
|
TokenVerificationErrorReason.TokenExpired,
|
|
TokenVerificationErrorReason.TokenNotActiveYet,
|
|
TokenVerificationErrorReason.TokenIatInTheFuture
|
|
].includes(err.reason);
|
|
if (reasonToHandshake) {
|
|
return handleMaybeHandshakeStatus(
|
|
authenticateContext,
|
|
convertTokenVerificationErrorReasonToAuthErrorReason({ tokenError: err.reason, refreshError }),
|
|
err.getFullMessage()
|
|
);
|
|
}
|
|
return signedOut({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
reason: err.reason,
|
|
message: err.getFullMessage()
|
|
});
|
|
}
|
|
function handleMachineError(tokenType, err) {
|
|
if (!(err instanceof MachineTokenVerificationError)) {
|
|
return signedOut({
|
|
tokenType,
|
|
authenticateContext,
|
|
reason: AuthErrorReason.UnexpectedError
|
|
});
|
|
}
|
|
return signedOut({
|
|
tokenType,
|
|
authenticateContext,
|
|
reason: err.code,
|
|
message: err.getFullMessage()
|
|
});
|
|
}
|
|
async function authenticateMachineRequestWithTokenInHeader() {
|
|
const { tokenInHeader } = authenticateContext;
|
|
if (!tokenInHeader) {
|
|
return handleSessionTokenError(new Error("Missing token in header"), "header");
|
|
}
|
|
if (!isMachineToken(tokenInHeader)) {
|
|
return signedOut({
|
|
tokenType: acceptsToken,
|
|
authenticateContext,
|
|
reason: AuthErrorReason.TokenTypeMismatch,
|
|
message: ""
|
|
});
|
|
}
|
|
const parsedTokenType = getMachineTokenType(tokenInHeader);
|
|
const mismatchState = checkTokenTypeMismatch(parsedTokenType, acceptsToken, authenticateContext);
|
|
if (mismatchState) {
|
|
return mismatchState;
|
|
}
|
|
const { data, tokenType, errors } = await verifyMachineAuthToken(tokenInHeader, authenticateContext);
|
|
if (errors) {
|
|
return handleMachineError(tokenType, errors[0]);
|
|
}
|
|
return signedIn({
|
|
tokenType,
|
|
authenticateContext,
|
|
machineData: data,
|
|
token: tokenInHeader
|
|
});
|
|
}
|
|
async function authenticateAnyRequestWithTokenInHeader() {
|
|
const { tokenInHeader } = authenticateContext;
|
|
if (!tokenInHeader) {
|
|
return handleSessionTokenError(new Error("Missing token in header"), "header");
|
|
}
|
|
if (isMachineToken(tokenInHeader)) {
|
|
const parsedTokenType = getMachineTokenType(tokenInHeader);
|
|
const mismatchState = checkTokenTypeMismatch(parsedTokenType, acceptsToken, authenticateContext);
|
|
if (mismatchState) {
|
|
return mismatchState;
|
|
}
|
|
const { data: data2, tokenType, errors: errors2 } = await verifyMachineAuthToken(tokenInHeader, authenticateContext);
|
|
if (errors2) {
|
|
return handleMachineError(tokenType, errors2[0]);
|
|
}
|
|
return signedIn({
|
|
tokenType,
|
|
authenticateContext,
|
|
machineData: data2,
|
|
token: tokenInHeader
|
|
});
|
|
}
|
|
const { data, errors } = await verifyToken(tokenInHeader, authenticateContext);
|
|
if (errors) {
|
|
return handleSessionTokenError(errors[0], "header");
|
|
}
|
|
return signedIn({
|
|
tokenType: TokenType.SessionToken,
|
|
authenticateContext,
|
|
sessionClaims: data,
|
|
token: tokenInHeader
|
|
});
|
|
}
|
|
if (Array.isArray(acceptsToken)) {
|
|
if (!isTokenTypeInAcceptedArray(acceptsToken, authenticateContext)) {
|
|
return signedOutInvalidToken();
|
|
}
|
|
}
|
|
if (authenticateContext.tokenInHeader) {
|
|
if (acceptsToken === "any" || Array.isArray(acceptsToken)) {
|
|
return authenticateAnyRequestWithTokenInHeader();
|
|
}
|
|
if (acceptsToken === TokenType.SessionToken) {
|
|
return authenticateRequestWithTokenInHeader();
|
|
}
|
|
return authenticateMachineRequestWithTokenInHeader();
|
|
}
|
|
if (acceptsToken === TokenType.OAuthToken || acceptsToken === TokenType.ApiKey || acceptsToken === TokenType.M2MToken) {
|
|
return signedOut({
|
|
tokenType: acceptsToken,
|
|
authenticateContext,
|
|
reason: "No token in header"
|
|
});
|
|
}
|
|
return authenticateRequestWithTokenInCookie();
|
|
});
|
|
var debugRequestState = (params) => {
|
|
const { isSignedIn, isAuthenticated, proxyUrl, reason, message, publishableKey, isSatellite, domain } = params;
|
|
return { isSignedIn, isAuthenticated, proxyUrl, reason, message, publishableKey, isSatellite, domain };
|
|
};
|
|
var convertTokenVerificationErrorReasonToAuthErrorReason = ({
|
|
tokenError,
|
|
refreshError
|
|
}) => {
|
|
switch (tokenError) {
|
|
case TokenVerificationErrorReason.TokenExpired:
|
|
return `${AuthErrorReason.SessionTokenExpired}-refresh-${refreshError}`;
|
|
case TokenVerificationErrorReason.TokenNotActiveYet:
|
|
return AuthErrorReason.SessionTokenNBF;
|
|
case TokenVerificationErrorReason.TokenIatInTheFuture:
|
|
return AuthErrorReason.SessionTokenIatInTheFuture;
|
|
default:
|
|
return AuthErrorReason.UnexpectedError;
|
|
}
|
|
};
|
|
|
|
// src/tokens/factory.ts
|
|
var defaultOptions = {
|
|
secretKey: "",
|
|
machineSecretKey: "",
|
|
jwtKey: "",
|
|
apiUrl: void 0,
|
|
apiVersion: void 0,
|
|
proxyUrl: "",
|
|
publishableKey: "",
|
|
isSatellite: false,
|
|
domain: "",
|
|
audience: ""
|
|
};
|
|
function createAuthenticateRequest(params) {
|
|
const buildTimeOptions = mergePreDefinedOptions(defaultOptions, params.options);
|
|
const apiClient = params.apiClient;
|
|
const authenticateRequest2 = (request, options = {}) => {
|
|
const { apiUrl, apiVersion } = buildTimeOptions;
|
|
const runTimeOptions = mergePreDefinedOptions(buildTimeOptions, options);
|
|
return authenticateRequest(request, {
|
|
...options,
|
|
...runTimeOptions,
|
|
// We should add all the omitted props from options here (eg apiUrl / apiVersion)
|
|
// to avoid runtime options override them.
|
|
apiUrl,
|
|
apiVersion,
|
|
apiClient
|
|
});
|
|
};
|
|
return {
|
|
authenticateRequest: authenticateRequest2,
|
|
debugRequestState
|
|
};
|
|
}
|
|
|
|
// src/util/decorateObjectWithResources.ts
|
|
var decorateObjectWithResources = async (obj, authObj, opts) => {
|
|
const { loadSession, loadUser, loadOrganization } = opts || {};
|
|
const { userId, sessionId, orgId } = authObj;
|
|
const { sessions, users, organizations } = createBackendApiClient({ ...opts });
|
|
const [sessionResp, userResp, organizationResp] = await Promise.all([
|
|
loadSession && sessionId ? sessions.getSession(sessionId) : Promise.resolve(void 0),
|
|
loadUser && userId ? users.getUser(userId) : Promise.resolve(void 0),
|
|
loadOrganization && orgId ? organizations.getOrganization({ organizationId: orgId }) : Promise.resolve(void 0)
|
|
]);
|
|
const resources = stripPrivateDataFromObject({
|
|
session: sessionResp,
|
|
user: userResp,
|
|
organization: organizationResp
|
|
});
|
|
return Object.assign(obj, resources);
|
|
};
|
|
function stripPrivateDataFromObject(authObject) {
|
|
const user = authObject.user ? { ...authObject.user } : authObject.user;
|
|
const organization = authObject.organization ? { ...authObject.organization } : authObject.organization;
|
|
prunePrivateMetadata(user);
|
|
prunePrivateMetadata(organization);
|
|
return { ...authObject, user, organization };
|
|
}
|
|
function prunePrivateMetadata(resource) {
|
|
if (resource) {
|
|
if ("privateMetadata" in resource) {
|
|
delete resource["privateMetadata"];
|
|
}
|
|
if ("private_metadata" in resource) {
|
|
delete resource["private_metadata"];
|
|
}
|
|
}
|
|
return resource;
|
|
}
|
|
|
|
// src/internal.ts
|
|
var import_authorization_errors = require("@clerk/shared/authorization-errors");
|
|
// Annotate the CommonJS export names for ESM import in node:
|
|
0 && (module.exports = {
|
|
AuthStatus,
|
|
TokenType,
|
|
authenticatedMachineObject,
|
|
constants,
|
|
createAuthenticateRequest,
|
|
createBootstrapSignedOutState,
|
|
createClerkRequest,
|
|
createRedirect,
|
|
debugRequestState,
|
|
decorateObjectWithResources,
|
|
getAuthObjectForAcceptedToken,
|
|
getAuthObjectFromJwt,
|
|
invalidTokenAuthObject,
|
|
isMachineToken,
|
|
isMachineTokenByPrefix,
|
|
isTokenTypeAccepted,
|
|
makeAuthObjectSerializable,
|
|
reverificationError,
|
|
reverificationErrorResponse,
|
|
signedInAuthObject,
|
|
signedOutAuthObject,
|
|
stripPrivateDataFromObject,
|
|
unauthenticatedMachineObject,
|
|
verifyMachineAuthToken
|
|
});
|
|
//# sourceMappingURL=internal.js.map
|