Forough
Forough

Reputation: 362

Is it secure to store a WebAPI JWT access token as an encrypted FormsAuthenticationTicket in Response.Cookies (in asp.net mvc)

I use the code below at login controller to store user JWT access token in Response cookies

  var returnedJwtToken = authenticationResponse.Content;           
        try
        {
            //Store a WebAPI JWT accesstoken in an FormsAuthenticationTicket userData
            var ticket = new FormsAuthenticationTicket( 1,
                login.UserName,
                DateTime.Now,
                DateTime.Now.Add(TimeSpan.FromSeconds(returnedJwtToken.ExpiresIn)),
                login.RememberMe,
                returnedJwtToken.AccessToken,
                FormsAuthentication.DefaultUrl);

            //Encrypt it
            string encryptedTicket = FormsAuthentication.Encrypt(ticket);

            //Add it to Response.Cookies 
            var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket) {                  
                    Domain = FormsAuthentication.CookieDomain,
                    Path = FormsAuthentication.FormsCookiePath,
                    HttpOnly = true,
                    Secure = FormsAuthentication.RequireSSL };
            Response.Cookies.Add(cookie);

Then I use a customized MVC AuthorizeAttribute to restore the access token and put it in request headers so can retrive on controllers to send authenticated requests to WebAPI. Also it provides Authorization on my MVC application controllers.

public class SiteAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
       // var tokenHandler = new JwtSecurityTokenHandler();
        HttpCookie authCookie =httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        {

            //Extract the forms authentication cookie
            FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            HttpContext.Current.Request.Headers["AccessKey"] = authTicket.UserData;

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

            // Create the IPrinciple instance
            IPrincipal principal = new GenericPrincipal(id, null);

            // Set the context user
            httpContext.User = principal;
        }
        var accessKey= httpContext.Request.Headers["AccessKey"];
        return (!string.IsNullOrWhiteSpace(accessKey));
    }
}

Also I use the MVC ValidateAntiForgeryToken filter in post forms to prevent CSRF attacks.

I want to know is this solution secure enough or not?

If yes how can I retrive roles and claims from the token and use them in my Authorize filter on controllers?

Upvotes: 5

Views: 1506

Answers (2)

Ian
Ian

Reputation: 4457

When I first had to integrate a new Web API into a legacy application, I had to create some custom auth functions. I tried to follow the guidelines in this book:

Pro ASP.NET Web API Security: Securing ASP.NET Web API (Expert's Voice in .NET)

by Badrinarayanan Lakshmiraghavan

https://www.amazon.com/Pro-ASP-NET-Web-API-Security/dp/1430257822/ref=sr_1_3?keywords=securing+.net+web+api&qid=1565367785&s=gateway&sr=8-3

From what I remember of the book, these are the main points to keep in mind when dealing with client-side tokens (I believe this expands on Mr. Garg's article):

1) Use a Secure, HttpOnly cookie (prevents MIM, or XSS hijacking of token)

2) Create a token different from the cookie that is also submitted with every request (prevents XRSF forgery). Being different means that even if a malicious script were to obtain the unprotected token from localStorage, a request could not be generated with all necessary auth data.

3) Tokens are to be generated on server and both strongly encrypted and signed. For .NET Framework, the book uses an AuthenticatedAesCng library for this purpose. This prevents users from blindly tampering with data as well as reading it.

MVC is most likely following these principles, and ValidateAntiForgeryToken sounds like it would be accomplishing point #2 above.

I did try for some time to use provided auth methods within the .NET Framework, and other sources. However, I never became comfortable with any of them, and did not think they met my needs. So I am not that familiar with your particular situation, however I hope this is helpful.

Currently I find it rather simple to use the .NET Core DataProtection API to protect my own client tokens and implement my own auth MiddleWare component. This is perhaps "dangerous", but all of the encryption/decryption is taken care of by people smarter than me, and on my latest projects I have been working with legacy custom permission schemes; so the approach is somewhat merited.

Upvotes: 1

Himalaya Garg
Himalaya Garg

Reputation: 1609

A very good explanation is on link

It recommends to store token in cookies (HttpOnly+Secure+Encrypted) for web applications, because of the additional security they provide. Also due to simplicity of protecting against CSRF with modern web frameworks. HTML5 Web Storage is vulnerable to XSS and has a larger attack surface area, and can impact all application users on a successful attack.

Upvotes: 0

Related Questions