@asgardeo/react
Version:
React implementation of Asgardeo JavaScript SDK.
1,500 lines (1,466 loc) • 577 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
// src/contexts/Asgardeo/AsgardeoProvider.tsx
import {
AsgardeoRuntimeError as AsgardeoRuntimeError3,
generateFlattenedUserProfile as generateFlattenedUserProfile2,
getBrandingPreference,
getActiveTheme,
Platform as Platform3,
extractUserClaimsFromIdToken as extractUserClaimsFromIdToken2
} from "@asgardeo/browser";
import { useEffect as useEffect6, useMemo as useMemo7, useRef as useRef2, useState as useState8, useCallback as useCallback8 } from "react";
// src/contexts/Asgardeo/AsgardeoContext.ts
import { createContext } from "react";
var AsgardeoContext = createContext({
afterSignInUrl: void 0,
applicationId: void 0,
baseUrl: void 0,
clearSession: () => {
},
exchangeToken: null,
getAccessToken: null,
getDecodedIdToken: null,
getIdToken: null,
http: {
request: () => null,
requestAll: () => null
},
instanceId: 0,
isInitialized: false,
isLoading: true,
isSignedIn: false,
meta: null,
organization: null,
organizationHandle: void 0,
platform: void 0,
reInitialize: null,
signIn: () => Promise.resolve({}),
signInOptions: {},
signInSilently: () => Promise.resolve({}),
signInUrl: void 0,
signOut: () => Promise.resolve({}),
signUp: () => Promise.resolve({}),
signUpUrl: void 0,
storage: "sessionStorage",
switchOrganization: null,
user: null
});
AsgardeoContext.displayName = "AsgardeoContext";
var AsgardeoContext_default = AsgardeoContext;
// src/AsgardeoReactClient.ts
import {
AsgardeoBrowserClient,
flattenUserSchema,
generateFlattenedUserProfile,
generateUserProfile,
AsgardeoRuntimeError,
executeEmbeddedSignUpFlow,
executeEmbeddedSignInFlow,
executeEmbeddedSignInFlowV2,
deriveOrganizationHandleFromBaseUrl,
extractUserClaimsFromIdToken,
navigate,
getRedirectBasedSignUpUrl,
Platform,
isEmpty,
executeEmbeddedSignUpFlowV2,
EmbeddedSignInFlowStatusV2
} from "@asgardeo/browser";
// src/__temp__/api.ts
import {
AsgardeoSPAClient,
Hooks
} from "@asgardeo/browser";
var _AuthAPI = class _AuthAPI {
constructor(spaClient, instanceId = 0) {
__publicField(this, "authState", _AuthAPI.DEFAULT_STATE);
__publicField(this, "client");
__publicField(this, "apiInstanceId");
__publicField(this, "loadingState");
this.apiInstanceId = instanceId;
this.client = spaClient ?? AsgardeoSPAClient.getInstance(instanceId);
this.getState = this.getState.bind(this);
this.init = this.init.bind(this);
this.signIn = this.signIn.bind(this);
this.signOut = this.signOut.bind(this);
this.updateState = this.updateState.bind(this);
}
/**
* Get the instance ID for this AuthAPI instance.
* @returns The instance ID used for multi-auth context support.
*/
getInstanceId() {
return this.apiInstanceId;
}
setLoadingState(isLoading) {
this.loadingState = isLoading;
}
getLoadingState() {
return this.loadingState;
}
isLoading() {
return this.getLoadingState();
}
/**
* Method to return Auth Client instance authentication state.
*
* @return {AuthStateInterface} Authentication State.
*/
getState() {
return this.authState;
}
/**
* Method to initialize the AuthClient instance.
*
* @param {Config} config - `dispatch` function from React Auth Context.
*/
async init(config) {
return this.client.initialize(config);
}
/**
* Method to get the configuration data.
*
* @returns {Promise<AuthClientConfig<Config>>} - A promise that resolves with the configuration data.
*/
async getConfigData() {
return this.client.getConfigData();
}
async getStorageManager() {
return this.client.getStorageManager();
}
/**
* Method to get the configuration data.
*
* @returns {Promise<AuthClientConfig<Config>>} - A promise that resolves with the configuration data.
*/
async isInitialized() {
return this.client.isInitialized();
}
/**
* Method to handle user Sign In requests.
*
* @param {any} dispatch - `dispatch` function from React Auth Context.
* @param {AuthStateInterface} state - Current authentication state in React Auth Context.
* @param {any} callback - Action to trigger on successful sign in.
*/
async signIn(config, authorizationCode, sessionState, authState, callback, tokenRequestConfig) {
return this.client.signIn(config, authorizationCode, sessionState, authState, tokenRequestConfig).then(async (response) => {
if (!response) {
return null;
}
if (await this.client.isSignedIn()) {
const stateToUpdate = {
displayName: response.displayName,
email: response.email,
isLoading: false,
isSignedIn: true,
username: response.username
};
this.updateState(stateToUpdate);
this.setLoadingState(false);
if (callback) {
callback(response);
}
}
return response;
}).catch((error) => Promise.reject(error));
}
/**
* Method to handle user Sign Out requests.
*
* @param {any} dispatch - `dispatch` function from React Auth Context.
* @param {AuthStateInterface} state - Current authentication state in React Auth Context.
* @param {any} callback - Action to trigger on successful sign out.
*/
signOut(callback) {
return this.client.signOut().then((response) => {
if (callback) {
callback(response);
}
return response;
}).catch((error) => Promise.reject(error));
}
/**
* Method to update Auth Client instance authentication state.
*
* @param {AuthStateInterface} state - State values to update in authentication state.
*/
updateState(state) {
this.authState = { ...this.authState, ...state };
}
/**
* This method returns a Promise that resolves with the basic user information obtained from the ID token.
*
* @return {Promise<User>} - A promise that resolves with the user information.
*/
async getUser() {
return this.client.getUser();
}
/**
* This method sends an API request to a protected endpoint.
* The access token is automatically attached to the header of the request.
* This is the only way by which protected endpoints can be accessed
* when the web worker is used to store session information.
*
* @param {HttpRequestConfig} config - The config object containing attributes necessary to send a request.
*
* @return {Promise<Response>} - Returns a Promise that resolves with the response to the request.
*/
async httpRequest(config) {
return this.client.httpRequest(config);
}
/**
* This method sends multiple API requests to a protected endpoint.
* The access token is automatically attached to the header of the request.
* This is the only way by which multiple requests can be sent to protected endpoints
* when the web worker is used to store session information.
*
* @param {HttpRequestConfig[]} config - The config object containing attributes necessary to send a request.
*
* @return {Promise<Response>} - Returns a Promise that resolves with the responses to the requests.
*/
async httpRequestAll(configs) {
return this.client.httpRequestAll(configs);
}
/**
* This method allows you to send a request with a custom grant.
*
* @param {CustomGrantRequestParams} config - The request parameters.
*
* @return {Promise<Response | SignInResponse>} - A Promise that resolves with
* the value returned by the custom grant request.
*/
exchangeToken(config, callback) {
return this.client.exchangeToken(config).then((response) => {
if (!response) {
return null;
}
if (config.returnsSession) {
this.updateState({
...this.getState(),
...response,
isLoading: false,
isSignedIn: true
});
}
if (callback) {
callback(response);
}
return response;
}).catch((error) => Promise.reject(error));
}
/**
* This method ends a user session. The access token is revoked and the session information is destroyed.
*
* @return {Promise<boolean>} - A promise that resolves with `true` if the process is successful.
*/
async revokeAccessToken(dispatch) {
return this.client.revokeAccessToken().then(() => {
this.updateState({ ..._AuthAPI.DEFAULT_STATE, isLoading: false });
dispatch(_AuthAPI.DEFAULT_STATE);
return true;
}).catch((error) => Promise.reject(error));
}
/**
* This method returns a Promise that resolves with an object containing the service endpoints.
*
* @return {Promise<ServiceResourcesType} - A Promise that resolves with an object containing the service endpoints.
*/
async getOpenIDProviderEndpoints() {
return this.client.getOpenIDProviderEndpoints();
}
/**
* This methods returns the Axios http client.
*
* @return {HttpClientInstance} - The Axios HTTP client.
*/
async getHttpClient() {
return this.client.getHttpClient();
}
/**
* This method decodes a JWT token payload and returns it.
*
* @param token - The token to decode.
* @returns The decoded token payload.
*/
async decodeJwtToken(token) {
return this.client.decodeJwtToken(token);
}
/**
* This method decodes the payload of the id token and returns it.
*
* @return {Promise<DecodedIDTokenPayloadInterface>} - A Promise that resolves with
* the decoded payload of the id token.
*/
async getDecodedIdToken(sessionId) {
return this.client.getDecodedIdToken(sessionId);
}
/**
* This method decodes the payload of the idp id token and returns it.
*
* @return {Promise<DecodedIDTokenPayloadInterface>} - A Promise that resolves with
* the decoded payload of the idp id token.
*/
async getDecodedIDPIDToken() {
return this.client.getDecodedIdToken();
}
/**
* This method returns the ID token.
*
* @return {Promise<string>} - A Promise that resolves with the id token.
*/
async getIdToken() {
return this.client.getIdToken();
}
/**
* This method return a Promise that resolves with the access token.
*
* **This method will not return the access token if the storage type is set to `webWorker`.**
*
* @return {Promise<string>} - A Promise that resolves with the access token.
*/
async getAccessToken(sessionId) {
return this.client.getAccessToken(sessionId);
}
/**
* This method return a Promise that resolves with the idp access token.
*
* **This method will not return the idp access token if the storage type is set to `webWorker`.**
* **This can be used to access the IDP access token when custom auth grant functionalities are used**
*
* @return {Promise<string>} - A Promise that resolves with the idp access token.
*/
async getIDPAccessToken() {
return this.client.getIDPAccessToken();
}
/**
* This method refreshes the access token.
*
* @return {TokenResponseInterface} - A Promise that resolves with an object containing
* information about the refreshed access token.
*/
async refreshAccessToken() {
return this.client.refreshAccessToken();
}
/**
* This method specifies if the user is authenticated or not.
*
* @return {Promise<boolean>} - A Promise that resolves with `true` if teh user is authenticated.
*/
async isSignedIn() {
return this.client.isSignedIn();
}
/**
* This method specifies if the session is active or not.
*
* @return {Promise<boolean>} - A Promise that resolves with `true` if there is an active session.
*/
async isSessionActive() {
return this.client.isSessionActive();
}
/**
* This method enables callback functions attached to the http client.
*
* @return {Promise<boolean>} - A promise that resolves with True.
*
*/
async enableHttpHandler() {
return this.client.enableHttpHandler();
}
/**
* This method disables callback functions attached to the http client.
*
* @return {Promise<boolean>} - A promise that resolves with True.
*/
async disableHttpHandler() {
return this.client.disableHttpHandler();
}
/**
* This method updates the configuration that was passed into the constructor when instantiating this class.
*
* @param {Partial<AuthClientConfig<T>>} config - A config object to update the SDK configurations with.
*/
async reInitialize(config) {
return this.client.reInitialize(config);
}
on(hook, callback, id) {
if (hook === Hooks.CustomGrant) {
return this.client.on(hook, callback, id);
}
return this.client.on(hook, callback);
}
/**
* This method allows you to sign in silently.
* First, this method sends a prompt none request to see if there is an active user session in the identity server.
* If there is one, then it requests the access token and stores it. Else, it returns false.
*
* @return {Promise<User | boolean>} - A Promise that resolves with the user information after signing in
* or with `false` if the user is not signed in.
*
* @example
*```
* client.signInSilently()
*```
*/
async signInSilently(additionalParams, tokenRequestConfig) {
return this.client.signInSilently(additionalParams, tokenRequestConfig).then(async (response) => {
if (!response) {
return false;
}
return response;
}).catch((error) => Promise.reject(error));
}
/**
* This method clears the session for the specified session ID.
*
* @param sessionId - Optional session ID to clear the session for.
*
* @return void
*/
clearSession(sessionId) {
this.client.clearSession(sessionId);
}
};
__publicField(_AuthAPI, "DEFAULT_STATE");
var AuthAPI = _AuthAPI;
AuthAPI.DEFAULT_STATE = {
displayName: "",
email: "",
isLoading: true,
isSignedIn: false,
username: ""
};
var api_default = AuthAPI;
// src/api/getAllOrganizations.ts
import {
AsgardeoSPAClient as AsgardeoSPAClient2,
getAllOrganizations as baseGetAllOrganizations
} from "@asgardeo/browser";
var getAllOrganizations = async ({
fetcher,
instanceId = 0,
...requestConfig
}) => {
const defaultFetcher = async (url, config) => {
const client = AsgardeoSPAClient2.getInstance(instanceId);
const httpClient = client.httpRequest.bind(client);
const response = await httpClient({
headers: config.headers,
method: config.method || "GET",
url
});
return {
json: () => Promise.resolve(response.data),
ok: response.status >= 200 && response.status < 300,
status: response.status,
statusText: response.statusText || "",
text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data))
};
};
return baseGetAllOrganizations({
...requestConfig,
fetcher: fetcher || defaultFetcher
});
};
var getAllOrganizations_default = getAllOrganizations;
// src/api/getMeOrganizations.ts
import {
AsgardeoSPAClient as AsgardeoSPAClient3,
getMeOrganizations as baseGetMeOrganizations
} from "@asgardeo/browser";
var getMeOrganizations = async ({
fetcher,
instanceId = 0,
...requestConfig
}) => {
const defaultFetcher = async (url, config) => {
const client = AsgardeoSPAClient3.getInstance(instanceId);
const httpClient = client.httpRequest.bind(client);
const response = await httpClient({
headers: config.headers,
method: config.method || "GET",
url
});
return {
json: () => Promise.resolve(response.data),
ok: response.status >= 200 && response.status < 300,
status: response.status,
statusText: response.statusText || "",
text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data))
};
};
return baseGetMeOrganizations({
...requestConfig,
fetcher: fetcher || defaultFetcher
});
};
var getMeOrganizations_default = getMeOrganizations;
// src/api/getSchemas.ts
import {
AsgardeoSPAClient as AsgardeoSPAClient4,
getSchemas as baseGetSchemas
} from "@asgardeo/browser";
var getSchemas = async ({ fetcher, instanceId = 0, ...requestConfig }) => {
const defaultFetcher = async (url, config) => {
const client = AsgardeoSPAClient4.getInstance(instanceId);
const httpClient = client.httpRequest.bind(client);
const response = await httpClient({
headers: config.headers,
method: config.method || "GET",
url
});
return {
json: () => Promise.resolve(response.data),
ok: response.status >= 200 && response.status < 300,
status: response.status,
statusText: response.statusText || "",
text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data))
};
};
return baseGetSchemas({
...requestConfig,
fetcher: fetcher || defaultFetcher
});
};
var getSchemas_default = getSchemas;
// src/api/getScim2Me.ts
import {
AsgardeoSPAClient as AsgardeoSPAClient5,
getScim2Me as baseGetScim2Me
} from "@asgardeo/browser";
var getScim2Me = async ({ fetcher, instanceId = 0, ...requestConfig }) => {
const defaultFetcher = async (url, config) => {
const client = AsgardeoSPAClient5.getInstance(instanceId);
const httpClient = client.httpRequest.bind(client);
const response = await httpClient({
headers: config.headers,
method: config.method || "GET",
url
});
return {
json: () => Promise.resolve(response.data),
ok: response.status >= 200 && response.status < 300,
status: response.status,
statusText: response.statusText || "",
text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data))
};
};
return baseGetScim2Me({
...requestConfig,
fetcher: fetcher || defaultFetcher
});
};
var getScim2Me_default = getScim2Me;
// src/AsgardeoReactClient.ts
var AsgardeoReactClient = class extends AsgardeoBrowserClient {
/**
* Creates a new AsgardeoReactClient instance.
* @param instanceId - Optional instance ID for multi-auth context support. Defaults to 0 for backward compatibility.
*/
constructor(instanceId = 0) {
super();
__publicField(this, "asgardeo");
__publicField(this, "loadingState", false);
__publicField(this, "clientInstanceId");
this.clientInstanceId = instanceId;
this.asgardeo = new api_default(void 0, instanceId);
}
/**
* Get the instance ID for this client.
* @returns The instance ID used for multi-auth context support.
*/
getInstanceId() {
return this.clientInstanceId;
}
/**
* Set the loading state of the client
* @param loading - Boolean indicating if the client is in a loading state
*/
setLoading(loading) {
this.loadingState = loading;
}
/**
* Wrap async operations with loading state management
* @param operation - The async operation to execute
* @returns Promise with the result of the operation
*/
async withLoading(operation) {
this.setLoading(true);
try {
const result = await operation();
return result;
} finally {
this.setLoading(false);
}
}
initialize(config) {
let resolvedOrganizationHandle = config?.organizationHandle;
if (!resolvedOrganizationHandle) {
resolvedOrganizationHandle = deriveOrganizationHandleFromBaseUrl(config?.baseUrl);
}
return this.withLoading(
async () => this.asgardeo.init({ ...config, organizationHandle: resolvedOrganizationHandle })
);
}
reInitialize(config) {
return this.withLoading(async () => {
let isInitialized;
try {
await this.asgardeo.reInitialize(config);
isInitialized = true;
} catch (error) {
throw new AsgardeoRuntimeError(
`Failed to check if the client is initialized: ${error instanceof Error ? error.message : String(error)}`,
"AsgardeoReactClient-reInitialize-RuntimeError-001",
"react",
"An error occurred while checking the initialization status of the client."
);
}
return isInitialized;
});
}
// eslint-disable-next-line class-methods-use-this
async updateUserProfile() {
throw new Error("Not implemented");
}
async getUser(options) {
try {
let baseUrl = options?.baseUrl;
if (!baseUrl) {
const configData = await this.asgardeo.getConfigData();
baseUrl = configData?.baseUrl;
}
const profile = await getScim2Me_default({ baseUrl });
const schemas = await getSchemas_default({ baseUrl });
return generateUserProfile(profile, flattenUserSchema(schemas));
} catch (error) {
return extractUserClaimsFromIdToken(await this.getDecodedIdToken());
}
}
async getDecodedIdToken(sessionId) {
return this.asgardeo.getDecodedIdToken(sessionId);
}
async getIdToken() {
return this.withLoading(async () => this.asgardeo.getIdToken());
}
async getUserProfile(options) {
return this.withLoading(async () => {
try {
let baseUrl = options?.baseUrl;
if (!baseUrl) {
const configData = await this.asgardeo.getConfigData();
baseUrl = configData?.baseUrl;
}
const profile = await getScim2Me_default({ baseUrl, instanceId: this.getInstanceId() });
const schemas = await getSchemas_default({ baseUrl, instanceId: this.getInstanceId() });
const processedSchemas = flattenUserSchema(schemas);
const output = {
flattenedProfile: generateFlattenedUserProfile(profile, processedSchemas),
profile,
schemas: processedSchemas
};
return output;
} catch (error) {
return {
flattenedProfile: extractUserClaimsFromIdToken(await this.getDecodedIdToken()),
profile: extractUserClaimsFromIdToken(await this.getDecodedIdToken()),
schemas: []
};
}
});
}
async getMyOrganizations(options) {
try {
let baseUrl = options?.baseUrl;
if (!baseUrl) {
const configData = await this.asgardeo.getConfigData();
baseUrl = configData?.baseUrl;
}
return await getMeOrganizations_default({ baseUrl, instanceId: this.getInstanceId() });
} catch (error) {
throw new AsgardeoRuntimeError(
`Failed to fetch the user's associated organizations: ${error instanceof Error ? error.message : String(error)}`,
"AsgardeoReactClient-getMyOrganizations-RuntimeError-001",
"react",
"An error occurred while fetching associated organizations of the signed-in user."
);
}
}
async getAllOrganizations(options) {
try {
let baseUrl = options?.baseUrl;
if (!baseUrl) {
const configData = await this.asgardeo.getConfigData();
baseUrl = configData?.baseUrl;
}
return await getAllOrganizations_default({ baseUrl, instanceId: this.getInstanceId() });
} catch (error) {
throw new AsgardeoRuntimeError(
`Failed to fetch all organizations: ${error instanceof Error ? error.message : String(error)}`,
"AsgardeoReactClient-getAllOrganizations-RuntimeError-001",
"react",
"An error occurred while fetching all the organizations associated with the user."
);
}
}
async getCurrentOrganization() {
try {
return await this.withLoading(async () => {
const idToken = await this.getDecodedIdToken();
return {
id: idToken?.org_id,
name: idToken?.org_name,
orgHandle: idToken?.org_handle
};
});
} catch (error) {
throw new AsgardeoRuntimeError(
`Failed to fetch the current organization: ${error instanceof Error ? error.message : String(error)}`,
"AsgardeoReactClient-getCurrentOrganization-RuntimeError-001",
"react",
"An error occurred while fetching the current organization of the signed-in user."
);
}
}
async switchOrganization(organization) {
return this.withLoading(async () => {
try {
if (!organization.id) {
throw new AsgardeoRuntimeError(
"Organization ID is required for switching organizations",
"react-AsgardeoReactClient-SwitchOrganizationError-001",
"react",
"The organization object must contain a valid ID to perform the organization switch."
);
}
const exchangeConfig = {
attachToken: false,
data: {
client_id: "{{clientId}}",
grant_type: "organization_switch",
scope: "{{scopes}}",
switching_organization: organization.id,
token: "{{accessToken}}"
},
id: "organization-switch",
returnsSession: true,
signInRequired: true
};
return await this.asgardeo.exchangeToken(exchangeConfig, () => {
});
} catch (error) {
throw new AsgardeoRuntimeError(
`Failed to switch organization: ${error.message || error}`,
"react-AsgardeoReactClient-SwitchOrganizationError-003",
"react",
"An error occurred while switching to the specified organization. Please try again."
);
}
});
}
isLoading() {
return this.loadingState || this.asgardeo.isLoading();
}
async isInitialized() {
return this.asgardeo.isInitialized();
}
async isSignedIn() {
return this.asgardeo.isSignedIn();
}
getConfiguration() {
return this.asgardeo.getConfigData();
}
async exchangeToken(config) {
return this.withLoading(
async () => this.asgardeo.exchangeToken(config, () => {
})
);
}
async signIn(...args) {
return this.withLoading(async () => {
const arg1 = args[0];
const arg2 = args[1];
const config = await this.asgardeo.getConfigData();
const platformFromStorage = sessionStorage.getItem("asgardeo_platform");
const isV2Platform = config && config.platform === Platform.AsgardeoV2 || platformFromStorage === "AsgardeoV2";
if (isV2Platform && typeof arg1 === "object" && arg1 !== null && arg1.callOnlyOnRedirect === true) {
return void 0;
}
if (isV2Platform && typeof arg1 === "object" && arg1 !== null && !isEmpty(arg1) && ("flowId" in arg1 || "applicationId" in arg1)) {
const authIdFromUrl = new URL(window.location.href).searchParams.get("authId");
const authIdFromStorage = sessionStorage.getItem("asgardeo_auth_id");
const authId = authIdFromUrl || authIdFromStorage;
const baseUrlFromStorage = sessionStorage.getItem("asgardeo_base_url");
const baseUrl = config?.baseUrl || baseUrlFromStorage;
const response = await executeEmbeddedSignInFlowV2({
authId,
baseUrl,
payload: arg1,
url: arg2?.url
});
if (isV2Platform && response && typeof response === "object" && response["flowStatus"] === EmbeddedSignInFlowStatusV2.Complete && response["assertion"]) {
const decodedAssertion = await this.decodeJwtToken(response["assertion"]);
const createdAt = decodedAssertion.iat ? decodedAssertion.iat * 1e3 : Date.now();
const expiresIn = decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600;
await this.setSession({
access_token: response["assertion"],
created_at: createdAt,
expires_in: expiresIn,
id_token: response["assertion"],
scope: decodedAssertion.scope,
token_type: "Bearer"
});
}
return response;
}
if (typeof arg1 === "object" && "flowId" in arg1 && typeof arg2 === "object" && "url" in arg2) {
return executeEmbeddedSignInFlow({
payload: arg1,
url: arg2.url
});
}
return await this.asgardeo.signIn(arg1);
});
}
async signInSilently(options) {
return this.asgardeo.signInSilently(options);
}
async signOut(...args) {
if (args[1] && typeof args[1] !== "function") {
throw new Error("The second argument must be a function.");
}
const config = await this.asgardeo.getConfigData();
if (config.platform === Platform.AsgardeoV2) {
this.asgardeo.clearSession();
args[1]?.(config.afterSignOutUrl || "");
return Promise.resolve(config.afterSignOutUrl || "");
}
const response = await this.asgardeo.signOut(args[1]);
return Promise.resolve(String(response));
}
async signUp(...args) {
const config = await this.asgardeo.getConfigData();
const firstArg = args[0];
const baseUrl = config?.baseUrl;
if (config.platform === Platform.AsgardeoV2) {
const authIdFromUrl = new URL(window.location.href).searchParams.get("authId");
const authIdFromStorage = sessionStorage.getItem("asgardeo_auth_id");
const authId = authIdFromUrl || authIdFromStorage;
if (authIdFromUrl && !authIdFromStorage) {
sessionStorage.setItem("asgardeo_auth_id", authIdFromUrl);
}
return executeEmbeddedSignUpFlowV2({
authId,
baseUrl,
payload: typeof firstArg === "object" && "flowType" in firstArg ? { ...firstArg, verbose: true } : firstArg
});
}
if (typeof firstArg === "object" && "flowType" in firstArg) {
return executeEmbeddedSignUpFlow({
baseUrl,
payload: firstArg
});
}
navigate(getRedirectBasedSignUpUrl(config));
return void 0;
}
async request(requestConfig) {
return this.asgardeo.httpRequest(requestConfig);
}
async requestAll(requestConfigs) {
return this.asgardeo.httpRequestAll(requestConfigs);
}
async getAccessToken(sessionId) {
return this.asgardeo.getAccessToken(sessionId);
}
clearSession(sessionId) {
this.asgardeo.clearSession(sessionId);
}
async setSession(sessionData, sessionId) {
return (await this.asgardeo.getStorageManager()).setSessionData(sessionData, sessionId);
}
decodeJwtToken(token) {
return this.asgardeo.decodeJwtToken(token);
}
};
var AsgardeoReactClient_default = AsgardeoReactClient;
// src/hooks/useBrowserUrl.ts
import { hasAuthParamsInUrl, hasCalledForThisInstanceInUrl } from "@asgardeo/browser";
var useBrowserUrl = () => {
const hasAuthParams = (url, afterSignInUrl) => hasAuthParamsInUrl() && new URL(url.origin + url.pathname).toString() === new URL(afterSignInUrl).toString() || // authParams?.authorizationCode || // FIXME: These are sent externally. Need to see what we can do about this.
url.searchParams.get("error") !== null;
const hasCalledForThisInstance = (url, instanceId) => hasCalledForThisInstanceInUrl(instanceId, url.search);
return { hasAuthParams, hasCalledForThisInstance };
};
var useBrowserUrl_default = useBrowserUrl;
// src/contexts/Branding/BrandingProvider.tsx
import { transformBrandingPreferenceToTheme } from "@asgardeo/browser";
import { useCallback, useEffect, useState } from "react";
// src/contexts/Branding/BrandingContext.ts
import { createContext as createContext2 } from "react";
var BrandingContext = createContext2(null);
BrandingContext.displayName = "BrandingContext";
var BrandingContext_default = BrandingContext;
// src/contexts/Branding/BrandingProvider.tsx
import { jsx } from "react/jsx-runtime";
var BrandingProvider = ({
children,
brandingPreference: externalBrandingPreference,
forceTheme,
enabled = true,
isLoading: externalIsLoading = false,
error: externalError = null,
refetch: externalRefetch
}) => {
const [theme, setTheme] = useState(null);
const [activeTheme, setActiveTheme] = useState(null);
useEffect(() => {
if (!enabled || !externalBrandingPreference) {
setTheme(null);
setActiveTheme(null);
return;
}
const activeThemeFromBranding = externalBrandingPreference?.preference?.theme?.activeTheme;
let extractedActiveTheme = null;
if (activeThemeFromBranding) {
const themeMode = activeThemeFromBranding.toLowerCase();
if (themeMode === "light" || themeMode === "dark") {
extractedActiveTheme = themeMode;
}
}
setActiveTheme(extractedActiveTheme);
const transformedTheme = transformBrandingPreferenceToTheme(externalBrandingPreference, forceTheme);
setTheme(transformedTheme);
}, [externalBrandingPreference, forceTheme, enabled]);
useEffect(() => {
if (!enabled) {
setTheme(null);
setActiveTheme(null);
}
}, [enabled]);
const fetchBranding = useCallback(async () => {
if (externalRefetch) {
await externalRefetch();
}
}, [externalRefetch]);
const value = {
activeTheme,
brandingPreference: externalBrandingPreference || null,
error: externalError,
fetchBranding,
isLoading: externalIsLoading,
refetch: externalRefetch || fetchBranding,
theme
};
return /* @__PURE__ */ jsx(BrandingContext_default.Provider, { value, children });
};
var BrandingProvider_default = BrandingProvider;
// src/contexts/Flow/FlowProvider.tsx
import { useCallback as useCallback2, useMemo, useState as useState2 } from "react";
// src/contexts/Flow/FlowContext.ts
import { createContext as createContext3 } from "react";
var FlowContext = createContext3(void 0);
FlowContext.displayName = "FlowContext";
var FlowContext_default = FlowContext;
// src/contexts/Flow/FlowProvider.tsx
import { jsx as jsx2 } from "react/jsx-runtime";
var FlowProvider = ({
children,
initialStep = null,
initialTitle = "",
initialSubtitle,
onFlowChange
}) => {
const [currentStep, setCurrentStepState] = useState2(initialStep);
const [title, setTitle] = useState2(initialTitle);
const [subtitle, setSubtitle] = useState2(initialSubtitle);
const [messages, setMessages] = useState2([]);
const [error, setError] = useState2(null);
const [isLoading, setIsLoading] = useState2(false);
const [showBackButton, setShowBackButton] = useState2(false);
const [onGoBack, setOnGoBack] = useState2(void 0);
const setCurrentStep = useCallback2(
(step) => {
setCurrentStepState(step);
if (step) {
setTitle(step.title);
setSubtitle(step.subtitle);
setShowBackButton(step.canGoBack ?? false);
}
onFlowChange?.(step);
},
[onFlowChange]
);
const addMessage = useCallback2((message) => {
const messageWithId = {
...message,
id: message.id ?? `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
};
setMessages((prev) => [...prev, messageWithId]);
}, []);
const removeMessage = useCallback2((messageId) => {
setMessages((prev) => prev.filter((msg) => msg.id !== messageId));
}, []);
const clearMessages = useCallback2(() => {
setMessages([]);
}, []);
const reset = useCallback2(() => {
setCurrentStepState(initialStep);
setTitle(initialTitle);
setSubtitle(initialSubtitle);
setMessages([]);
setError(null);
setIsLoading(false);
setShowBackButton(false);
setOnGoBack(void 0);
}, [initialStep, initialTitle, initialSubtitle]);
const navigateToFlow = useCallback2(
(flowType, options) => {
const stepId = `${flowType}-${Date.now()}`;
const step = {
canGoBack: flowType !== "signin",
// Usually allow going back except for main signin
id: stepId,
metadata: options?.metadata,
subtitle: options?.subtitle,
title: options?.title,
type: flowType
};
setCurrentStep(step);
clearMessages();
setError(null);
},
[setCurrentStep, clearMessages]
);
const contextValue = useMemo(
() => ({
addMessage,
clearMessages,
currentStep,
error,
isLoading,
messages,
navigateToFlow,
onGoBack,
removeMessage,
reset,
setCurrentStep,
setError,
setIsLoading,
setOnGoBack,
setShowBackButton,
setSubtitle,
setTitle,
showBackButton,
subtitle,
title
}),
[
currentStep,
setCurrentStep,
title,
subtitle,
messages,
addMessage,
removeMessage,
clearMessages,
error,
isLoading,
showBackButton,
onGoBack,
reset,
navigateToFlow
]
);
return /* @__PURE__ */ jsx2(FlowContext_default.Provider, { value: contextValue, children });
};
var FlowProvider_default = FlowProvider;
// src/contexts/FlowMeta/FlowMetaProvider.tsx
import { FlowMetaType, getFlowMetaV2 } from "@asgardeo/browser";
import { useCallback as useCallback3, useEffect as useEffect2, useRef, useState as useState3 } from "react";
// src/contexts/FlowMeta/FlowMetaContext.ts
import { createContext as createContext4 } from "react";
var FlowMetaContext = createContext4(null);
FlowMetaContext.displayName = "FlowMetaContext";
var FlowMetaContext_default = FlowMetaContext;
// src/contexts/Asgardeo/useAsgardeo.ts
import { useContext } from "react";
var useAsgardeo = () => {
const context = useContext(AsgardeoContext_default);
if (!context) {
throw new Error("useAsgardeo must be used within an AsgardeoProvider");
}
const flowMetaContext = useContext(FlowMetaContext_default);
return {
...context,
meta: flowMetaContext?.meta ?? null
};
};
var useAsgardeo_default = useAsgardeo;
// src/contexts/FlowMeta/FlowMetaProvider.tsx
import { jsx as jsx3 } from "react/jsx-runtime";
var FlowMetaProvider = ({
children,
enabled = true
}) => {
const { baseUrl, applicationId } = useAsgardeo_default();
const [meta, setMeta] = useState3(null);
const [isLoading, setIsLoading] = useState3(false);
const [error, setError] = useState3(null);
const hasFetchedRef = useRef(false);
const fetchFlowMeta = useCallback3(async () => {
if (!enabled) {
setMeta(null);
return;
}
setIsLoading(true);
setError(null);
try {
const result = await getFlowMetaV2({ baseUrl, id: applicationId, type: FlowMetaType.App });
setMeta(result);
} catch (err) {
setError(err instanceof Error ? err : new Error(String(err)));
} finally {
setIsLoading(false);
}
}, [enabled, baseUrl, applicationId]);
useEffect2(() => {
if (!hasFetchedRef.current) {
hasFetchedRef.current = true;
fetchFlowMeta();
return;
}
fetchFlowMeta();
}, [fetchFlowMeta]);
const value = {
error,
fetchFlowMeta,
isLoading,
meta
};
return /* @__PURE__ */ jsx3(FlowMetaContext_default.Provider, { value, children });
};
var FlowMetaProvider_default = FlowMetaProvider;
// src/contexts/I18n/I18nProvider.tsx
import { deepMerge, createPackageComponentLogger } from "@asgardeo/browser";
import { getDefaultI18nBundles } from "@asgardeo/i18n";
import { useCallback as useCallback4, useEffect as useEffect3, useMemo as useMemo2, useState as useState4 } from "react";
// src/contexts/I18n/I18nContext.ts
import { createContext as createContext5 } from "react";
var I18nContext = createContext5(null);
I18nContext.displayName = "I18nContext";
var I18nContext_default = I18nContext;
// src/contexts/I18n/I18nProvider.tsx
import { jsx as jsx4 } from "react/jsx-runtime";
var logger = createPackageComponentLogger(
"@asgardeo/react",
"I18nProvider"
);
var I18N_LANGUAGE_STORAGE_KEY = "asgardeo-i18n-language";
var detectBrowserLanguage = () => {
if (typeof window !== "undefined" && window.navigator) {
return window.navigator.language || "en-US";
}
return "en-US";
};
var getStoredLanguage = () => {
if (typeof window !== "undefined" && window.localStorage) {
try {
return window.localStorage.getItem(I18N_LANGUAGE_STORAGE_KEY);
} catch (error) {
return null;
}
}
return null;
};
var storeLanguage = (language) => {
if (typeof window !== "undefined" && window.localStorage) {
try {
window.localStorage.setItem(I18N_LANGUAGE_STORAGE_KEY, language);
} catch (error) {
logger.warn("Failed to store language preference:");
}
}
};
var I18nProvider = ({
children,
preferences
}) => {
const defaultBundles = getDefaultI18nBundles();
const determineInitialLanguage = () => {
const configLanguage = preferences?.language;
const storedLanguage = getStoredLanguage();
const browserLanguage = detectBrowserLanguage();
const fallbackLanguage2 = preferences?.fallbackLanguage || "en-US";
return configLanguage || storedLanguage || browserLanguage || fallbackLanguage2;
};
const [currentLanguage, setCurrentLanguage] = useState4(determineInitialLanguage);
const mergedBundles = useMemo2(() => {
const merged = {};
Object.entries(defaultBundles).forEach(([key, bundle]) => {
const languageKey = key.replace("_", "-");
merged[languageKey] = bundle;
});
if (preferences?.bundles) {
Object.entries(preferences.bundles).forEach(([key, userBundle]) => {
if (merged[key]) {
merged[key] = {
...merged[key],
metadata: userBundle.metadata ? { ...merged[key].metadata, ...userBundle.metadata } : merged[key].metadata,
translations: deepMerge(merged[key].translations, userBundle.translations)
};
} else {
merged[key] = userBundle;
}
});
}
return merged;
}, [defaultBundles, preferences?.bundles]);
const fallbackLanguage = preferences?.fallbackLanguage || "en-US";
useEffect3(() => {
storeLanguage(currentLanguage);
}, [currentLanguage]);
const t = useCallback4(
(key, params) => {
let translation;
const currentBundle = mergedBundles[currentLanguage];
if (currentBundle?.translations[key]) {
translation = currentBundle.translations[key];
}
if (!translation && currentLanguage !== fallbackLanguage) {
const fallbackBundle = mergedBundles[fallbackLanguage];
if (fallbackBundle?.translations[key]) {
translation = fallbackBundle.translations[key];
}
}
if (!translation) {
translation = key;
}
if (params && Object.keys(params).length > 0) {
return Object.entries(params).reduce(
(acc, [paramKey, paramValue]) => acc.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue)),
translation
);
}
return translation;
},
[mergedBundles, currentLanguage, fallbackLanguage]
);
const setLanguage = useCallback4(
(language) => {
if (mergedBundles[language]) {
setCurrentLanguage(language);
} else {
logger.warn(
`Language '${language}' is not available. Available languages: ${Object.keys(mergedBundles).join(", ")}`
);
}
},
[mergedBundles]
);
const contextValue = useMemo2(
() => ({
bundles: mergedBundles,
currentLanguage,
fallbackLanguage,
setLanguage,
t
}),
[currentLanguage, fallbackLanguage, mergedBundles, setLanguage, t]
);
return /* @__PURE__ */ jsx4(I18nContext_default.Provider, { value: contextValue, children });
};
var I18nProvider_default = I18nProvider;
// src/contexts/Organization/OrganizationProvider.tsx
import {
AsgardeoRuntimeError as AsgardeoRuntimeError2
} from "@asgardeo/browser";
import { useCallback as useCallback5, useMemo as useMemo3, useState as useState5 } from "react";
// src/contexts/Organization/OrganizationContext.ts
import { createContext as createContext6 } from "react";
var OrganizationContext = createContext6({
createOrganization: () => null,
currentOrganization: null,
error: null,
getAllOrganizations: () => Promise.resolve({
count: 0,
organizations: []
}),
isLoading: false,
myOrganizations: null,
revalidateMyOrganizations: () => Promise.resolve([]),
switchOrganization: () => Promise.resolve()
});
OrganizationContext.displayName = "OrganizationContext";
var OrganizationContext_default = OrganizationContext;
// src/contexts/Organization/OrganizationProvider.tsx
import { jsx as jsx5 } from "react/jsx-runtime";
var OrganizationProvider = ({
children,
currentOrganization,
onError,
myOrganizations,
onOrganizationSwitch,
revalidateMyOrganizations,
getAllOrganizations: getAllOrganizations2,
createOrganization: createOrganization2
}) => {
const [isLoading, setIsLoading] = useState5(false);
const [error, setError] = useState5(null);
const switchOrganization = useCallback5(
async (organization) => {
if (!onOrganizationSwitch) {
throw new AsgardeoRuntimeError2(
"onOrganizationSwitch callback is required",
"OrganizationProvider-SwitchError-001",
"react",
"The onOrganizationSwitch callback must be provided to handle organization switching."
);
}
setIsLoading(true);
setError(null);
try {
await onOrganizationSwitch(organization);
} catch (switchError) {
const errorMessage = switchError instanceof Error ? switchError.message : "Failed to switch organization";
setError(errorMessage);
if (onError) {
onError(errorMessage);
}
throw switchError;
} finally {
setIsLoading(false);
}
},
[onOrganizationSwitch, onError]
);
const contextValue = useMemo3(
() => ({
createOrganization: createOrganization2,
currentOrganization,
error,
getAllOrganizations: getAllOrganizations2,
isLoading,
myOrganizations,
revalidateMyOrganizations,
switchOrganization
}),
[
currentOrganization,
error,
isLoading,
myOrganizations,
switchOrganization,
revalidateMyOrganizations,
getAllOrganizations2,
createOrganization2
]
);
return /* @__PURE__ */ jsx5(OrganizationContext_default.Provider, { value: contextValue, children });
};
var OrganizationProvider_default = OrganizationProvider;
// src/contexts/Theme/ThemeProvider.tsx
import {
Platform as Platform2
} from "@asgardeo/browser";
// src/contexts/Theme/v1/ThemeProvider.tsx
import {
createTheme,
detectThemeMode,
createClassObserver,
createMediaQueryListener,
DEFAULT_THEME,
createPackageComponentLogger as createPackageComponentLogger2
} from "@asgardeo/browser";
import { useEffect as useEffect4, useMemo as useMemo4, useState as useState6, useCallback as useCallback6 } from "react";
// src/utils/applyThemeToDOM.ts
var applyThemeToDOM = (theme) => {
Object.entries(theme.cssVariables).forEach(([key, value]) => {
document.documentElement.style.setProperty(key, value);
});
};
var applyThemeToDOM_default = applyThemeToDOM;
// src/utils/normalizeThemeConfig.ts
var normalizeColorValue = (color) => typeof color === "string" ? { main: color } : color;
var normalizeThemeConfig = (config) => {
if (!config?.colors) {
return config;
}
const { primary, secondary, error, success, warning, info, ...restColors } = config.colors;
return {
...config,
colors: {
...restColors,
...primary !== void 0 ? { primary: normalizeColorValue(primary) } : {},
...secondary !== void 0 ? { secondary: normalizeColorValue(secondary) } : {},
...error !== void 0 ? { error: normalizeColorValue(error) } : {},
...success !== void 0 ? { success: normalizeColorValue(success) } : {},
...warning !== void 0 ? { warning: normalizeColorValue(warning) } : {},
...info !== void 0 ? { info: normalizeColorValue(info) } : {}
}
};
};
var normalizeThemeConfig_default = normalizeThemeConfig;
// src/contexts/Branding/useBrandingContext.ts
import { useContext as useContext2 } from "react";
var useBrandingContext = () => {
const context = useContext2(BrandingContext_default);
if (!context) {
throw new Error("useBrandingContext must be used within a BrandingProvider");
}
return context;
};
var useBrandingContext_default = useBrandingContext;
// src/contexts/Theme/ThemeContext.ts
import { createContext as createContext7 } from "react";
var ThemeContext = createContext7(null);
ThemeContext.displayName = "ThemeContext";
var ThemeContext_default = ThemeContext;
// src/contexts/Theme/v1/ThemeProvider.tsx
import { jsx as jsx6 } from "react/jsx-runtime";
var logger2 = createPackageComponentLogger2(
"@asgardeo/react",
"ThemeProvider"
);
var ThemeProvider = ({
children,
theme: themeConfigProp,
mode = DEFAULT_THEME,
detection = {},
inheritFromBranding = true
}) => {
const themeConfig = normalizeThemeConfig_default(themeConfigProp);
const [colorScheme, setColorScheme] = useState6(() => {
if (mode === "light" || mode === "dark") {
return mode;
}
if (mode === "branding") {
return detectThemeMode("system", detection);
}
return detectThemeMode(mode, detection);
});
let brandingTheme = null;
let brandingActiveTheme = null;
let isBrandingLoading = false;
let brandingError = null;
try {
const brandingContext = useBrandingContext_default();
brandingTheme = brandingContext.theme;
brandingActiveTheme = brandingContext.activeTheme;
isBrandingLoading = brandingContext.isLoading;
brandingError = brandingContext.error;
} catch (error) {
if (inheritFromBranding) {
logger2.warn(
"ThemeProvider: inheritFromBranding is enabled but BrandingProvider is not available. Make sure to wrap your app with BrandingProvider or AsgardeoProvider with branding preferences."
);
}
}
useEffect4(() => {
if (inheritFromBranding && brandingActiveTheme) {
if (mode === "branding") {
setColorScheme(brandingActiveTheme);
} else if (mode === "system" && !isBrandingLoading) {
setColorScheme(brandingActiveTheme);