Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 338
Forough Avatar asked Nov 09 '22 22:11

Forough


1 Answers

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.

like image 162
Ian Avatar answered Dec 13 '22 17:12

Ian