2
votes

I've got a single page app that authenticates users in Azure using adal-angular.js/adal.js [client].
The returned token is inserted into the auth header and passed to a web API [server]. This web api generates a new access token for the app using the on-behalf-of workflow (https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof) This token is then used to call a downstream API [API1]. So the downstream API then repeats this process to get a new token to call another API [API2]. It's at this point that I'm getting the above error.

The aud value in the token passed from [client] to [server] is the application id of the [server] app. The aud value in the token passed from the [server] to [API1] is the Application URI of the [API1] app. So far so good.

When I call AcquireTokenAsync in [API1] app, I get the following error:

AADSTS70002: Error validating credentials. AADSTS50013: Assertion audience claim does not match the required value. The audience in the assertion was 'http://application_uri.com/' and the expected audience is 'snip-a1d5-e82e84f4e19e' or one of the Application Uris of this application with App ID 'snip-a1d5-e82e84f4e19e'

The relevant code from [API1]:

public static async Task<string> GetApplicationTokenOnBehalfOfUser(string appId, string appKey)
    {
        var clientCredential = new ClientCredential(appId, appKey);
        var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as
                System.IdentityModel.Tokens.BootstrapContext;
        var userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
        var userAccessToken = bootstrapContext.Token;
        var userAssertion = new UserAssertion(userAccessToken, _assertionType, userName);
        var authority = string.Format(System.Globalization.CultureInfo.InvariantCulture, _aadInstance, _tenant);

        var userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        var authContext = new AuthenticationContext(authority, new TokenCache());

        var result = await authContext.AcquireTokenAsync(_resourceId, clientCredential, userAssertion);
        var accessToken = result.AccessToken;
        return accessToken;
    }

Where: appId = "snip-a1d5-e82e84f4e19e"

And the "aud" value from the BootstrapContext.Token is: "aud": "http://application_uri.com/"

If I change the above to use the "aud" value from the token as the appId in the ClientCredential, I get this error instead:

AADSTS65001: The user or administrator has not consented to use the application with ID 'http://application_uri.com/'. Send an interactive authorization request for this user and resource.

Am I doing this right? Thanks.

2

2 Answers

0
votes

AADSTS70002: Error validating credentials. AADSTS50013: Assertion audience claim does not match the required value. The audience in the assertion was 'http://application_uri.com/' and the expected audience is 'snip-a1d5-e82e84f4e19e' or one of the Application Uris of this application with App ID 'snip-a1d5-e82e84f4e19e'

To use the on-behalf-of flow, we need to provide the access token for the API1 and provide the clientId and secrect of API1 to request the access token for the API2.

AADSTS65001: The user or administrator has not consented to use the application with ID 'http://application_uri.com/'. Send an interactive authorization request for this user and resource.

Before that tenant users can use the app, the corresponding service principal must be register to that tenant first by permission grant. Is API2 is not in the tenant of the users sign-in?

If I understand correctly, we need to specify the knownClientApplications in the manifest of API1(http://application_uri.com/') with the client_id of your SPA, and it also require to set the permission of API1 to the SPA. After that, when the users sign-in your SPA, the API1 app will also register to the users' tenant.

More detail about multi-tier applications please refer the document below:

How to sign in any Azure Active Directory (AD) user using the multi-tenant application pattern

Update( append the test result to explain)

enter image description here

-1
votes

To get this working I had to add the following delegated permissions to API1 for AP2. Azure Permissions