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:
Safia Abdalla 2020-12-10 10:30:23 -08:00 committed by GitHub
parent 1d2877ed33
commit f45bf46312
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 27 deletions

File diff suppressed because one or more lines are too long

View File

@ -101,8 +101,12 @@ class MsalAuthorizeService implements AuthorizeService {
scopes: scopes scopes: scopes
}; };
const response = await this._msalApplication.acquireTokenSilent(silentRequest); try {
return response.idTokenClaims; const response = await this._msalApplication.acquireTokenSilent(silentRequest);
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 {
const parsedUrl = new URL(url); let stateFromUrl;
const fromHash = parsedUrl.hash && parsedUrl.hash.length > 0 && new URLSearchParams(parsedUrl.hash.substring(1)); // Parse the state key from the `search` query parameter in the URL if provided
let state = fromHash && fromHash.getAll('state'); if (url) {
if (state && state.length > 1) { const parsedUrl = new URL(url);
return undefined; stateFromUrl = parsedUrl.searchParams && parsedUrl.searchParams.getAll('state');
} 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();
} }