Add error handling for token acquisition in getUser and fix state retrieval (#28498)
* Add error handling for token acquisition in getUser * Clean up fetching state key from URL
This commit is contained in:
parent
1d2877ed33
commit
f45bf46312
File diff suppressed because one or more lines are too long
|
|
@ -101,8 +101,12 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
scopes: scopes
|
scopes: scopes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
const response = await this._msalApplication.acquireTokenSilent(silentRequest);
|
const response = await this._msalApplication.acquireTokenSilent(silentRequest);
|
||||||
return response.idTokenClaims;
|
return response.idTokenClaims;
|
||||||
|
} catch (e) {
|
||||||
|
await this.signInCore(silentRequest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAccessToken(request?: AccessTokenRequestOptions): Promise<AccessTokenResult> {
|
async getAccessToken(request?: AccessTokenRequestOptions): Promise<AccessTokenResult> {
|
||||||
|
|
@ -224,10 +228,9 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
async completeSignIn() {
|
async completeSignIn() {
|
||||||
// Make sure that the redirect handler has completed execution before
|
// Make sure that the redirect handler has completed execution before
|
||||||
// completing sign in.
|
// completing sign in.
|
||||||
await this._redirectCallback;
|
var authenticationResult = await this._redirectCallback;
|
||||||
const account = this.getAccount();
|
if (authenticationResult) {
|
||||||
if (account) {
|
return authenticationResult;
|
||||||
return this.success(account);
|
|
||||||
}
|
}
|
||||||
return this.operationCompleted();
|
return this.operationCompleted();
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +256,7 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
const logoutStateId = sessionStorage.getItem(`${AuthenticationService._infrastructureKey}.LogoutState`);
|
const logoutStateId = sessionStorage.getItem(`${AuthenticationService._infrastructureKey}.LogoutState`);
|
||||||
const updatedUrl = new URL(url);
|
const updatedUrl = new URL(url);
|
||||||
updatedUrl.search = `?state=${logoutStateId}`;
|
updatedUrl.search = `?state=${logoutStateId}`;
|
||||||
const logoutState = await this.retrieveState(updatedUrl.href, /*isLogout*/ true);
|
const logoutState = await this.retrieveState(updatedUrl.href, null, /*isLogout*/ true);
|
||||||
|
|
||||||
sessionStorage.removeItem(`${AuthenticationService._infrastructureKey}.LogoutState`);
|
sessionStorage.removeItem(`${AuthenticationService._infrastructureKey}.LogoutState`);
|
||||||
|
|
||||||
|
|
@ -285,25 +288,22 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
return base64UrlIdentifier;
|
return base64UrlIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveState<T>(url: string, isLogout: boolean = false): Promise<T | undefined> {
|
retrieveState<T>(url: string | null, providedState: string | null = null, isLogout: boolean = false): T | undefined {
|
||||||
|
let stateFromUrl;
|
||||||
|
// Parse the state key from the `search` query parameter in the URL if provided
|
||||||
|
if (url) {
|
||||||
const parsedUrl = new URL(url);
|
const parsedUrl = new URL(url);
|
||||||
const fromHash = parsedUrl.hash && parsedUrl.hash.length > 0 && new URLSearchParams(parsedUrl.hash.substring(1));
|
stateFromUrl = parsedUrl.searchParams && parsedUrl.searchParams.getAll('state');
|
||||||
let state = fromHash && fromHash.getAll('state');
|
|
||||||
if (state && state.length > 1) {
|
|
||||||
return undefined;
|
|
||||||
} else if (!state || state.length == 0) {
|
|
||||||
state = parsedUrl.searchParams && parsedUrl.searchParams.getAll('state');
|
|
||||||
if (!state || state.length !== 1) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to calculate the state key in two different ways. The reason for it is that
|
// Chose the provided state from MSAL. Otherwise, choose the state computed from the URL
|
||||||
// msal.js doesn't support the state parameter on logout flows, which forces us to shim our own logout state.
|
const state = providedState || stateFromUrl;
|
||||||
// The format then is different, as msal follows the pattern state=<<guid>>|<<user_state>> and our format
|
|
||||||
// simple uses <<base64urlIdentifier>>.
|
if (!state) {
|
||||||
const appState = !isLogout ? this.getAccountState(state[0]) : state[0];
|
return undefined;
|
||||||
const stateKey = `${AuthenticationService._infrastructureKey}.AuthorizeService.${appState}`;
|
}
|
||||||
|
|
||||||
|
const stateKey = `${AuthenticationService._infrastructureKey}.AuthorizeService.${state}`;
|
||||||
const stateString = sessionStorage.getItem(stateKey);
|
const stateString = sessionStorage.getItem(stateKey);
|
||||||
if (stateString) {
|
if (stateString) {
|
||||||
sessionStorage.removeItem(stateKey);
|
sessionStorage.removeItem(stateKey);
|
||||||
|
|
@ -336,9 +336,9 @@ class MsalAuthorizeService implements AuthorizeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleResult(result: Msal.AuthenticationResult | null) {
|
private handleResult(result: Msal.AuthenticationResult | null) {
|
||||||
if (result != null) {
|
if (result) {
|
||||||
this._account = result.account;
|
this._account = result.account;
|
||||||
return this.success(result.state);
|
return this.success(this.retrieveState(null, result.state));
|
||||||
} else {
|
} else {
|
||||||
return this.operationCompleted();
|
return this.operationCompleted();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue