Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

401 error when authenticating to an Azure API App using AAD

I have an API app that has been working fine with a Gateway Host and now that the gateway host is being deprecated I'm trying to follow the Migration Guide. I've redeployed my service using the 2.8.1 SDK and can log into the service with a browser using AAD or a Microsoft account and use Swagger to test the service. However, I'm trying to get a client to access the service using a ClientId and Secret. The code is able to get the access token from AAD but I always get a 401 error whenever I try to access one of the service resources.

When I debug the service I see the following in the log:

Microsoft.Azure.AppService.Authentication Verbose: 0 : Received request: GET https://[myService].azurewebsites.net/api/[myResource]
Microsoft.Azure.AppService.Authentication Warning: 0 : JWT validation failed: IDX10214: Audience validation failed. Audiences: 'https://[myService].azurewebsites.net/'. Did not match:  validationParameters.ValidAudience: '[AAD ClientId]' or validationParameters.ValidAudiences: 'http://[myService].azurewebsites.net'.
Microsoft.Azure.AppService.Authentication Information: 0 : Sending response: 401.71 Unauthorized
The thread 0x3b00 has exited with code 0 (0x0).

What appears to be the issue is that the Audience presented with the request is https but the validParameters.ValidAudiences collection only contains http.

I can't see any way of configuring the Audience and it appears that the http based audience is being set when Visual Studio 2015 creates the App Service. Is there a way of manually editing the ValidAudience collection?

For reference my client code is:

    private static void Main(string[] args)
    {
        string app_id_url = "https://[myService].azurewebsites.net/";
        string authority = "https://login.windows.net/[myDirectory].onmicrosoft.com/";
        string clientId = "[AAD ClientId]";
        string clientSecret = "[AAD Client Secret]";
        string apiBaseUrl = "https://[myService].azurewebsites.net/";

        string aadToken = GetTokenForApplication(authority, clientId, clientSecret, app_id_url);

        var apiClient = new HttpClient { BaseAddress = new Uri(apiBaseUrl) };
        apiClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", aadToken);
        var apiResponse = apiClient.GetAsync(apiBaseUrl + @"api/[myResource]").Result;
        string apiResponseContent = apiResponse.Content.ReadAsStringAsync().Result;
        Console.WriteLine(apiResponseContent);
    }

    public static string GetTokenForApplication(string authority, string clientId, string clientSecret, string resourceUrl)
    {
        AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
        ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
        AuthenticationResult authenticationResult = authenticationContext.AcquireToken(resourceUrl, clientCred);
        string token = authenticationResult.AccessToken;
        return token;
    }
like image 361
Graeme Wilson Avatar asked Dec 16 '15 17:12

Graeme Wilson


People also ask

How do I enable Azure AD connect pass through authentication?

Sign in to the Azure Active Directory admin center with the global administrator credentials for your tenant. Select Azure Active Directory in the left pane. Select Azure AD Connect. Verify that the Pass-through authentication feature appears as Enabled.

What authentication protocols does aad support?

Azure AD supports many standardized protocols for authentication and authorization, such as SAML 2.0, OpenID Connect, OAuth 2.0, and WS-Federation. Azure AD also supports password vaulting and automated sign-in capabilities for apps that only support forms-based authentication.


1 Answers

Your problem have something to do with the valid audiences. You may have 2 choices:

Option 1. Try to acquire the token with the WebAPI client ID as the AcquireToken method 'resource' parameter, instead of its Uri.

Option 2. If the previous method didn't work, you should have to modify the authentication settings of the App Service API, using Azure Resources Explorer. Navigate to your web API, find the authSettings JSON document under the config node, and modify (after having changed to Read/Write mode) the array allowedAudiences to match your needs. In your case you may have to change http to https

like image 192
Loul G. Avatar answered Sep 25 '22 21:09

Loul G.