I have an API application that works great with the Gateway host, and now that the host gateway is out of date, I'm trying to follow the Migration Guide . I redistributed my service using the 2.8.1 SDK and can log in to the service using a browser using AAD or a Microsoft account and use Swagger to test the service. However, I am trying to get the client to access the service using ClientId and Secret. The code can get an access token from AAD, but I always get a 401 error whenever I try to access one of the service resources.
When I debug a 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).
It seems that the problem is that the audience submitted with the request is https, but the validParameters.ValidAudiences collection contains only http.
I don't see any way to set up Audience, and it looks like an http-based audience is setting up when Visual Studio 2015 creates the App service. Is there a way to manually edit 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; }
source share