Skip to content
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

MSAL-Browser 2.0.1: Incorrectly deserializes URL Hash resulting In 'platformStateObj is null' exception #2118

Closed
3 of 13 tasks
wdspider opened this issue Aug 8, 2020 · 3 comments · Fixed by #2129
Closed
3 of 13 tasks
Labels
bug A problem that needs to be fixed for the feature to function as intended. msal-browser Related to msal-browser package

Comments

@wdspider
Copy link

wdspider commented Aug 8, 2020

Please follow the issue template below. Failure to do so will result in a delay in answering your question.

Library

  • msal@1.x.x or @azure/msal@1.x.x
  • @azure/msal-browser@2.0.1
  • @azure/msal-angular@0.x.x
  • @azure/msal-angular@1.x.x
  • @azure/msal-angularjs@1.x.x

Important: Please fill in your exact version number above, e.g. msal@1.1.3.

Framework

TypeScript / React / Material UI

Description

MSAL redirects to AD B2C fine which returns back to the app as expected. However, MSAL is not processing the url hash properly. The problem seems to lie within this method:

PublicClientApplication.prototype.getRedirectResponseHash = function () {
        // Get current location hash from window or cache.
        var hash = window.location.hash;
        var isResponseHash = UrlString.hashContainsKnownProperties(hash);
        var cachedHash = this.browserStorage.getItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.URL_HASH), CacheSchemaType.TEMPORARY);
        this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.URL_HASH));
        var responseHash = isResponseHash ? hash : cachedHash;
        if (responseHash) {
            // Deserialize hash fragment response parameters.
            var serverParams = UrlString.getDeserializedHash(responseHash);
            var platformStateObj = BrowserProtocolUtils.extractBrowserRequestState(this.browserCrypto, serverParams.state);
            if (platformStateObj.interactionType !== InteractionType.REDIRECT) {
                return null;
            }
            else {
                BrowserUtils.clearHash();
                return responseHash;
            }
        }
        return null;
    };

particularly, these two lines:

            var serverParams = UrlString.getDeserializedHash(responseHash);
            var platformStateObj = BrowserProtocolUtils.extractBrowserRequestState(this.browserCrypto, serverParams.state);

The first line successfully deserializes the hash into this serverParams object:
image
However, the next line fails since serverParams.state is undefined. As you can see in the above screenshot, the object key is actually #state.

Error Message

image

Security

  • Is this issue security related?

Regression

  • Did this behavior work before?
    Version:

MSAL Configuration

import {
    Configuration,
    LogLevel,
    PublicClientApplication,
    AccountInfo,
    RedirectRequest,
    EndSessionRequest,
    AuthenticationResult,
} from '@azure/msal-browser';

const msalConfig: Configuration = {
    auth: {
        clientId: 'myid',
        authority:
            'https://myauth.b2clogin.com/myauth.onmicrosoft.com/B2C_1_SignUpSignIn/',
        knownAuthorities: ['myauth.b2clogin.com'],
        redirectUri: `https://${window.location.host}/`,
    },
    cache: {
        cacheLocation: 'sessionStorage', // This configures where your cache will be stored
        storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
    },
    system: {
        loggerOptions: {
            loggerCallback: (level, message, containsPii) => {
                if (containsPii) {
                    return;
                }
                switch (level) {
                    case LogLevel.Error:
                        console.error(message);
                        return;
                    case LogLevel.Info:
                        console.info(message);
                        return;
                    case LogLevel.Verbose:
                        console.debug(message);
                        return;
                    case LogLevel.Warning:
                        console.warn(message);
                        return;
                }
            },
        },
    },
};

class AuthManager {
    private msal: PublicClientApplication;
    private loginRequest: RedirectRequest = {
        scopes: [],
        redirectStartPage: window.location.href,
    };

    private account?: AccountInfo;

    constructor() {
        this.msal = new PublicClientApplication(msalConfig);
    }

    public initialize(): void {
        this.msal
            .handleRedirectPromise()
            .then((response: AuthenticationResult | null) =>
                this.handleResponse(response ?? undefined),
            )
            .catch(console.error);
    }

    public getAccount(): AccountInfo | undefined {
        if (this.account !== undefined) {
            return this.account;
        }

        const currentAccounts = this.msal.getAllAccounts();
        if (currentAccounts?.length > 1) {
            this.account = currentAccounts[0];
        }

        return this.account;
    }
    public login(): void {
        this.msal.loginRedirect(this.loginRequest);
    }

    public logout(): void {
        const logoutRequest: EndSessionRequest = {
            account: this.account,
        };

        this.msal.logout(logoutRequest);
    }

    private handleResponse(response?: AuthenticationResult): void {
        this.account = response?.account ?? this.getAccount();
    }
}

const authManager = new AuthManager();
export { authManager as AuthManager };

window.addEventListener('load', () => {
    authManager.initialize();
});

Reproduction steps

// Provide relevant code snippets here.
// For Azure B2C issues, please include your policies.

Expected behavior

User is logged in without error.

Browsers/Environment

  • Chrome
  • Firefox
  • Edge
  • Safari
  • IE
  • Other (Please add browser name here)
@wdspider wdspider added the bug A problem that needs to be fixed for the feature to function as intended. label Aug 8, 2020
@vaughanh1
Copy link

vaughanh1 commented Aug 10, 2020

I had the typescript sample working nicely with 2.0.0 of msal-browser. Upgraded to 2.0.1 just now, and it breaks at the same lines mentioned.
I had similar issues with 2.0.0-beta.2. See here for the sample: https://github.com/pcibraro/msal-browser-react

When will there be a fix please?

@pkanher617
Copy link
Contributor

@wdspider @vaughanh1 Will try to fix this issue today. Thanks for opening this.

@hectormmg hectormmg added the msal-browser Related to msal-browser package label Aug 11, 2020
@pkanher617 pkanher617 linked a pull request Aug 11, 2020 that will close this issue
@wdspider
Copy link
Author

Is there a rough eta on when 2.0.2 will be released?

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug A problem that needs to be fixed for the feature to function as intended. msal-browser Related to msal-browser package
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants