53

I planned to use ASP.NET Identity 2.0 in an ASP.NET MVC application for authentication and authorization.

Referring the below link

JSON Web Token in ASP.NET Web API 2 using Owin

I was able to create a access token(JWT) for the valid user i.e., When user Logs in to the application I will validate the user with name and password then I will issue a JSON web token for that valid user.

Now, I read in some articles that we need to pass the bearer token in headers for every request to validate the user for authentication. In MVC we will provide Authorize attribute for the methods that needs to be protected as shown below…

      public class UserController : BaseHRAppController
      {
            [Authorize]
            public ActionResult Index()
            {          
               return View();
            }
       }

How to tell my MVC application to use JWT for validating the user?

I want to make my MVC application validate the user using JWT whenever the user tries to access the method with authorize attribute. Since I will use AJAX calls in many pages to access method present in MVC controller, I don't think it's good to pass a token on every AJAX request. I need help to accomplish authentication and authorization in an efficient way using ASP.NET Identity in an MVC applicaton.

Currently, I don't know how to use this JWT token for authentication and authorization in an MVC application.

Luke Girvin
  • 13,221
  • 9
  • 64
  • 84
SDK
  • 1,532
  • 1
  • 15
  • 31
  • any luck on this? I think that for MVC application you would have to use cookies, I'm not sure about this but that how it seems to work. SPA template within VS uses 2 forms of authentication: cookies for MVC and token for Web API – Pawel May 18 '15 at 08:06

2 Answers2

58

In order for MVC to understand anything about your JWT you basically have to tell it :-) . First, install the Jwt package from nuget:

Install-Package Microsoft.Owin.Security.Jwt

Then open up your Startup.cs file and add a new funtion that will tell MVC how to consume JWT. At basics your Startup will look something like:

using System.Configuration;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler.Encoder;
using Microsoft.Owin.Security.Jwt;
using Owin;

[assembly: OwinStartupAttribute(typeof(TOMS.Frontend.Startup))]
namespace TOMS.Frontend
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            ConfigureOAuthTokenConsumption(app);
        }

        private void ConfigureOAuthTokenConsumption(IAppBuilder app)
        {
            var issuer = ConfigurationManager.AppSettings["Issuer"];
            var audienceId = ConfigurationManager.AppSettings["AudienceId"];
            var audienceSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["AudienceSecret"]);

            // Api controllers with an [Authorize] attribute will be validated with JWT
            app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
            {
                AuthenticationMode = AuthenticationMode.Active,
                AllowedAudiences = new[] { audienceId },
                IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                {
                    new SymmetricKeyIssuerSecurityTokenProvider(issuer, audienceSecret) 
                }
            });
        }
    }
}

You will notice that I am placing the issuer, audienceId and audienceSecret in my Web.config file. (Those values should match the ones on your Resource Server). Also, you might want to ensure you have an updated System.IdentityModel.Tokens.Jwt running:

Update-package System.IdentityModel.Tokens.Jwt

With those set, you may decorate your controller Action with the [Authorize] attribute and play ball.

Play ball of course meaning fire your request from your javascript to your protected controller action:

//assuming you placed the token in a sessionStorage variable called tokenKey when it came back from your Authorization Server
    var token = sessionStorage.getItem(tokenKey);
    var headers = {};
    if (token) {
        headers.Authorization = 'Bearer ' + token;
    }

    $.ajax({
        type: 'GET',
        url: 'CONTROLLER/ACTION',
        headers: headers
    }).done(function (data) {
        self.result(data);
    }).fail(showError);

UPDATE By The way, if you wish to add the values in your web.config file in order to retrieve them as I did above; simply add them under the AppSettings:

<configuration>
 <appSettings>
    <add key="Issuer" value="YOUR_ISSUER" />
    <add key="AudienceId" value="YOUR_AUDIENCEID" />
    <add key="AudienceSecret" value="YOUR_AUDIENCESECRET" />
 </appSettings>
</configuration>

...of course, replacing the "values" with your own

Houdini Sutherland
  • 1,550
  • 21
  • 20
  • 1
    If you are getting your tokens back via JWT, then you can look at this answer I gave to a similar question: http://stackoverflow.com/questions/29271314/get-user-role-in-clear-text-along-with-jwt-when-using-angularjs-webapi-and-oaut/37708802#37708802 – Houdini Sutherland Feb 20 '17 at 20:58
  • 2
    @HoudiniSutherland Great answer. How do you mix this with standard cookie authentication? I have an MVC 5 project with normal Controller that are protected with the `Authorize` attribute and using cookies. But I've also added some ApiControllers that I want to protect with JWT. How can I make it so cookies are used for normal controllers and JWT for Api controllers? – empz Oct 01 '18 at 19:30
  • @emzero Check out Shawn's article, which should have you set up and going. Hope it helps: https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2 – Houdini Sutherland Oct 02 '18 at 15:14
  • 1
    @HoudiniSutherland Unfortunately that is for ASP.NET Core (like most articles on this). I can't seem to find one for plain old ASP.NET MVC 5. – empz Oct 02 '18 at 17:03
  • @HoudiniSutherland Where is `ConfigureAuth()` implementation? And should we use it with default or add some configuration lines raleted to JWT. Could you pls add this method to your answer? Thanks. –  Apr 02 '20 at 07:36
  • @hexadecimal The ConfigureAuth() is just a method for additional authentication configurations down the pipeline on the IAppBuilder object [app]. For example, in the ConfigureAuth() you could configure authentication such as FaceBook, Google, Twitter, etc., configure your db context, user manager and sign in manager to use a single instance per request, configure sign-in cookies for External or TwoFactor, In this specific case, I was not necessarily using it to configure the JWT related components. it's a simple area for configuring the authentication bits for the application as it starts up. – Houdini Sutherland Apr 03 '20 at 17:25
  • @HoudiniSutherland Thanks for explanataions. But it would be better to post the implementation of it even if empty for unexperienced users. This way users does not confused too. Thanks. –  Apr 04 '20 at 07:49
15

I don't know if you solved this, but I was having a similar issue and decided to store the token using FormsAuthentication which I was able to encrypt the token, and on each request the cookie was passed back and then I could decrypt it to get the JWT and then pull out the roles/claims from and then use those roles to create and Identity Principal that would allow me to decorate my controller methods with [Authorize(Role="blah,blah")].

Here is some sample code below.

Once you get the JSON web token back from the api after login, you can use something like:

var returnedToken = (TokenResponse)result.ReturnedObject;
var ticket = new FormsAuthenticationTicket(1, model.Email, DateTime.Now, ConvertUnitToDateTime(returnedToken.expires_in), true, returnedToken.access_token);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie)

I have some of my own created classes and methods in there, but it will give you the general idea that you store the JWT access token as well as the expiration date in your FormsAuthentication cookie.

Then the cookie is passed with each request and in your Global.asax file you can have a method to authenticate the request:

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        //Extract the forms authentication cookie
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

        JwtSecurityToken jwTok = TokenHelper.GetJWTokenFromCookie(authCookie); 

        // Create the IIdentity instance
        IIdentity id = new FormsIdentity(authTicket);

        // Create the IPrinciple instance
        IPrincipal principal = new GenericPrincipal(id, TokenHelper.GetRolesFromToken(jwTok).ToArray());

        // Set the context user
        Context.User = principal;
    }
}

So that method you would decrypt the cookie to get the JWT access token which you can then decode using the System.IdentityModel.Tokens.Jwt library from Microsoft and then take those roles and ID and generate the principal and identity for the user which creates your user with the roles.

Then those roles can be validated against the [Authorize] attribute.

Dan Atkinson
  • 11,391
  • 14
  • 81
  • 114
reverence12389
  • 457
  • 5
  • 15