@azure/msal-common
Version:
Microsoft Authentication Library for js
1,318 lines (1,300 loc) • 344 kB
JavaScript
/*! @azure/msal-common v15.12.0 2025-08-19 */
'use strict';
'use strict';
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
const Constants = {
LIBRARY_NAME: "MSAL.JS",
SKU: "msal.js.common",
// default authority
DEFAULT_AUTHORITY: "https://login.microsoftonline.com/common/",
DEFAULT_AUTHORITY_HOST: "login.microsoftonline.com",
DEFAULT_COMMON_TENANT: "common",
// ADFS String
ADFS: "adfs",
DSTS: "dstsv2",
// Default AAD Instance Discovery Endpoint
AAD_INSTANCE_DISCOVERY_ENDPT: "https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=",
// CIAM URL
CIAM_AUTH_URL: ".ciamlogin.com",
AAD_TENANT_DOMAIN_SUFFIX: ".onmicrosoft.com",
// Resource delimiter - used for certain cache entries
RESOURCE_DELIM: "|",
// Placeholder for non-existent account ids/objects
NO_ACCOUNT: "NO_ACCOUNT",
// Claims
CLAIMS: "claims",
// Consumer UTID
CONSUMER_UTID: "9188040d-6c67-4c5b-b112-36a304b66dad",
// Default scopes
OPENID_SCOPE: "openid",
PROFILE_SCOPE: "profile",
OFFLINE_ACCESS_SCOPE: "offline_access",
EMAIL_SCOPE: "email",
CODE_GRANT_TYPE: "authorization_code",
RT_GRANT_TYPE: "refresh_token",
S256_CODE_CHALLENGE_METHOD: "S256",
URL_FORM_CONTENT_TYPE: "application/x-www-form-urlencoded;charset=utf-8",
AUTHORIZATION_PENDING: "authorization_pending",
NOT_DEFINED: "not_defined",
EMPTY_STRING: "",
NOT_APPLICABLE: "N/A",
NOT_AVAILABLE: "Not Available",
FORWARD_SLASH: "/",
IMDS_ENDPOINT: "http://169.254.169.254/metadata/instance/compute/location",
IMDS_VERSION: "2020-06-01",
IMDS_TIMEOUT: 2000,
AZURE_REGION_AUTO_DISCOVER_FLAG: "TryAutoDetect",
REGIONAL_AUTH_PUBLIC_CLOUD_SUFFIX: "login.microsoft.com",
KNOWN_PUBLIC_CLOUDS: [
"login.microsoftonline.com",
"login.windows.net",
"login.microsoft.com",
"sts.windows.net",
],
SHR_NONCE_VALIDITY: 240,
INVALID_INSTANCE: "invalid_instance",
};
const HttpStatus = {
SUCCESS: 200,
SUCCESS_RANGE_START: 200,
SUCCESS_RANGE_END: 299,
REDIRECT: 302,
CLIENT_ERROR: 400,
CLIENT_ERROR_RANGE_START: 400,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
NOT_FOUND: 404,
REQUEST_TIMEOUT: 408,
GONE: 410,
TOO_MANY_REQUESTS: 429,
CLIENT_ERROR_RANGE_END: 499,
SERVER_ERROR: 500,
SERVER_ERROR_RANGE_START: 500,
SERVICE_UNAVAILABLE: 503,
GATEWAY_TIMEOUT: 504,
SERVER_ERROR_RANGE_END: 599,
MULTI_SIDED_ERROR: 600,
};
const HttpMethod = {
GET: "GET",
POST: "POST",
};
const OIDC_DEFAULT_SCOPES = [
Constants.OPENID_SCOPE,
Constants.PROFILE_SCOPE,
Constants.OFFLINE_ACCESS_SCOPE,
];
const OIDC_SCOPES = [...OIDC_DEFAULT_SCOPES, Constants.EMAIL_SCOPE];
/**
* Request header names
*/
const HeaderNames = {
CONTENT_TYPE: "Content-Type",
CONTENT_LENGTH: "Content-Length",
RETRY_AFTER: "Retry-After",
CCS_HEADER: "X-AnchorMailbox",
WWWAuthenticate: "WWW-Authenticate",
AuthenticationInfo: "Authentication-Info",
X_MS_REQUEST_ID: "x-ms-request-id",
X_MS_HTTP_VERSION: "x-ms-httpver",
};
/**
* Persistent cache keys MSAL which stay while user is logged in.
*/
const PersistentCacheKeys = {
ACTIVE_ACCOUNT_FILTERS: "active-account-filters", // new cache entry for active_account for a more robust version for browser
};
/**
* String constants related to AAD Authority
*/
const AADAuthorityConstants = {
COMMON: "common",
ORGANIZATIONS: "organizations",
CONSUMERS: "consumers",
};
/**
* Claims request keys
*/
const ClaimsRequestKeys = {
ACCESS_TOKEN: "access_token",
XMS_CC: "xms_cc",
};
/**
* we considered making this "enum" in the request instead of string, however it looks like the allowed list of
* prompt values kept changing over past couple of years. There are some undocumented prompt values for some
* internal partners too, hence the choice of generic "string" type instead of the "enum"
*/
const PromptValue = {
LOGIN: "login",
SELECT_ACCOUNT: "select_account",
CONSENT: "consent",
NONE: "none",
CREATE: "create",
NO_SESSION: "no_session",
};
/**
* allowed values for codeVerifier
*/
const CodeChallengeMethodValues = {
PLAIN: "plain",
S256: "S256",
};
/**
* Allowed values for response_type
*/
const OAuthResponseType = {
CODE: "code",
IDTOKEN_TOKEN: "id_token token",
IDTOKEN_TOKEN_REFRESHTOKEN: "id_token token refresh_token",
};
/**
* allowed values for server response type
* @deprecated Use ResponseMode instead
*/
const ServerResponseType = {
QUERY: "query",
FRAGMENT: "fragment",
};
/**
* allowed values for response_mode
*/
const ResponseMode = {
QUERY: "query",
FRAGMENT: "fragment",
FORM_POST: "form_post",
};
/**
* allowed grant_type
*/
const GrantType = {
IMPLICIT_GRANT: "implicit",
AUTHORIZATION_CODE_GRANT: "authorization_code",
CLIENT_CREDENTIALS_GRANT: "client_credentials",
RESOURCE_OWNER_PASSWORD_GRANT: "password",
REFRESH_TOKEN_GRANT: "refresh_token",
DEVICE_CODE_GRANT: "device_code",
JWT_BEARER: "urn:ietf:params:oauth:grant-type:jwt-bearer",
};
/**
* Account types in Cache
*/
const CacheAccountType = {
MSSTS_ACCOUNT_TYPE: "MSSTS",
ADFS_ACCOUNT_TYPE: "ADFS",
MSAV1_ACCOUNT_TYPE: "MSA",
GENERIC_ACCOUNT_TYPE: "Generic", // NTLM, Kerberos, FBA, Basic etc
};
/**
* Separators used in cache
*/
const Separators = {
CACHE_KEY_SEPARATOR: "-",
CLIENT_INFO_SEPARATOR: ".",
};
/**
* Credential Type stored in the cache
*/
const CredentialType = {
ID_TOKEN: "IdToken",
ACCESS_TOKEN: "AccessToken",
ACCESS_TOKEN_WITH_AUTH_SCHEME: "AccessToken_With_AuthScheme",
REFRESH_TOKEN: "RefreshToken",
};
/**
* Combine all cache types
*/
const CacheType = {
ADFS: 1001,
MSA: 1002,
MSSTS: 1003,
GENERIC: 1004,
ACCESS_TOKEN: 2001,
REFRESH_TOKEN: 2002,
ID_TOKEN: 2003,
APP_METADATA: 3001,
UNDEFINED: 9999,
};
/**
* More Cache related constants
*/
const APP_METADATA = "appmetadata";
const CLIENT_INFO$1 = "client_info";
const THE_FAMILY_ID = "1";
const AUTHORITY_METADATA_CONSTANTS = {
CACHE_KEY: "authority-metadata",
REFRESH_TIME_SECONDS: 3600 * 24, // 24 Hours
};
const AuthorityMetadataSource = {
CONFIG: "config",
CACHE: "cache",
NETWORK: "network",
HARDCODED_VALUES: "hardcoded_values",
};
const SERVER_TELEM_CONSTANTS = {
SCHEMA_VERSION: 5,
MAX_LAST_HEADER_BYTES: 330,
MAX_CACHED_ERRORS: 50,
CACHE_KEY: "server-telemetry",
CATEGORY_SEPARATOR: "|",
VALUE_SEPARATOR: ",",
OVERFLOW_TRUE: "1",
OVERFLOW_FALSE: "0",
UNKNOWN_ERROR: "unknown_error",
};
/**
* Type of the authentication request
*/
const AuthenticationScheme = {
BEARER: "Bearer",
POP: "pop",
SSH: "ssh-cert",
};
/**
* Constants related to throttling
*/
const ThrottlingConstants = {
// Default time to throttle RequestThumbprint in seconds
DEFAULT_THROTTLE_TIME_SECONDS: 60,
// Default maximum time to throttle in seconds, overrides what the server sends back
DEFAULT_MAX_THROTTLE_TIME_SECONDS: 3600,
// Prefix for storing throttling entries
THROTTLING_PREFIX: "throttling",
// Value assigned to the x-ms-lib-capability header to indicate to the server the library supports throttling
X_MS_LIB_CAPABILITY_VALUE: "retry-after, h429",
};
const Errors = {
INVALID_GRANT_ERROR: "invalid_grant",
CLIENT_MISMATCH_ERROR: "client_mismatch",
};
/**
* Password grant parameters
*/
const PasswordGrantConstants = {
username: "username",
password: "password",
};
/**
* Region Discovery Sources
*/
const RegionDiscoverySources = {
FAILED_AUTO_DETECTION: "1",
INTERNAL_CACHE: "2",
ENVIRONMENT_VARIABLE: "3",
IMDS: "4",
};
/**
* Region Discovery Outcomes
*/
const RegionDiscoveryOutcomes = {
CONFIGURED_NO_AUTO_DETECTION: "2",
AUTO_DETECTION_REQUESTED_SUCCESSFUL: "4",
AUTO_DETECTION_REQUESTED_FAILED: "5",
};
/**
* Specifies the reason for fetching the access token from the identity provider
*/
const CacheOutcome = {
// When a token is found in the cache or the cache is not supposed to be hit when making the request
NOT_APPLICABLE: "0",
// When the token request goes to the identity provider because force_refresh was set to true. Also occurs if claims were requested
FORCE_REFRESH_OR_CLAIMS: "1",
// When the token request goes to the identity provider because no cached access token exists
NO_CACHED_ACCESS_TOKEN: "2",
// When the token request goes to the identity provider because cached access token expired
CACHED_ACCESS_TOKEN_EXPIRED: "3",
// When the token request goes to the identity provider because refresh_in was used and the existing token needs to be refreshed
PROACTIVELY_REFRESHED: "4",
};
const JsonWebTokenTypes = {
Jwt: "JWT",
Jwk: "JWK",
Pop: "pop",
};
const ONE_DAY_IN_MS = 86400000;
// Token renewal offset default in seconds
const DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;
const EncodingTypes = {
BASE64: "base64",
HEX: "hex",
UTF8: "utf-8",
};
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* AuthErrorMessage class containing string constants used by error codes and messages.
*/
const unexpectedError = "unexpected_error";
const postRequestFailed = "post_request_failed";
var AuthErrorCodes = /*#__PURE__*/Object.freeze({
__proto__: null,
postRequestFailed: postRequestFailed,
unexpectedError: unexpectedError
});
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
const AuthErrorMessages = {
[unexpectedError]: "Unexpected error in authentication.",
[postRequestFailed]: "Post request failed from the network, could be a 4xx/5xx or a network unavailability. Please check the exact error code for details.",
};
/**
* AuthErrorMessage class containing string constants used by error codes and messages.
* @deprecated Use AuthErrorCodes instead
*/
const AuthErrorMessage = {
unexpectedError: {
code: unexpectedError,
desc: AuthErrorMessages[unexpectedError],
},
postRequestFailed: {
code: postRequestFailed,
desc: AuthErrorMessages[postRequestFailed],
},
};
/**
* General error class thrown by the MSAL.js library.
*/
class AuthError extends Error {
constructor(errorCode, errorMessage, suberror) {
const errorString = errorMessage
? `${errorCode}: ${errorMessage}`
: errorCode;
super(errorString);
Object.setPrototypeOf(this, AuthError.prototype);
this.errorCode = errorCode || Constants.EMPTY_STRING;
this.errorMessage = errorMessage || Constants.EMPTY_STRING;
this.subError = suberror || Constants.EMPTY_STRING;
this.name = "AuthError";
}
setCorrelationId(correlationId) {
this.correlationId = correlationId;
}
}
function createAuthError(code, additionalMessage) {
return new AuthError(code, additionalMessage
? `${AuthErrorMessages[code]} ${additionalMessage}`
: AuthErrorMessages[code]);
}
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
const clientInfoDecodingError = "client_info_decoding_error";
const clientInfoEmptyError = "client_info_empty_error";
const tokenParsingError = "token_parsing_error";
const nullOrEmptyToken = "null_or_empty_token";
const endpointResolutionError = "endpoints_resolution_error";
const networkError = "network_error";
const openIdConfigError = "openid_config_error";
const hashNotDeserialized = "hash_not_deserialized";
const invalidState = "invalid_state";
const stateMismatch = "state_mismatch";
const stateNotFound = "state_not_found";
const nonceMismatch = "nonce_mismatch";
const authTimeNotFound = "auth_time_not_found";
const maxAgeTranspired = "max_age_transpired";
const multipleMatchingTokens = "multiple_matching_tokens";
const multipleMatchingAccounts = "multiple_matching_accounts";
const multipleMatchingAppMetadata = "multiple_matching_appMetadata";
const requestCannotBeMade = "request_cannot_be_made";
const cannotRemoveEmptyScope = "cannot_remove_empty_scope";
const cannotAppendScopeSet = "cannot_append_scopeset";
const emptyInputScopeSet = "empty_input_scopeset";
const deviceCodePollingCancelled = "device_code_polling_cancelled";
const deviceCodeExpired = "device_code_expired";
const deviceCodeUnknownError = "device_code_unknown_error";
const noAccountInSilentRequest = "no_account_in_silent_request";
const invalidCacheRecord = "invalid_cache_record";
const invalidCacheEnvironment = "invalid_cache_environment";
const noAccountFound = "no_account_found";
const noCryptoObject = "no_crypto_object";
const unexpectedCredentialType = "unexpected_credential_type";
const invalidAssertion = "invalid_assertion";
const invalidClientCredential = "invalid_client_credential";
const tokenRefreshRequired = "token_refresh_required";
const userTimeoutReached = "user_timeout_reached";
const tokenClaimsCnfRequiredForSignedJwt = "token_claims_cnf_required_for_signedjwt";
const authorizationCodeMissingFromServerResponse = "authorization_code_missing_from_server_response";
const bindingKeyNotRemoved = "binding_key_not_removed";
const endSessionEndpointNotSupported = "end_session_endpoint_not_supported";
const keyIdMissing = "key_id_missing";
const noNetworkConnectivity = "no_network_connectivity";
const userCanceled = "user_canceled";
const missingTenantIdError = "missing_tenant_id_error";
const methodNotImplemented = "method_not_implemented";
const nestedAppAuthBridgeDisabled = "nested_app_auth_bridge_disabled";
var ClientAuthErrorCodes = /*#__PURE__*/Object.freeze({
__proto__: null,
authTimeNotFound: authTimeNotFound,
authorizationCodeMissingFromServerResponse: authorizationCodeMissingFromServerResponse,
bindingKeyNotRemoved: bindingKeyNotRemoved,
cannotAppendScopeSet: cannotAppendScopeSet,
cannotRemoveEmptyScope: cannotRemoveEmptyScope,
clientInfoDecodingError: clientInfoDecodingError,
clientInfoEmptyError: clientInfoEmptyError,
deviceCodeExpired: deviceCodeExpired,
deviceCodePollingCancelled: deviceCodePollingCancelled,
deviceCodeUnknownError: deviceCodeUnknownError,
emptyInputScopeSet: emptyInputScopeSet,
endSessionEndpointNotSupported: endSessionEndpointNotSupported,
endpointResolutionError: endpointResolutionError,
hashNotDeserialized: hashNotDeserialized,
invalidAssertion: invalidAssertion,
invalidCacheEnvironment: invalidCacheEnvironment,
invalidCacheRecord: invalidCacheRecord,
invalidClientCredential: invalidClientCredential,
invalidState: invalidState,
keyIdMissing: keyIdMissing,
maxAgeTranspired: maxAgeTranspired,
methodNotImplemented: methodNotImplemented,
missingTenantIdError: missingTenantIdError,
multipleMatchingAccounts: multipleMatchingAccounts,
multipleMatchingAppMetadata: multipleMatchingAppMetadata,
multipleMatchingTokens: multipleMatchingTokens,
nestedAppAuthBridgeDisabled: nestedAppAuthBridgeDisabled,
networkError: networkError,
noAccountFound: noAccountFound,
noAccountInSilentRequest: noAccountInSilentRequest,
noCryptoObject: noCryptoObject,
noNetworkConnectivity: noNetworkConnectivity,
nonceMismatch: nonceMismatch,
nullOrEmptyToken: nullOrEmptyToken,
openIdConfigError: openIdConfigError,
requestCannotBeMade: requestCannotBeMade,
stateMismatch: stateMismatch,
stateNotFound: stateNotFound,
tokenClaimsCnfRequiredForSignedJwt: tokenClaimsCnfRequiredForSignedJwt,
tokenParsingError: tokenParsingError,
tokenRefreshRequired: tokenRefreshRequired,
unexpectedCredentialType: unexpectedCredentialType,
userCanceled: userCanceled,
userTimeoutReached: userTimeoutReached
});
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* ClientAuthErrorMessage class containing string constants used by error codes and messages.
*/
const ClientAuthErrorMessages = {
[clientInfoDecodingError]: "The client info could not be parsed/decoded correctly",
[clientInfoEmptyError]: "The client info was empty",
[tokenParsingError]: "Token cannot be parsed",
[nullOrEmptyToken]: "The token is null or empty",
[endpointResolutionError]: "Endpoints cannot be resolved",
[networkError]: "Network request failed",
[openIdConfigError]: "Could not retrieve endpoints. Check your authority and verify the .well-known/openid-configuration endpoint returns the required endpoints.",
[hashNotDeserialized]: "The hash parameters could not be deserialized",
[invalidState]: "State was not the expected format",
[stateMismatch]: "State mismatch error",
[stateNotFound]: "State not found",
[nonceMismatch]: "Nonce mismatch error",
[authTimeNotFound]: "Max Age was requested and the ID token is missing the auth_time variable." +
" auth_time is an optional claim and is not enabled by default - it must be enabled." +
" See https://aka.ms/msaljs/optional-claims for more information.",
[maxAgeTranspired]: "Max Age is set to 0, or too much time has elapsed since the last end-user authentication.",
[multipleMatchingTokens]: "The cache contains multiple tokens satisfying the requirements. " +
"Call AcquireToken again providing more requirements such as authority or account.",
[multipleMatchingAccounts]: "The cache contains multiple accounts satisfying the given parameters. Please pass more info to obtain the correct account",
[multipleMatchingAppMetadata]: "The cache contains multiple appMetadata satisfying the given parameters. Please pass more info to obtain the correct appMetadata",
[requestCannotBeMade]: "Token request cannot be made without authorization code or refresh token.",
[cannotRemoveEmptyScope]: "Cannot remove null or empty scope from ScopeSet",
[cannotAppendScopeSet]: "Cannot append ScopeSet",
[emptyInputScopeSet]: "Empty input ScopeSet cannot be processed",
[deviceCodePollingCancelled]: "Caller has cancelled token endpoint polling during device code flow by setting DeviceCodeRequest.cancel = true.",
[deviceCodeExpired]: "Device code is expired.",
[deviceCodeUnknownError]: "Device code stopped polling for unknown reasons.",
[noAccountInSilentRequest]: "Please pass an account object, silent flow is not supported without account information",
[invalidCacheRecord]: "Cache record object was null or undefined.",
[invalidCacheEnvironment]: "Invalid environment when attempting to create cache entry",
[noAccountFound]: "No account found in cache for given key.",
[noCryptoObject]: "No crypto object detected.",
[unexpectedCredentialType]: "Unexpected credential type.",
[invalidAssertion]: "Client assertion must meet requirements described in https://tools.ietf.org/html/rfc7515",
[invalidClientCredential]: "Client credential (secret, certificate, or assertion) must not be empty when creating a confidential client. An application should at most have one credential",
[tokenRefreshRequired]: "Cannot return token from cache because it must be refreshed. This may be due to one of the following reasons: forceRefresh parameter is set to true, claims have been requested, there is no cached access token or it is expired.",
[userTimeoutReached]: "User defined timeout for device code polling reached",
[tokenClaimsCnfRequiredForSignedJwt]: "Cannot generate a POP jwt if the token_claims are not populated",
[authorizationCodeMissingFromServerResponse]: "Server response does not contain an authorization code to proceed",
[bindingKeyNotRemoved]: "Could not remove the credential's binding key from storage.",
[endSessionEndpointNotSupported]: "The provided authority does not support logout",
[keyIdMissing]: "A keyId value is missing from the requested bound token's cache record and is required to match the token to it's stored binding key.",
[noNetworkConnectivity]: "No network connectivity. Check your internet connection.",
[userCanceled]: "User cancelled the flow.",
[missingTenantIdError]: "A tenant id - not common, organizations, or consumers - must be specified when using the client_credentials flow.",
[methodNotImplemented]: "This method has not been implemented",
[nestedAppAuthBridgeDisabled]: "The nested app auth bridge is disabled",
};
/**
* String constants used by error codes and messages.
* @deprecated Use ClientAuthErrorCodes instead
*/
const ClientAuthErrorMessage = {
clientInfoDecodingError: {
code: clientInfoDecodingError,
desc: ClientAuthErrorMessages[clientInfoDecodingError],
},
clientInfoEmptyError: {
code: clientInfoEmptyError,
desc: ClientAuthErrorMessages[clientInfoEmptyError],
},
tokenParsingError: {
code: tokenParsingError,
desc: ClientAuthErrorMessages[tokenParsingError],
},
nullOrEmptyToken: {
code: nullOrEmptyToken,
desc: ClientAuthErrorMessages[nullOrEmptyToken],
},
endpointResolutionError: {
code: endpointResolutionError,
desc: ClientAuthErrorMessages[endpointResolutionError],
},
networkError: {
code: networkError,
desc: ClientAuthErrorMessages[networkError],
},
unableToGetOpenidConfigError: {
code: openIdConfigError,
desc: ClientAuthErrorMessages[openIdConfigError],
},
hashNotDeserialized: {
code: hashNotDeserialized,
desc: ClientAuthErrorMessages[hashNotDeserialized],
},
invalidStateError: {
code: invalidState,
desc: ClientAuthErrorMessages[invalidState],
},
stateMismatchError: {
code: stateMismatch,
desc: ClientAuthErrorMessages[stateMismatch],
},
stateNotFoundError: {
code: stateNotFound,
desc: ClientAuthErrorMessages[stateNotFound],
},
nonceMismatchError: {
code: nonceMismatch,
desc: ClientAuthErrorMessages[nonceMismatch],
},
authTimeNotFoundError: {
code: authTimeNotFound,
desc: ClientAuthErrorMessages[authTimeNotFound],
},
maxAgeTranspired: {
code: maxAgeTranspired,
desc: ClientAuthErrorMessages[maxAgeTranspired],
},
multipleMatchingTokens: {
code: multipleMatchingTokens,
desc: ClientAuthErrorMessages[multipleMatchingTokens],
},
multipleMatchingAccounts: {
code: multipleMatchingAccounts,
desc: ClientAuthErrorMessages[multipleMatchingAccounts],
},
multipleMatchingAppMetadata: {
code: multipleMatchingAppMetadata,
desc: ClientAuthErrorMessages[multipleMatchingAppMetadata],
},
tokenRequestCannotBeMade: {
code: requestCannotBeMade,
desc: ClientAuthErrorMessages[requestCannotBeMade],
},
removeEmptyScopeError: {
code: cannotRemoveEmptyScope,
desc: ClientAuthErrorMessages[cannotRemoveEmptyScope],
},
appendScopeSetError: {
code: cannotAppendScopeSet,
desc: ClientAuthErrorMessages[cannotAppendScopeSet],
},
emptyInputScopeSetError: {
code: emptyInputScopeSet,
desc: ClientAuthErrorMessages[emptyInputScopeSet],
},
DeviceCodePollingCancelled: {
code: deviceCodePollingCancelled,
desc: ClientAuthErrorMessages[deviceCodePollingCancelled],
},
DeviceCodeExpired: {
code: deviceCodeExpired,
desc: ClientAuthErrorMessages[deviceCodeExpired],
},
DeviceCodeUnknownError: {
code: deviceCodeUnknownError,
desc: ClientAuthErrorMessages[deviceCodeUnknownError],
},
NoAccountInSilentRequest: {
code: noAccountInSilentRequest,
desc: ClientAuthErrorMessages[noAccountInSilentRequest],
},
invalidCacheRecord: {
code: invalidCacheRecord,
desc: ClientAuthErrorMessages[invalidCacheRecord],
},
invalidCacheEnvironment: {
code: invalidCacheEnvironment,
desc: ClientAuthErrorMessages[invalidCacheEnvironment],
},
noAccountFound: {
code: noAccountFound,
desc: ClientAuthErrorMessages[noAccountFound],
},
noCryptoObj: {
code: noCryptoObject,
desc: ClientAuthErrorMessages[noCryptoObject],
},
unexpectedCredentialType: {
code: unexpectedCredentialType,
desc: ClientAuthErrorMessages[unexpectedCredentialType],
},
invalidAssertion: {
code: invalidAssertion,
desc: ClientAuthErrorMessages[invalidAssertion],
},
invalidClientCredential: {
code: invalidClientCredential,
desc: ClientAuthErrorMessages[invalidClientCredential],
},
tokenRefreshRequired: {
code: tokenRefreshRequired,
desc: ClientAuthErrorMessages[tokenRefreshRequired],
},
userTimeoutReached: {
code: userTimeoutReached,
desc: ClientAuthErrorMessages[userTimeoutReached],
},
tokenClaimsRequired: {
code: tokenClaimsCnfRequiredForSignedJwt,
desc: ClientAuthErrorMessages[tokenClaimsCnfRequiredForSignedJwt],
},
noAuthorizationCodeFromServer: {
code: authorizationCodeMissingFromServerResponse,
desc: ClientAuthErrorMessages[authorizationCodeMissingFromServerResponse],
},
bindingKeyNotRemovedError: {
code: bindingKeyNotRemoved,
desc: ClientAuthErrorMessages[bindingKeyNotRemoved],
},
logoutNotSupported: {
code: endSessionEndpointNotSupported,
desc: ClientAuthErrorMessages[endSessionEndpointNotSupported],
},
keyIdMissing: {
code: keyIdMissing,
desc: ClientAuthErrorMessages[keyIdMissing],
},
noNetworkConnectivity: {
code: noNetworkConnectivity,
desc: ClientAuthErrorMessages[noNetworkConnectivity],
},
userCanceledError: {
code: userCanceled,
desc: ClientAuthErrorMessages[userCanceled],
},
missingTenantIdError: {
code: missingTenantIdError,
desc: ClientAuthErrorMessages[missingTenantIdError],
},
nestedAppAuthBridgeDisabled: {
code: nestedAppAuthBridgeDisabled,
desc: ClientAuthErrorMessages[nestedAppAuthBridgeDisabled],
},
};
/**
* Error thrown when there is an error in the client code running on the browser.
*/
class ClientAuthError extends AuthError {
constructor(errorCode, additionalMessage) {
super(errorCode, additionalMessage
? `${ClientAuthErrorMessages[errorCode]}: ${additionalMessage}`
: ClientAuthErrorMessages[errorCode]);
this.name = "ClientAuthError";
Object.setPrototypeOf(this, ClientAuthError.prototype);
}
}
function createClientAuthError(errorCode, additionalMessage) {
return new ClientAuthError(errorCode, additionalMessage);
}
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* Extract token by decoding the rawToken
*
* @param encodedToken
*/
function extractTokenClaims(encodedToken, base64Decode) {
const jswPayload = getJWSPayload(encodedToken);
// token will be decoded to get the username
try {
// base64Decode() should throw an error if there is an issue
const base64Decoded = base64Decode(jswPayload);
return JSON.parse(base64Decoded);
}
catch (err) {
throw createClientAuthError(tokenParsingError);
}
}
/**
* decode a JWT
*
* @param authToken
*/
function getJWSPayload(authToken) {
if (!authToken) {
throw createClientAuthError(nullOrEmptyToken);
}
const tokenPartsRegex = /^([^\.\s]*)\.([^\.\s]+)\.([^\.\s]*)$/;
const matches = tokenPartsRegex.exec(authToken);
if (!matches || matches.length < 4) {
throw createClientAuthError(tokenParsingError);
}
/**
* const crackedToken = {
* header: matches[1],
* JWSPayload: matches[2],
* JWSSig: matches[3],
* };
*/
return matches[2];
}
/**
* Determine if the token's max_age has transpired
*/
function checkMaxAge(authTime, maxAge) {
/*
* per https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
* To force an immediate re-authentication: If an app requires that a user re-authenticate prior to access,
* provide a value of 0 for the max_age parameter and the AS will force a fresh login.
*/
const fiveMinuteSkew = 300000; // five minutes in milliseconds
if (maxAge === 0 || Date.now() - fiveMinuteSkew > authTime + maxAge) {
throw createClientAuthError(maxAgeTranspired);
}
}
var AuthToken = /*#__PURE__*/Object.freeze({
__proto__: null,
checkMaxAge: checkMaxAge,
extractTokenClaims: extractTokenClaims,
getJWSPayload: getJWSPayload
});
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* Authority types supported by MSAL.
*/
const AuthorityType = {
Default: 0,
Adfs: 1,
Dsts: 2,
Ciam: 3,
};
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
function isOpenIdConfigResponse(response) {
return (response.hasOwnProperty("authorization_endpoint") &&
response.hasOwnProperty("token_endpoint") &&
response.hasOwnProperty("issuer") &&
response.hasOwnProperty("jwks_uri"));
}
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
const redirectUriEmpty = "redirect_uri_empty";
const claimsRequestParsingError = "claims_request_parsing_error";
const authorityUriInsecure = "authority_uri_insecure";
const urlParseError = "url_parse_error";
const urlEmptyError = "empty_url_error";
const emptyInputScopesError = "empty_input_scopes_error";
const invalidClaims = "invalid_claims";
const tokenRequestEmpty = "token_request_empty";
const logoutRequestEmpty = "logout_request_empty";
const invalidCodeChallengeMethod = "invalid_code_challenge_method";
const pkceParamsMissing = "pkce_params_missing";
const invalidCloudDiscoveryMetadata = "invalid_cloud_discovery_metadata";
const invalidAuthorityMetadata = "invalid_authority_metadata";
const untrustedAuthority = "untrusted_authority";
const missingSshJwk = "missing_ssh_jwk";
const missingSshKid = "missing_ssh_kid";
const missingNonceAuthenticationHeader = "missing_nonce_authentication_header";
const invalidAuthenticationHeader = "invalid_authentication_header";
const cannotSetOIDCOptions = "cannot_set_OIDCOptions";
const cannotAllowPlatformBroker = "cannot_allow_platform_broker";
const authorityMismatch = "authority_mismatch";
const invalidRequestMethodForEAR = "invalid_request_method_for_EAR";
const invalidAuthorizePostBodyParameters = "invalid_authorize_post_body_parameters";
var ClientConfigurationErrorCodes = /*#__PURE__*/Object.freeze({
__proto__: null,
authorityMismatch: authorityMismatch,
authorityUriInsecure: authorityUriInsecure,
cannotAllowPlatformBroker: cannotAllowPlatformBroker,
cannotSetOIDCOptions: cannotSetOIDCOptions,
claimsRequestParsingError: claimsRequestParsingError,
emptyInputScopesError: emptyInputScopesError,
invalidAuthenticationHeader: invalidAuthenticationHeader,
invalidAuthorityMetadata: invalidAuthorityMetadata,
invalidAuthorizePostBodyParameters: invalidAuthorizePostBodyParameters,
invalidClaims: invalidClaims,
invalidCloudDiscoveryMetadata: invalidCloudDiscoveryMetadata,
invalidCodeChallengeMethod: invalidCodeChallengeMethod,
invalidRequestMethodForEAR: invalidRequestMethodForEAR,
logoutRequestEmpty: logoutRequestEmpty,
missingNonceAuthenticationHeader: missingNonceAuthenticationHeader,
missingSshJwk: missingSshJwk,
missingSshKid: missingSshKid,
pkceParamsMissing: pkceParamsMissing,
redirectUriEmpty: redirectUriEmpty,
tokenRequestEmpty: tokenRequestEmpty,
untrustedAuthority: untrustedAuthority,
urlEmptyError: urlEmptyError,
urlParseError: urlParseError
});
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
const ClientConfigurationErrorMessages = {
[redirectUriEmpty]: "A redirect URI is required for all calls, and none has been set.",
[claimsRequestParsingError]: "Could not parse the given claims request object.",
[authorityUriInsecure]: "Authority URIs must use https. Please see here for valid authority configuration options: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications#configuration-options",
[urlParseError]: "URL could not be parsed into appropriate segments.",
[urlEmptyError]: "URL was empty or null.",
[emptyInputScopesError]: "Scopes cannot be passed as null, undefined or empty array because they are required to obtain an access token.",
[invalidClaims]: "Given claims parameter must be a stringified JSON object.",
[tokenRequestEmpty]: "Token request was empty and not found in cache.",
[logoutRequestEmpty]: "The logout request was null or undefined.",
[invalidCodeChallengeMethod]: 'code_challenge_method passed is invalid. Valid values are "plain" and "S256".',
[pkceParamsMissing]: "Both params: code_challenge and code_challenge_method are to be passed if to be sent in the request",
[invalidCloudDiscoveryMetadata]: "Invalid cloudDiscoveryMetadata provided. Must be a stringified JSON object containing tenant_discovery_endpoint and metadata fields",
[invalidAuthorityMetadata]: "Invalid authorityMetadata provided. Must by a stringified JSON object containing authorization_endpoint, token_endpoint, issuer fields.",
[untrustedAuthority]: "The provided authority is not a trusted authority. Please include this authority in the knownAuthorities config parameter.",
[missingSshJwk]: "Missing sshJwk in SSH certificate request. A stringified JSON Web Key is required when using the SSH authentication scheme.",
[missingSshKid]: "Missing sshKid in SSH certificate request. A string that uniquely identifies the public SSH key is required when using the SSH authentication scheme.",
[missingNonceAuthenticationHeader]: "Unable to find an authentication header containing server nonce. Either the Authentication-Info or WWW-Authenticate headers must be present in order to obtain a server nonce.",
[invalidAuthenticationHeader]: "Invalid authentication header provided",
[cannotSetOIDCOptions]: "Cannot set OIDCOptions parameter. Please change the protocol mode to OIDC or use a non-Microsoft authority.",
[cannotAllowPlatformBroker]: "Cannot set allowPlatformBroker parameter to true when not in AAD protocol mode.",
[authorityMismatch]: "Authority mismatch error. Authority provided in login request or PublicClientApplication config does not match the environment of the provided account. Please use a matching account or make an interactive request to login to this authority.",
[invalidAuthorizePostBodyParameters]: "Invalid authorize post body parameters provided. If you are using authorizePostBodyParameters, the request method must be POST. Please check the request method and parameters.",
[invalidRequestMethodForEAR]: "Invalid request method for EAR protocol mode. The request method cannot be GET when using EAR protocol mode. Please change the request method to POST.",
};
/**
* ClientConfigurationErrorMessage class containing string constants used by error codes and messages.
* @deprecated Use ClientConfigurationErrorCodes instead
*/
const ClientConfigurationErrorMessage = {
redirectUriNotSet: {
code: redirectUriEmpty,
desc: ClientConfigurationErrorMessages[redirectUriEmpty],
},
claimsRequestParsingError: {
code: claimsRequestParsingError,
desc: ClientConfigurationErrorMessages[claimsRequestParsingError],
},
authorityUriInsecure: {
code: authorityUriInsecure,
desc: ClientConfigurationErrorMessages[authorityUriInsecure],
},
urlParseError: {
code: urlParseError,
desc: ClientConfigurationErrorMessages[urlParseError],
},
urlEmptyError: {
code: urlEmptyError,
desc: ClientConfigurationErrorMessages[urlEmptyError],
},
emptyScopesError: {
code: emptyInputScopesError,
desc: ClientConfigurationErrorMessages[emptyInputScopesError],
},
invalidClaimsRequest: {
code: invalidClaims,
desc: ClientConfigurationErrorMessages[invalidClaims],
},
tokenRequestEmptyError: {
code: tokenRequestEmpty,
desc: ClientConfigurationErrorMessages[tokenRequestEmpty],
},
logoutRequestEmptyError: {
code: logoutRequestEmpty,
desc: ClientConfigurationErrorMessages[logoutRequestEmpty],
},
invalidCodeChallengeMethod: {
code: invalidCodeChallengeMethod,
desc: ClientConfigurationErrorMessages[invalidCodeChallengeMethod],
},
invalidCodeChallengeParams: {
code: pkceParamsMissing,
desc: ClientConfigurationErrorMessages[pkceParamsMissing],
},
invalidCloudDiscoveryMetadata: {
code: invalidCloudDiscoveryMetadata,
desc: ClientConfigurationErrorMessages[invalidCloudDiscoveryMetadata],
},
invalidAuthorityMetadata: {
code: invalidAuthorityMetadata,
desc: ClientConfigurationErrorMessages[invalidAuthorityMetadata],
},
untrustedAuthority: {
code: untrustedAuthority,
desc: ClientConfigurationErrorMessages[untrustedAuthority],
},
missingSshJwk: {
code: missingSshJwk,
desc: ClientConfigurationErrorMessages[missingSshJwk],
},
missingSshKid: {
code: missingSshKid,
desc: ClientConfigurationErrorMessages[missingSshKid],
},
missingNonceAuthenticationHeader: {
code: missingNonceAuthenticationHeader,
desc: ClientConfigurationErrorMessages[missingNonceAuthenticationHeader],
},
invalidAuthenticationHeader: {
code: invalidAuthenticationHeader,
desc: ClientConfigurationErrorMessages[invalidAuthenticationHeader],
},
cannotSetOIDCOptions: {
code: cannotSetOIDCOptions,
desc: ClientConfigurationErrorMessages[cannotSetOIDCOptions],
},
cannotAllowPlatformBroker: {
code: cannotAllowPlatformBroker,
desc: ClientConfigurationErrorMessages[cannotAllowPlatformBroker],
},
authorityMismatch: {
code: authorityMismatch,
desc: ClientConfigurationErrorMessages[authorityMismatch],
},
invalidAuthorizePostBodyParameters: {
code: invalidAuthorizePostBodyParameters,
desc: ClientConfigurationErrorMessages[invalidAuthorizePostBodyParameters],
},
invalidRequestMethodForEAR: {
code: invalidRequestMethodForEAR,
desc: ClientConfigurationErrorMessages[invalidRequestMethodForEAR],
},
};
/**
* Error thrown when there is an error in configuration of the MSAL.js library.
*/
class ClientConfigurationError extends AuthError {
constructor(errorCode) {
super(errorCode, ClientConfigurationErrorMessages[errorCode]);
this.name = "ClientConfigurationError";
Object.setPrototypeOf(this, ClientConfigurationError.prototype);
}
}
function createClientConfigurationError(errorCode) {
return new ClientConfigurationError(errorCode);
}
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* @hidden
*/
class StringUtils {
/**
* Check if stringified object is empty
* @param strObj
*/
static isEmptyObj(strObj) {
if (strObj) {
try {
const obj = JSON.parse(strObj);
return Object.keys(obj).length === 0;
}
catch (e) { }
}
return true;
}
static startsWith(str, search) {
return str.indexOf(search) === 0;
}
static endsWith(str, search) {
return (str.length >= search.length &&
str.lastIndexOf(search) === str.length - search.length);
}
/**
* Parses string into an object.
*
* @param query
*/
static queryStringToObject(query) {
const obj = {};
const params = query.split("&");
const decode = (s) => decodeURIComponent(s.replace(/\+/g, " "));
params.forEach((pair) => {
if (pair.trim()) {
const [key, value] = pair.split(/=(.+)/g, 2); // Split on the first occurence of the '=' character
if (key && value) {
obj[decode(key)] = decode(value);
}
}
});
return obj;
}
/**
* Trims entries in an array.
*
* @param arr
*/
static trimArrayEntries(arr) {
return arr.map((entry) => entry.trim());
}
/**
* Removes empty strings from array
* @param arr
*/
static removeEmptyStringsFromArray(arr) {
return arr.filter((entry) => {
return !!entry;
});
}
/**
* Attempts to parse a string into JSON
* @param str
*/
static jsonParseHelper(str) {
try {
return JSON.parse(str);
}
catch (e) {
return null;
}
}
/**
* Tests if a given string matches a given pattern, with support for wildcards and queries.
* @param pattern Wildcard pattern to string match. Supports "*" for wildcards and "?" for queries
* @param input String to match against
*/
static matchPattern(pattern, input) {
/**
* Wildcard support: https://stackoverflow.com/a/3117248/4888559
* Queries: replaces "?" in string with escaped "\?" for regex test
*/
// eslint-disable-next-line security/detect-non-literal-regexp
const regex = new RegExp(pattern
.replace(/\\/g, "\\\\")
.replace(/\*/g, "[^ ]*")
.replace(/\?/g, "\\?"));
return regex.test(input);
}
}
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* Canonicalizes a URL by making it lowercase and ensuring it ends with /
* Inlined version of UrlString.canonicalizeUri to avoid circular dependency
* @param url - URL to canonicalize
* @returns Canonicalized URL
*/
function canonicalizeUrl(url) {
if (!url) {
return url;
}
let lowerCaseUrl = url.toLowerCase();
if (StringUtils.endsWith(lowerCaseUrl, "?")) {
lowerCaseUrl = lowerCaseUrl.slice(0, -1);
}
else if (StringUtils.endsWith(lowerCaseUrl, "?/")) {
lowerCaseUrl = lowerCaseUrl.slice(0, -2);
}
if (!StringUtils.endsWith(lowerCaseUrl, "/")) {
lowerCaseUrl += "/";
}
return lowerCaseUrl;
}
/**
* Parses hash string from given string. Returns empty string if no hash symbol is found.
* @param hashString
*/
function stripLeadingHashOrQuery(responseString) {
if (responseString.startsWith("#/")) {
return responseString.substring(2);
}
else if (responseString.startsWith("#") ||
responseString.startsWith("?")) {
return responseString.substring(1);
}
return responseString;
}
/**
* Returns URL hash as server auth code response object.
*/
function getDeserializedResponse(responseString) {
// Check if given hash is empty
if (!responseString || responseString.indexOf("=") < 0) {
return null;
}
try {
// Strip the # or ? symbol if present
const normalizedResponse = stripLeadingHashOrQuery(responseString);
// If # symbol was not present, above will return empty string, so give original hash value
const deserializedHash = Object.fromEntries(new URLSearchParams(normalizedResponse));
// Check for known response properties
if (deserializedHash.code ||
deserializedHash.ear_jwe ||
deserializedHash.error ||
deserializedHash.error_description ||
deserializedHash.state) {
return deserializedHash;
}
}
catch (e) {
throw createClientAuthError(hashNotDeserialized);
}
return null;
}
/**
* Utility to create a URL from the params map
*/
function mapToQueryString(parameters, encodeExtraParams = true, extraQueryParameters) {
const queryParameterArray = new Array();
parameters.forEach((value, key) => {
if (!encodeExtraParams &&
extraQueryParameters &&
key in extraQueryParameters) {
queryParameterArray.push(`${key}=${value}`);
}
else {
queryParameterArray.push(`${key}=${encodeURIComponent(value)}`);
}
});
return queryParameterArray.join("&");
}
/**
* Normalizes URLs for comparison by removing hash, canonicalizing,
* and ensuring consistent URL encoding in query parameters.
* This fixes redirect loops when URLs contain encoded characters like apostrophes (%27).
* @param url - URL to normalize
* @returns Normalized URL string for comparison
*/
function normalizeUrlForComparison(url) {
if (!url) {
return url;
}
// Remove hash first
const urlWithoutHash = url.split("#")[0];
try {
// Parse the URL to handle encoding consistently
const urlObj = new URL(urlWithoutHash);
/*
* Reconstruct the URL with properly decoded query parameters
* This ensures that %27 and ' are treated as equivalent
*/
const normalizedUrl = urlObj.origin + urlObj.pathname + urlObj.search;
// Apply canonicalization logic inline to avoid circular dependency
return canonicalizeUrl(normalizedUrl);
}
catch (e) {
// Fallback to original logic if URL parsing fails
return canonicalizeUrl(urlWithoutHash);
}
}
var UrlUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
getDeserializedResponse: getDeserializedResponse,
mapToQueryString: mapToQueryString,
normalizeUrlForComparison: normalizeUrlForComparison,
stripLeadingHashOrQuery: stripLeadingHashOrQuery
});
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* Url object class which can perform various transformations on url strings.
*/
class UrlString {
get urlString() {
return this._urlString;
}
constructor(url) {
this._urlString = url;
if (!this._urlString) {
// Throws error if url is empty
throw createClientConfigurationError(urlEmptyError);
}
if (!url.includes("#")) {
this._urlString = UrlString.canonicalizeUri(url);
}
}
/**
* Ensure urls are lower case and end with a / character.
* @param url
*/
static canonicalizeUri(url) {
if (url) {
let lowerCaseUrl = url.toLowerCase();
if (StringUtils.endsWith(lowerCaseUrl, "?")) {
lowerCaseUrl = lowerCaseUrl.slice(0, -1);
}
else if (StringUtils.endsWith(lowerCaseUrl, "?/")) {
lowerCaseUrl = lowerCaseUrl.slice(0, -2);
}
if (!StringUtils.endsWith(lowerCaseUrl, "/")) {
lowerCaseUrl += "/";
}
return lowerCaseUrl;
}
return url;
}
/**
* Throws if urlString passed is not a valid authority URI string.
*/
validateAsUri() {
// Attempts to parse url for uri components
let components;
try {
components = this.getUrlComponents();
}
catch (e) {
throw createClientConfigurationError(urlParseError);
}
// Throw error if URI or path segments are not parseable.
if (!components.HostNameAndPort || !components.PathSegments) {
throw createClientConfigurationError(urlParseError);
}
// Throw error if uri is insecure.
if (!components.Protocol ||
components.Protocol.toLowerCase() !== "https:") {
throw createClientConfigurationError(authorityUriInsecure);
}
}
/**
* Given a url and a query string return the url with provided query string appended
* @param url
* @param queryString
*/
static appendQueryString(url, queryString) {
if (!queryString) {
return url;
}
return url.indexOf("?") < 0
? `${url}?${queryString}`
: `${url}&${queryString}`;
}
/**
* Returns a url with the