6
votes

I'm currently setting up ADD with MSAL for my app. The issue I am running into is that the api is set to accept Azure AD V1 tokens, but with my current MSAL setup I keep receiving an Azure AD V2.

Other people in my team are using ADAL, but we want to migrate to MSAL. I'm sure I'm doing something wrong, as it seems hard to believe there is no backwards compatibility.

This is my Msal Config:

import * as Msal from 'msal';

export const applicationConfig = {
    clientID: process.env.REACT_APP_MSAL_CLIENT_ID,
    authority: process.env.REACT_APP_AUTHORITY_TENANT,
    graphScopes: ['user.read'],
    graphEndpoint: process.env.REACT_APP_GRAPH_ENDPOINT,
};

/**
 * will get the call back once the API is complete
 * (either complete or failure), redirects flows.
 * Is called after the authentication request is completed
 * successfully/failure
 *
 * @param {*} errorDesc
 * @param {*} token
 * @param {*} error
 * @param {*} tokenType
 */
const tokenReceivedCallback = async (errorDesc, token, errorMsg) => {
    try {
        if (token) console.log('Success!');
    } catch (error) {
        throw new Error(`${errorMsg}:${errorDesc}`);
    }
};

/**
 * Instantiate UserAgentApplication
 */
const userAgentApplication = new Msal.UserAgentApplication(
    applicationConfig.clientID,
    applicationConfig.authority,
    tokenReceivedCallback,
    {
        cacheLocation: process.env.REACT_APP_CACHE_LOCATION,
        redirectUri: process.env.REACT_APP_REDIRECT_URI,
    },
);

/**
 * Log user in
 * Checks if there is no user and if there is no
 * callback occuring within the window url which throws into
 * infinite loop, then login, and redirect to SSO login
 * @param {*} graphScopes
 */
export const signIn = async graphScopes => {
    console.log(graphScopes);
    /**
     * avoid duplicate code execution on page load in case of iframe and popup window
     */
    if (!userAgentApplication.getUser() && !userAgentApplication.isCallback(window.location.hash)) {
        /**
         * login site, and go directly to SSO
         */
        await userAgentApplication.loginRedirect(graphScopes, process.env.REACT_APP_DOMAIN);
        /**
         * acquireTokenSilent method makes a silent request to ADD to obtain an access token.
         * ADD returns an access token containing the user consented scopes to allow
         * the app to securely call the api
         */
        await userAgentApplication.acquireTokenSilent(graphScopes);
    }
};

/**
 * Logs user out
 */
export const logOut = () => userAgentApplication.logout();

This is what I get when I use jwt.ms: enter image description here

Thanks in advance!

1
Aren't those scopes for Graph API and not your API? Where do you request a token for your API?juunas
hi @juunas thanks for your quick reply. I'm not sure I follow the first part of your question. The scopes are intended for the graphAPI I think, loginRedirect() belongs to the MSAL() object. I request my token from graph.windowsaromanarguello
You are requesting an access token for Graph API. That is not your API so it does not respect your token version settings. You need to change the scopes to match your API's identifier.juunas
github.com/AzureAD/microsoft-authentication-library-for-dotnet/… shows you some examples. You would normally use the app id URI + /.default or some specific scopes. I can't remember if it was different if you want to use the same app registration for the client and API.juunas
You can create an app id URI from the Azure portal if one doesn't already exist for the APIjuunas

1 Answers

6
votes

Yes, it is possible to request an V1 access token from the V2 endpoint. The type of access token (v1 or v2) that is issued to your client application is determined by the application registration of the resource API. As others point out, your example code requests a Microsoft Graph scope and the Microsoft Graph app registration is configured to accept v2 tokens. You can determine what type of tokens your API is configured to accept by looking at the app registration. In portal.azure.com, open "App registrations (Preview)", go to the "Manifest" section, and look for the property "accessTokenAcceptedVersion". If it is set to null or 1, then all client applications requesting access tokens to call this resource will get a v1 access token (regardless if they use MSAL or ADAL to request the access token).

A common calling pattern for an ADAL app calling v1 resource API was to provide the resource URI as the scope. This told the endpoint to issue an access token for all of the permissions configured in the app registration of the resource API. MSAL (which uses the v2 endpoint) allows for requesting any scope regardless if it's in the static list of scopes of the app registration for a resource. To get the same behavior as ADAL (which uses the v1 endpoint), append ".default" to the resource URI (e.g. "https://contoso.onmicrosoft.com/V1TodoListService/.default")

At Ignite, I gave a demo of an existing to-do-list service that accepts only v1 access tokens, and I walk through the entire portal configuration of my new MSAL client application to request v1 access tokens and call this service. Watch it here: https://youtu.be/77A47CfNqIU?t=3120