Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to share an Access Token between an MVC 5 web application and Web API 2 application

In this instance I am having the user log into the (MVC 5) Web application, which then acts as proxy to log into the (Web API 2) API (using basic over SSL) and return a Bearer/Access Token. I'm using the Thinktecture.IdentityModel.Client.OAuth2Client to handle the login and get the access token, which all works fine.

Some other stuff happens but now I want the Web application to be able to decode the Access Token to access the claims set on the API (specifically the user ID returned after login to the API).

I'm using the much demoed, UseOAuthAuthorizationServer and UseOAuthBearerAuthentication extension methods with a token endpoint pretty much out of the box but with a custom OAuthAuthorizationServerOptions.Provider to access my own repository.

I have the same MachineKey on both applications, but I am unclear how to decode the token , although I understand I would probably have to use the SecureDataFormat.Unprotect method.

The closest attempt I have in the Web application is:

Task<TokenResponse> response = client.RequestResourceOwnerPasswordAsync(model.Email, model.Password);

IDataProtector dataProtecter = Startup.DataProtectionProvider.Create("does this matter?");
TicketDataFormat ticketDataFormat = new TicketDataFormat(dataProtecter);
AuthenticationTicket ticket = ticketDataFormat.Unprotect(response.Result.AccessToken);

With the Startup.DataProtectionProvider set as follows:

public partial class Startup
{
    internal static IDataProtectionProvider DataProtectionProvider { get; private set; }

    public void Configuration(IAppBuilder app)
    {
        DataProtectionProvider = app.GetDataProtectionProvider();
        this.ConfigureAuth(app);
    }
}

My fall back plan is to offer an API method that returns the information I am interested in after login, but it seems excessive seeing as it forms part of the claims in the token (as I understand it).

I have tried to wrap my head around JWT (I've looked at Thinktecture, Microsoft source code and various other forums), but not sure if that would help (although claims being available in plain text us useful). I have yet to find an example that allows sign in with basic authentication and returns a custom JWT containing an access token.

Anyway I hope thats enoguh information and any help would be much appreciated... cheers

like image 861
teatime Avatar asked Aug 19 '14 18:08

teatime


People also ask

How do Web API and MVC work together in the same project?

In order to add a Web API Controller you will need to Right Click the Controllers folder in the Solution Explorer and click on Add and then Controller. Now from the Add Scaffold window, choose the Web API 2 Controller – Empty option as shown below. Then give it a suitable name and click OK.


1 Answers

You guys got very close. Shadi was on the right track. Even if this is a separate mvc application, you still need to decrypt the token as shown and extract the claim. If your web api token is in the variable called accessToken, you can do the following in your mvc web app. (Note that mvc is using both bearer authentication and cookie authentication and OAuthBearerOptions is a static class)

//Unprotect the token 
var unencryptedToken = Startup.OAuthBearerOptions.AccessTokenFormat.Unprotect(accessToken);
//Extract the claims identity from the token
var identity = unencryptedToken.Identity;

//Once you have the claims identity extracted, create a new claims identity that uses 
//ApplicationCookie as the default authentication type

var id = new ClaimsIdentity(identity.Claims, DefaultAuthenticationTypes.ApplicationCookie);

// Now you are ready to sign in with your new claims identity. You basically created an  
//application cookie from a bearer token and now using this cookie to sign-in

AuthenticationManager.SignIn(id);

Here is how your startup.auth.cs should include (note that we have an OAuthBearerAuthenticationOptions static member and we call app.UseOAuthBearerAuthentication() just to be able to decrypt the bearer token

public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }

    static Startup()
    {
        OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
    }


    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseOAuthBearerAuthentication(OAuthBearerOptions);
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login")
        });
    }
like image 54
freud Avatar answered Sep 23 '22 09:09

freud