10

I have an ASP.Net Web API 2 on which I implemented the following security: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-devquickstarts-webapi-dotnet

It worked, I can't access the controllers except if I remove the [Authorize] attribute.

Now, I have a logged in user in a Xamarin app. The user is logged in via MSAL authentication which works fine too. Very basic implementation :

var authenticationResult = await App.IdentityClientApp.AcquireTokenSilentAsync(App.ClientScope);
var token = authenticationResult.Token;

Now, I want to access the web API by giving the MSAL authentication token in the DefaultRequestHeaders with something like this :

this.httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

Is there anyway this is possible ? How can I use this token to make my user consume my web API ?

Thank you !

Pierre P.
  • 890
  • 1
  • 18
  • 41

1 Answers1

14

The tutorial Help protect a web API by using bearer tokens from Azure AD you mentioned targets on AD v1.0 and you need to register your apps on Azure Portal. While MSAL targets on AD v2.0 and you need to register your app at apps.dev.microsoft.com, and you need to use the middleware in your Web API 2 as follows:

var tvps = new TokenValidationParameters
{
    ValidAudience = clientId,
    ValidateIssuer = false,
};

app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
    AccessTokenFormat = new Microsoft.Owin.Security.Jwt.JwtFormat(tvps, new OpenIdConnectCachingSecurityTokenProvider("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"))
});

For more details, you could refer to active-directory-v2-devquickstarts-dotnet-api.

Additionally, you could refer to AppModelv2-WebAPI-DotNet for code samples about the web api backend and the mobile client via MSAL accessing the web api backend.

Update:

  • I downloaded the code sample AppModelv2-WebAPI-DotNet

  • Follow How to register an app with the v2.0 endpoint for registering my app for v2.0 as follows:

    enter image description here

  • Copy the Application Id from the above screenshot and update it to TodoListClient and TodoListService project as follows:

    enter image description here

  • Launch TodoListService first, then you could debug TodoListService as follows:

    enter image description here

Also, you could copy the Token and leverage postman to simulate the request as follows:

enter image description here

Bruce Chen
  • 18,207
  • 2
  • 21
  • 35
  • Thank you for the answer, I did use the sample project as a guide to implement the way you described. I'll mark your answer as soon as I get another message than "{"$id":"1","Message":"Authorization has been denied for this request."}". Thanks ! – Pierre P. Jun 08 '17 at 14:13
  • Thank you very much for the complete update ! I'm currently trying to get this working on my project now that it worked on the sample. – Pierre P. Jun 12 '17 at 13:57
  • Thank you for your time. I'm facing a problem where I don't hit my controllers and just get 401 errors instantly when trying to contact my API. Any insight about this ? Thank you again. EDIT : Posted another question. Not sure both are related though https://stackoverflow.com/questions/44516351/cant-connect-to-https-on-web-api-from-xamarin-forms-app – Pierre P. Jun 13 '17 at 08:59
  • As I known, the api side would validate the audience (clientId) from the bearer token sent by the client, you could use https://jwt.io/ to decode the token and check with it. Since the core code is provided by the code sample and it could work as expected, for you project you could open a new question and provide your code snippet or sample project for reproducing this issue if possible. – Bruce Chen Jun 13 '17 at 09:13
  • I would check with your new question. – Bruce Chen Jun 13 '17 at 09:15
  • I've tried to create a new app, but it seems like the API has changed from the alpha to the preview versions...for instance, you can't pass the client id as a scope (what should I pass here?) – Luis Abreu Nov 10 '17 at 14:36
  • Ok, fixed it. Anyone knows if there's a way of getting the user name filled without having to implement the OAuthBearerAuthenticationProvider.OnValidateIdentity method? Currently, I'm using the event to fill the name claim of the ticket's identity... – Luis Abreu Nov 10 '17 at 15:07
  • I'm not able to find the class OpenIdConnectCachingSecurityTokenProvider – aj go Apr 30 '22 at 00:46