Skip to content

Standalone functions in PCA #7810

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: msal-v5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Standalone functions in PCA #7810",
"packageName": "@azure/msal-browser",
"email": "[email protected]",
"dependentChangeType": "patch"
}
314 changes: 163 additions & 151 deletions lib/msal-browser/src/interaction_client/BaseInteractionClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,168 +85,180 @@ export abstract class BaseInteractionClient {
abstract logout(
request: EndSessionRequest | ClearCacheRequest | undefined
): Promise<void>;
}

protected async clearCacheOnLogout(
account?: AccountInfo | null
): Promise<void> {
if (account) {
if (
AccountEntityUtils.accountInfoIsEqual(
account,
this.browserStorage.getActiveAccount(),
false
)
) {
this.logger.verbose("Setting active account to null");
this.browserStorage.setActiveAccount(null);
}
// Clear given account.
try {
this.browserStorage.removeAccount(
AccountEntityUtils.generateAccountCacheKey(account),
this.correlationId
);
this.logger.verbose(
"Cleared cache items belonging to the account provided in the logout request."
);
} catch (error) {
this.logger.error(
"Account provided in logout request was not found. Local cache unchanged."
);
}
} else {
try {
this.logger.verbose(
"No account provided in logout request, clearing all cache items.",
this.correlationId
);
// Clear all accounts and tokens
this.browserStorage.clear(this.correlationId);
// Clear any stray keys from IndexedDB
await this.browserCrypto.clearKeystore();
} catch (e) {
this.logger.error(
"Attempted to clear all MSAL cache items and failed. Local cache unchanged."
);
}
}
}
/**
*
* Use to get the redirect uri configured in MSAL or null.
* @param requestRedirectUri
* @returns Redirect URL
*
*/
export function getRedirectUri(
requestRedirectUri?: string,
clientConfig?: BrowserConfiguration,
logger?: Logger
): string {
logger?.verbose("getRedirectUri called");
const redirectUri =
requestRedirectUri || clientConfig?.auth.redirectUri || "";
return UrlString.getAbsoluteUrl(redirectUri, BrowserUtils.getCurrentUri());
}

/**
*
* Use to get the redirect uri configured in MSAL or null.
* @param requestRedirectUri
* @returns Redirect URL
*
*/
getRedirectUri(requestRedirectUri?: string): string {
this.logger.verbose("getRedirectUri called");
const redirectUri = requestRedirectUri || this.config.auth.redirectUri;
return UrlString.getAbsoluteUrl(
redirectUri,
BrowserUtils.getCurrentUri()
);
}
/**
*
* @param apiId
* @param correlationId
* @param forceRefresh
*/
export function initializeServerTelemetryManager(
apiId: number,
config: BrowserConfiguration,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the whole config here or can we just pass in the clientId?

correlationId: string,
browserStorage: BrowserCacheManager,
logger?: Logger,
forceRefresh?: boolean
): ServerTelemetryManager {
logger?.verbose("initializeServerTelemetryManager called");
const telemetryPayload: ServerTelemetryRequest = {
clientId: config.auth.clientId,
correlationId: correlationId,
apiId: apiId,
forceRefresh: forceRefresh || false,
wrapperSKU: browserStorage.getWrapperMetadata()[0],
wrapperVer: browserStorage.getWrapperMetadata()[1],
};

/**
*
* @param apiId
* @param correlationId
* @param forceRefresh
*/
protected initializeServerTelemetryManager(
apiId: number,
forceRefresh?: boolean
): ServerTelemetryManager {
this.logger.verbose("initializeServerTelemetryManager called");
const telemetryPayload: ServerTelemetryRequest = {
clientId: this.config.auth.clientId,
correlationId: this.correlationId,
apiId: apiId,
forceRefresh: forceRefresh || false,
wrapperSKU: this.browserStorage.getWrapperMetadata()[0],
wrapperVer: this.browserStorage.getWrapperMetadata()[1],
};

return new ServerTelemetryManager(
telemetryPayload,
this.browserStorage
);
}
return new ServerTelemetryManager(telemetryPayload, browserStorage);
}

