Microsoft-authentication-library-for-js: AADSTS9002327: Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests.

Created on 23 Oct 2020  路  9Comments  路  Source: AzureAD/microsoft-authentication-library-for-js

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

Library

Important: Please fill in your exact version number above, e.g. [email protected].

Framework

React

Description

I see some errors in our logs where users are getting "AADSTS9002327: Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests."

Sample correlation id: 6db502bf-7351-45b9-b6e8-0d868a5e52c6
Timestamp: 2020-10-22 23:45:45Z

Our app is a first party application, and I've set up safe rollout to make the reply urls be type: "SPA". Then I made sure to pass the safe rollout query params in all requests made by msal. Somehow there's still this error, I'm not sure what it means by "may only be redemeed via cross-origin requests"? I thought it is cross origin? (Our origin is ml.azure.com)

Error Message

AADSTS9002327: Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests.

Security

  • [ ] Is this issue security related?

Regression

  • [ ] Did this behavior work before?
    Version:

MSAL Configuration

    const publicClientApp = new PublicClientApplication({
      auth: {
        clientId: this.clientId,
        authority: this.authority,
        redirectUri: this.loginRedirectUri,
        postLogoutRedirectUri: this.postLogoutRedirectUri
      },
      cache: {
        cacheLocation: "localStorage",
        storeAuthStateInCookie: isIEOrOldEdge // https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/1188#issuecomment-634281307
      },
      system: {
        tokenRenewalOffsetSeconds: 60,
        iframeHashTimeout: 30000, // iframe is used to refresh the refresh_token as it has a 24h lifetime
        loggerOptions: {
          loggerCallback: MsalAuthContext.msalLoggerCallback,
          piiLoggingEnabled: false,
          logLevel: LogLevel.Verbose
        }
      }
    });
    const handleRedirectPromise = publicClientApp
      .handleRedirectPromise()
      .then(response => {
        this.account = response ? response.account : this.getAccount();
        if (!this.account) {
          CoreLogger.trackEvent(TelemetryEventName.Core_MSALAuthContext_login);
          this.publicClientApp.loginRedirect({
            scopes: this.scopes,
            authority: this.authority,
            extraQueryParameters: this.safeRolloutQueryParams
          });
        }
      })
      .catch(error => {
        if (error) {
          this.trackError(error);
        }
      });

Reproduction steps

Not sure how to repro

Expected behavior

No errors

Browsers/Environment

  • [x] Chrome
  • [ ] Firefox
  • [ ] Edge
  • [ ] Safari
  • [ ] IE
  • [ ] Other (Please add browser name here)
bug

Most helpful comment

It might help or (probably) not. I ended up in this thread because I got the same error:

Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests.

and solved the problem.

I'm NOT using MSAL.

I have a custom test webclient that I use to test multiple oAuth flows (implicit, pkce, auth_code, etc.).

I got this error precisely when the PKCE flows tries to refresh the token using the provided refresh_token. My problem was that the code was running serverside (NodeJS app) instead from being executed from the browser.

That was working with another oAuth provider, but not with Azure:

From NodeJs code:

const payload: any = {
   grant_type: 'refresh_token',
   client_id: <clientid>,
   refresh_token: <refresh_token_from_body_test_field>
;

const payloadStr: string = querystring.stringify(payload);

const post_options = {
    host: login.microsoftonline.com,
    port: 443,
    path: `'/${tenantID}/oauth2/v2.0/token'`,
    method: POST,
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
        'Content-Length': payloadStr.length
    }
};

// sent using https.request method -> got the error

Then, I moved the code to run directly in the browser (where PKCE flow should be anyway) using an IFrame, and my token is now refreshed without error.

    <script type="text/javascript">
        const payload = {
            grant_type: 'refresh_token',
            client_id: '$<clientId>',
            refresh_token: '$<refreshToken>'
        };

        const xhr = new XMLHttpRequest();
        xhr.open('POST', '$<endpoint>');
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');

        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                window.sessionStorage['token'] = xhr.responseText;
                document.location.replace('/');
            }
        };
        xhr.onerror = e => {
            console.log('error', e);
        };
        xhr.send(Object.keys(payload).map(key => key + '=' + payload[key]).join('&'));
    </script>

All 9 comments

This is thrown by the server in some cases where the expected headers are missing. Following offline with @thoo1 for a repro to check why this may happen.

I am having the same issue with a Single Tenant Application using PublicClientApplication

It might help or (probably) not. I ended up in this thread because I got the same error:

Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests.

and solved the problem.

I'm NOT using MSAL.

I have a custom test webclient that I use to test multiple oAuth flows (implicit, pkce, auth_code, etc.).

I got this error precisely when the PKCE flows tries to refresh the token using the provided refresh_token. My problem was that the code was running serverside (NodeJS app) instead from being executed from the browser.

That was working with another oAuth provider, but not with Azure:

From NodeJs code:

const payload: any = {
   grant_type: 'refresh_token',
   client_id: <clientid>,
   refresh_token: <refresh_token_from_body_test_field>
;

const payloadStr: string = querystring.stringify(payload);

const post_options = {
    host: login.microsoftonline.com,
    port: 443,
    path: `'/${tenantID}/oauth2/v2.0/token'`,
    method: POST,
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
        'Content-Length': payloadStr.length
    }
};

// sent using https.request method -> got the error

Then, I moved the code to run directly in the browser (where PKCE flow should be anyway) using an IFrame, and my token is now refreshed without error.

    <script type="text/javascript">
        const payload = {
            grant_type: 'refresh_token',
            client_id: '$<clientId>',
            refresh_token: '$<refreshToken>'
        };

        const xhr = new XMLHttpRequest();
        xhr.open('POST', '$<endpoint>');
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');

        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                window.sessionStorage['token'] = xhr.responseText;
                document.location.replace('/');
            }
        };
        xhr.onerror = e => {
            console.log('error', e);
        };
        xhr.send(Object.keys(payload).map(key => key + '=' + payload[key]).join('&'));
    </script>

^ makes sense,
From the last time @sameerag and I debugged, I think it is because the "Origin" header (which most browsers add) was missing from the request
In my case I don't know why its missing

Adding Origin header works! Thank you @simardo

I'm getting this in Angular using "@azure/msal-browser": "^2.5.2", but I can't find where to modify the request headers to add Origin. Can you provide a bit more detail? Thanks

@zapap I am no using msal and also not using Angular. All frameworks / libraries should have a way to modify headers.

@alur222. Thanks, I got it working in Angular and @azure/msal-browser 2.5.2.
I was receiving this error when trying to make requests to Azure DevOps Feeds, but I didn't configure the correct scope for those endpoints.
I needed these endpoints scopes:

protectedResourceMap.set('https://app.vssps.visualstudio.com/', ['vso.packaging_manage']);
protectedResourceMap.set('https://feeds.dev.azure.com', ["499b84ac-1321-427f-aa17-267ca6975798/user_impersonation"]

Looks like adding Origin headers resolved this issue. Closing.

Was this page helpful?
0 / 5 - 0 ratings