17

I have a standard Web API running on an Azure website with Azure AD authentication enabled, when browsing to the API in a browser I am able to login via the browser and gain access to the API.

The WPF desktop application however is receiving an Unauthorized response when submitting the request:

var authContext = new AuthenticationContext(authority, new FileCache()); var accessToken = await authContext.AcquireTokenAsync(apiResourceid, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto)); // accessToken is valid var apiUrl = "https://example.azurewebsites.net/api/list"; var request = new HttpRequestMessage(HttpMethod.Get, apiUrl); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.AccessToken); var response = await httpClient.SendAsync(request); 

The authentication is successfull and I can see the User info when debugging.

I do not have access to the Azure account but am confident the Service AD application is configured correctly to allow access to the Client AD application as when testing on an alternate account (not configured correctly) the AuthenticationContext.AcquireTokenAsync method was failing.

I did notice that the AuthenticationResult.ExpiresOn is always in the past but see no way of extending it, should this be a future date? - (Time is of course UTC)

Request:

GET https://example.azure websites.net/api/categorisation HTTP/1.1 Authorization: Bearer eyJ0eXAiO... Host: example.azurewebsites.net 

Response:

HTTP/1.1 401 Unauthorized Content-Length: 58 Content-Type: text/html Server: Microsoft-IIS/8.0 WWW-Authenticate: Bearer realm="example.azurewebsites.net" X-Powered-By: ASP.NET Set-Cookie: ARRAffinity=e35f2977dba55e6708887e762940f75c2a0fcb0a9df4e1cbe0d3f10a614c59b8;Path=/;Domain=example.azurewebsites.net Date: Fri, 08 Jul 2016 07:51:13 GMT You do not have permission to view this directory or page. 

Update:

I have recreated the environment in an Azure account I have access to and still receive an Unauthorised response (works fine in a browser).

5
  • Can you post the code in your websites Startup.Auth.cs setting up Azure AD auth? Or if you are using the "Authentication / Authorization" option in Azure Websites, can you share the values/settings you configured? Commented Jul 11, 2016 at 2:12
  • Also, on this: "The authentication is successfull and I can see the User info when debugging.", are you saying that when running the WPF application with Visual Studio you successfully connect to the API but when running from the exe it doesn't? If so, do you get prompted at all when you run the .exe? Commented Jul 11, 2016 at 2:16
  • @Saca the API is using the Azure Websites Authentication with. The Provider is "Azure Active Directory" which is configured using Express Management Mode, the Azure AD App is set to the AD Web Service application. Commented Jul 11, 2016 at 8:58
  • @Saca unfortunately the API request always receives 401 when debugging or running the exe. In both cases the AcquireToken is successful. Commented Jul 11, 2016 at 9:03
  • Using a code example from Pluralsight configured to use my Azure AD is working locally but when I deploy to Azure (and disable the automatica Authentication) the API is innaccessible to the Client application. Commented Jul 11, 2016 at 11:09

6 Answers 6

5

The issue appears to be with the "Authentication / Authorization" option in Azure Websites, when enabled the Web Api will not accept requests using the Authentication header. Disabling the option and using the Owin library alongside Azure AD has provided the solution required.

Sign up to request clarification or add additional context in comments.

1 Comment

Was the same for me I created another project without web api and azure auth works out of the box
3

I know this is a few months old, but I wanted to throw out there what was causing this issue when I got it, and what I found out I could to do resolve it.

I had a site that I made that used SignalR. As I was developing I didn't secure the site, but when I went to secure the site with AzureAD I got the aforementioned error. The issue was that I had two startup classes, one in the application root, and one in App_Start. One was in the [applicationname].App_Start namespace, while one was in the App_Start namespace, and one was marked as the OWIN startup assembly.

My resolution was to remove the one in the App_Start folder, which was in the [appname].App_Start namespace, and add the proper SignalR and OWIN startup attributes to the one in the application root.

This solved my issue.

Hope this helps anyone else that runs into this!

Comments

2

I was also getting unauthorized errors and when obtaining a bearer token everything seemed to be working just fine.

My problem was in my resource id. It did not match my Azure-AD application's "App ID URI". I had an extra slash on the end when calling the AcquireTokenAsync method and I had entered it in Azure-AD without a slash.

// private string resourceId = "https://mywebsite.azurewebsites.net/"; // bad private string resourceId = "https://mywebsite.azurewebsites.net"; // good result = await authContext.AcquireTokenAsync(resourceId, clientId, redirectUri, new PlatformParameters(PromptBehavior.Never)); 

So, make sure that your resource id matches your Azure-AD application's "App ID URI" exactly.

Notes:

  • Every app service that is associated with Azure-AD has a corresponding Azure-AD application declaration of type Web app/API. This resource id is the "App ID URI" in the app service's Azure-AD application declaration.
  • My resource id just happens to be my web site URL, but it could have been anything. The point is to match your "APP ID URI" of the Azure-AD application your trying to access.

Comments

2

For me this was simply a case of using the wrong "secret" i.e. I accidentally used the SecretID instead of the value of the secret.

That was allowing me to get a code without an error message, but the code was not actually valid even though it looked like a proper code, and all I got back was the infamous 401 without a clue as to why it was happening.

Comments

1

Just my 5 cents. A bit late but if this helps somebody, awesome.

The issue for me was: Not sending Scopes properly along with the request.

Background: localhost node server using the official graph-api quickstart repo. REST API-server - app service running on azure, with Auth. (Express mode) enabled.

I made one critical mistake, and took way too long to figure it out. I was attempting to call the API with wrong access token.

It was possible to call the GRAPH API with just "openid", "profile" etc. scopes.

But to access the web API, I had to make the scopes include the API url Scopes = "https://yourwebsiteurl.com/allowed_scope" and not only "allowed_scope". Even the Application ID URI using the scope as "Application ID URI"/allowed_scope would not work, unless "Application ID URI" is the API url.

Azure throws a clear error if you attempt to call the API with a scope that does not exists or such, but in this case if you don't include the real API url within the scope - the error is just 401, nothing else.

The "Application ID URI" configuration in Azure actually does not seem to make difference, seems like it can be pretty much anything. - while the API call scope must include the whole API url.

1 Comment

Thank you!! I have been stuck for days (weeks?) The QuickStart/tutorial/code sample documentation is very inaccurate with regards to scopes. For me I had to add the "Impersonation" scope into AcquireTokenInteractive(scopes), which can be copied from the 'API permissions' page of the Client App registration in the Azure AD panel (looks like api://{API_ClientId}/user_impersonation). Then GetTokenInteractive asked the user to allow the client to connect to the API on their behalf.
0

Spent hours trying to figure out what the issue was and normally when that happens it is something simple. Postman provides RestSharp C# code and if you are using HttpClient it is simply a formatting issue. Use:

var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer tokenValueLongStringHere); 

Using httpClient.DefaultRequestHeaders.Authorization did not work in my case.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.