/**
* Used to get a discovered version of the default authority.
* @param params {
* requestAuthority?: string;
* requestAzureCloudOptions?: AzureCloudOptions;
* requestExtraQueryParameters?: StringDict;
* account?: AccountInfo;
* }
*/
protected async getDiscoveredAuthority(params: {
/**
* Used to get a discovered version of the default authority.
* @param params {
* requestAuthority?: string;
* requestAzureCloudOptions?: AzureCloudOptions;
* requestExtraQueryParameters?: StringDict;
* account?: AccountInfo;
* }
*/
export async function getDiscoveredAuthority(
params: {
requestAuthority?: string;
requestAzureCloudOptions?: AzureCloudOptions;
requestExtraQueryParameters?: StringDict;
account?: AccountInfo;
}): Promise<Authority> {
const { account } = params;
const instanceAwareEQ =
params.requestExtraQueryParameters &&
params.requestExtraQueryParameters.hasOwnProperty("instance_aware")
? params.requestExtraQueryParameters["instance_aware"]
: undefined;

const authorityOptions: AuthorityOptions = {
protocolMode: this.config.system.protocolMode,
OIDCOptions: this.config.auth.OIDCOptions,
knownAuthorities: this.config.auth.knownAuthorities,
cloudDiscoveryMetadata: this.config.auth.cloudDiscoveryMetadata,
authorityMetadata: this.config.auth.authorityMetadata,
};

// build authority string based on auth params, precedence - azureCloudInstance + tenant >> authority
const resolvedAuthority =
params.requestAuthority || this.config.auth.authority;
const resolvedInstanceAware = instanceAwareEQ?.length
? instanceAwareEQ === "true"
: this.config.auth.instanceAware;

const userAuthority =
account && resolvedInstanceAware
? this.config.auth.authority.replace(
UrlString.getDomainFromUrl(resolvedAuthority),
account.environment
)
: resolvedAuthority;

// fall back to the authority from config
const builtAuthority = Authority.generateAuthority(
userAuthority,
params.requestAzureCloudOptions ||
this.config.auth.azureCloudOptions
);
const discoveredAuthority = await invokeAsync(
AuthorityFactory.createDiscoveredInstance,
BrowserPerformanceEvents.AuthorityFactoryCreateDiscoveredInstance,
this.logger,
this.performanceClient,
this.correlationId
)(
builtAuthority,
this.config.system.networkClient,
this.browserStorage,
authorityOptions,
this.logger,
this.correlationId,
this.performanceClient
},
config: BrowserConfiguration,
correlationId: string,
performanceClient: IPerformanceClient,
browserStorage: BrowserCacheManager,
logger: Logger
): Promise<Authority> {
const { account } = params;
const instanceAwareEQ =
params.requestExtraQueryParameters &&
params.requestExtraQueryParameters.hasOwnProperty("instance_aware")
? params.requestExtraQueryParameters["instance_aware"]
: undefined;

const authorityOptions: AuthorityOptions = {
protocolMode: config.system.protocolMode,
OIDCOptions: config.auth.OIDCOptions,
knownAuthorities: config.auth.knownAuthorities,
cloudDiscoveryMetadata: config.auth.cloudDiscoveryMetadata,
authorityMetadata: config.auth.authorityMetadata,
};

// build authority string based on auth params, precedence - azureCloudInstance + tenant >> authority
const resolvedAuthority = params.requestAuthority || config.auth.authority;
const resolvedInstanceAware = instanceAwareEQ?.length
? instanceAwareEQ === "true"
: config.auth.instanceAware;

const userAuthority =
account && resolvedInstanceAware
? config.auth.authority.replace(
UrlString.getDomainFromUrl(resolvedAuthority),
account.environment
)
: resolvedAuthority;

// fall back to the authority from config
const builtAuthority = Authority.generateAuthority(
userAuthority,
params.requestAzureCloudOptions || config.auth.azureCloudOptions
);
const discoveredAuthority = await invokeAsync(
AuthorityFactory.createDiscoveredInstance,
BrowserPerformanceEvents.AuthorityFactoryCreateDiscoveredInstance,
logger,
performanceClient,
correlationId
)(
builtAuthority,
config.system.networkClient,
browserStorage,
authorityOptions,
logger,
correlationId,
performanceClient
);

if (account && !discoveredAuthority.isAlias(account.environment)) {
throw createClientConfigurationError(
ClientConfigurationErrorCodes.authorityMismatch
);
}

return discoveredAuthority;
}

if (account && !discoveredAuthority.isAlias(account.environment)) {
throw createClientConfigurationError(
ClientConfigurationErrorCodes.authorityMismatch
export async function clearCacheOnLogout(
browserStorage: BrowserCacheManager,
browserCrypto: ICrypto,
logger: Logger,
correlationId: string,
account?: AccountInfo | null
): Promise<void> {
if (account) {
if (
AccountEntityUtils.accountInfoIsEqual(
account,
browserStorage.getActiveAccount(),
false
)
) {
logger.verbose("Setting active account to null");
browserStorage.setActiveAccount(null);
}
// Clear given account.
try {
browserStorage.removeAccount(
AccountEntityUtils.generateAccountCacheKey(account),
correlationId
);
logger.verbose(
"Cleared cache items belonging to the account provided in the logout request."
);
} catch (error) {
logger.error(
"Account provided in logout request was not found. Local cache unchanged."
);
}
} else {
try {
logger.verbose(
"No account provided in logout request, clearing all cache items.",
correlationId
);
// Clear all accounts and tokens
await browserStorage.clear(correlationId);
// Clear any stray keys from IndexedDB
await browserCrypto.clearKeystore();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like something that should be handled by the clear function above. Thoughts?

} catch (e) {
logger.error(
"Attempted to clear all MSAL cache items and failed. Local cache unchanged."
);
}

return discoveredAuthority;
}
}
Loading