简体   繁体   中英

How can I use OWIN to authenticate with OpenID Connect directly with a token

I have an MVC web application that uses OWIN / openid connect to authenticate users with https://login.windows.net/common/ . It's based on the azure / office 365 sample here: https://github.com/OfficeDev/Research-Project-Code-Sample .

If I understand the authentication flow correctly it goes like this:

  1. the app checks (based on a cookie) if there is already an authenticated user
  2. if not, then it redirects to the providers authorization page (login.microsoftonline.com)
  3. the page redirects back to my app with an auth code
  4. My app calls the provider again with the auth code for an access token (or is it an id_token?)
  5. My app (the OWIN component) extracts the various openid properties and sets them on the threads current principal

That works fine.

Now I want my MVC application to call my Web API application. The Web API application is never called directly by the browser but always by the MVC client. The Web API application doesn't use cookies and can't redirect if a request is made with incorrect or stale authentication info. The Web API application should be able to be called with the authentication token that the MVC application got and use this to set a ClaimsPrincipal on the executing thread. An alternative might be for me to use some custom solution in the MVC app for encrypting the user info and sending it on to the Web API, but this would be a last resort. I would much prefer to use standard owin.

If you dig through the Azure samples, you'll find what you need. The key here is you want to use bearer tokens.

In Azure you need to create a new App for the WebApi side and setup a relationship with your client App. I was using the same app Id for my Client authentication and WebApi and that does not work.

On the Web Api side, you need to configure your authentication using Windows Azure Active Directory Bearer Authentication.

app.UseWindowsAzureActiveDirectoryBearerAuthentication(
    new WindowsAzureActiveDirectoryBearerAuthenticationOptions
    {
        TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters()
        {
            ValidAudience = ConfigurationManager.AppSettings["ida:AppApiResourceId"],
            SaveSigninToken = true
        },
        AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
        Tenant = ConfigurationManager.AppSettings["ida:Tenant"]
    });

You can get the token using bootstrap context from Identity. I was trying all sorts of riggish ways to get the token before a SO answer helped me get at that ( Acquiring an Access token by using JWT used for AzureBearerAuthentication ). Also note below that resourceId is the appId for the WebApi app.

if (identity == null || !identity.IsAuthenticated) return null;

AuthenticationResult authResult = null;

var context = identity.BootstrapContext as BootstrapContext;
var credential = new ClientCredential(AuthConfig.ClientId, AuthConfig.AppKey);
if (context != null && context.Token != null)
{
    authResult = authInfo.AuthContext.AcquireToken(resourceId, authInfo.Credential,
        new UserAssertion(context.Token));
}

return authResult;

When you create a request to the web api you need to send the bearer token in each request under the Authorization header.

headers["Authorization"] = "bearer " + token;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM