Using cookies as storage for JwtTokens in ASP.NET 5.0

I have updated my code base to be able to use cookies to hold the Jwt Tokens for my API after the API has authenticated the user account.

Parse error on line 1:

^
Expecting 'NEWLINE', 'SPACE', 'GRAPH', got 'EOF'

The basic flow is now:

  1. User authenticates via /api/Users/authenticateUser
  2. My API returns a Jwt Token in the message body and also sets a cookie containing the token
  3. Subsequent requests to protected resources (controlled by the [Authorize] attribute) use the token from the cookie
  4. If the cookie is not provided or empty the token can be read from the Authorization header as a Bearer token

This is the response to the authentication request

This is the authorization token being stored in the cookies

Now I can make requests using the Authorization cookie without needing to pass an Authorization header:

To get this working I add one line of code to the authenticateUser method to send the authorization bearer token as a cookie:

HttpContext.Response.Cookies.Append("Authorization", "Bearer " + token);

I then update my HandleAuthentication method to read the cookie first if it is provided:

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
	string authorizationHeader = null;
	if (Request.Cookies.ContainsKey("Authorization"))
	{
		authorizationHeader = Request.Cookies["Authorization"];
	}

	if (authorizationHeader == null && !Request.Headers.ContainsKey("Authorization"))
	{
		return AuthenticateResult.Fail("Unauthorized");
	}

	if (authorizationHeader == null)
	{
		authorizationHeader = Request.Headers["Authorization"];
	}

	if (string.IsNullOrEmpty(authorizationHeader))
	{
		return AuthenticateResult.NoResult();
	}

	if (!authorizationHeader.StartsWith("bearer", StringComparison.OrdinalIgnoreCase))
	{
		return AuthenticateResult.Fail("Unauthorized");
	}

	string token = authorizationHeader.Substring("bearer".Length).Trim();

Of course this isn’t 100% secure as I don’t want the cookie to be read by Javascript in case of a malicous script. To get around this I am going to set the cookie to be a HttpOnly cookie. This is using the advise from Wade (https://twitter.com/netCoreTutorial) in this article:

https://dotnetcoretutorials.com/2017/01/15/httponly-cookies-asp-net-core/

Adding new CookieOptions { HttpOnly = true } to the end of the Append method for adding cookies will achieve this.

HttpContext.Response.Cookies.Append("Authorization", 
"Bearer " + token, 
new CookieOptions { HttpOnly = true });

This means that a Javascript script running on the browser cannot read the cookie but the cookie will still be passed back to the server on subsequent requests to protected resources.

The cookie can still be viewed in the Application tab in dev tools but it now has the Http Only flag ticked which is what we want.

For the next time I am going to make some improvements to the above technique including removing the Jwt Token from the message body response for the authenticate user end point.

Leave a comment

Your email address will not be published. Required fields are marked *