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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With