Skip to content

Instantly share code, notes, and snippets.

@marcosdeaguiar
Created May 20, 2020 18:10
Show Gist options
  • Save marcosdeaguiar/3f984538281c9baa5dd4a66922741375 to your computer and use it in GitHub Desktop.
Save marcosdeaguiar/3f984538281c9baa5dd4a66922741375 to your computer and use it in GitHub Desktop.
public static class JwtCookieMiddleware
{
/// <summary>
/// Checks the jwt cookie and sets the user for the application.
/// </summary>
/// <param name="app">App builder reference.</param>
/// <param name="antiforgery">Reference to the antiforgery service.</param>
/// <param name="key">The key to decrypt the token.</param>
/// <param name="autoRefresh">Creates a new token if the token is half past expiration time (and still valid).</param>
/// <param name="cookieName">Name of the cookie where the jwt is (defaults to jwt).</param>
/// <param name="csrfCookieName">Name of the cookie where the request token is stored.</param>
public static void UseJwtCookieMiddleware(this IApplicationBuilder app,
IAntiforgery antiforgery,
byte[] key,
bool autoRefresh = true,
string cookieName = "jwt",
string csrfCookieName = "XSRF-TOKEN")
{
app.Use(async (context, next) =>
{
string jwtStr = context.Request.Cookies[cookieName];
if (string.IsNullOrEmpty(jwtStr))
{
await next();
return;
}
var validationParameters = new TokenValidationParameters
{
// Clock skew compensates for server time drift.
ClockSkew = TimeSpan.FromMinutes(5),
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
RequireSignedTokens = true,
RequireExpirationTime = true,
ValidateLifetime = true,
// Ensure the token audience matches our audience value (default true):
ValidateAudience = false,
ValidateIssuer = false
};
ClaimsIdentity claimsIdentity = null;
ClaimsPrincipal newPrincipal;
JwtSecurityToken jwtToken = null;
try
{
var claimsPrincipal = new JwtSecurityTokenHandler()
.ValidateToken(jwtStr,
validationParameters,
out var rawValidatedToken);
//rawValidatedToken.
claimsIdentity = new ClaimsIdentity("AuthenticationTypes.Federation");
foreach (var claim in claimsPrincipal.Claims)
{
if (claim.Type == "iat" ||
claim.Type == "exp" ||
claim.Type == "nbf")
{
continue;
}
claimsIdentity.AddClaim(claim);
}
newPrincipal = new ClaimsPrincipal(claimsIdentity);
context.User = newPrincipal;
jwtToken = rawValidatedToken as JwtSecurityToken;
context.Items[Constants.JwtTokenKey] = jwtToken;
}
catch (Exception)
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append(csrfCookieName,
tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
context.Response.Cookies.Delete(cookieName);
}
if (autoRefresh &&
jwtToken != null &&
claimsIdentity != null)
{
CheckAndRefreshToken(key, claimsIdentity, jwtToken, cookieName, context);
}
await next();
});
}
}
@sammyaxe
Copy link

Hey any chance you could share CheckAndRefreshToken code bit, we are trying to work out how to implement cookie auth in our .NET SPA project and having hard time to find full example. Would be really appreciated if you could share more code @marcosdeaguiar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment