A handler for JWT Authentication in .NET
Created
June 4, 2017 16:48
-
-
Save mykeels/3535e9849cfb7c555bc363a437168951 to your computer and use it in GitHub Desktop.
A JWT Token Handler wrapper class for .NET
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Microsoft.IdentityModel.Tokens; | |
using System.IdentityModel.Tokens.Jwt; | |
using System.Security.Claims; | |
using System.Text; | |
public class JwtTokenHandler | |
{ | |
private static JwtTokenHandler _jwtHandler; | |
private JwtSecurityTokenHandler tokenHandler; | |
private SymmetricSecurityKey signingKey; | |
private SigningCredentials signingCredentials; | |
private TokenValidationParameters tokenValidationParameters; | |
private Config config; | |
public const int EXPIRY_HOURS = 5; | |
private JwtTokenHandler(Config _config) | |
{ | |
config = _config; | |
signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.SecurityKey)); | |
signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); | |
tokenHandler = new JwtSecurityTokenHandler(); | |
tokenValidationParameters = new TokenValidationParameters() | |
{ | |
ValidAudiences = config.Audiences, | |
ValidIssuers = config.Issuers, | |
IssuerSigningKey = signingKey | |
}; | |
} | |
/// <summary> | |
/// Returns a Singleton JwtTokenHandler Instance | |
/// </summary> | |
public static JwtTokenHandler GetTokenHandler(Config config = null) | |
{ | |
if (_jwtHandler == null) | |
{ | |
_jwtHandler = new JwtTokenHandler(config); | |
} | |
return _jwtHandler; | |
} | |
private SecurityTokenDescriptor _getTokenDescriptor(ClaimsIdentity claimsIdentity, int expiryHours) | |
{ | |
return new SecurityTokenDescriptor() | |
{ | |
Audience = config.GetAudience.Invoke(), | |
Expires = DateTime.UtcNow.AddHours(expiryHours), | |
IssuedAt = DateTime.UtcNow, | |
Issuer = config.GetIssuer.Invoke(), | |
NotBefore = DateTime.UtcNow, | |
SigningCredentials = signingCredentials, | |
Subject = claimsIdentity | |
}; | |
} | |
/// <summary> | |
/// Use if you which to define a custom SecurityTokenDescriptor | |
/// </summary> | |
public SecurityToken GetPlainToken(SecurityTokenDescriptor tokenDescriptor) | |
{ | |
return tokenHandler.CreateToken(tokenDescriptor); | |
} | |
/// <summary> | |
/// Get a Security Token from Claims like username and role | |
/// </summary> | |
/// <param name="claimsIdentity"></param> | |
/// <param name="expiryHours">Set the number of Hours for a Token to stay Valid</param> | |
/// <returns></returns> | |
public SecurityToken GetPlainToken(ClaimsIdentity claimsIdentity, int expiryHours = EXPIRY_HOURS) | |
{ | |
return tokenHandler.CreateToken(_getTokenDescriptor(claimsIdentity, expiryHours)); | |
} | |
/// <summary> | |
/// Get the JWT Token String from a Security Token | |
/// </summary> | |
public string GetSignedToken(SecurityToken plainToken) | |
{ | |
return tokenHandler.WriteToken(plainToken); | |
} | |
/// <summary> | |
/// Using a valid JWT String, get its Claims | |
/// </summary> | |
public ClaimedToken GetClaims(string signedAndEncodedToken) | |
{ | |
SecurityToken validatedToken; | |
return new ClaimedToken() | |
{ | |
Claims = tokenHandler.ValidateToken(signedAndEncodedToken, tokenValidationParameters, out validatedToken), | |
Token = validatedToken | |
}; | |
} | |
public class Config | |
{ | |
public string SecurityKey { get; set; } | |
public Func<string> GetAudience { get; set; } | |
public Func<string> GetIssuer { get; set; } | |
public string[] Audiences { get; set; } | |
public string[] Issuers { get; set; } | |
} | |
public class ClaimedToken | |
{ | |
public ClaimsPrincipal Claims { get; set; } | |
public SecurityToken Token { get; set; } | |
} | |
public class TokenModel | |
{ | |
public string AccessToken { get; set; } | |
public string RefreshToken { get; set; } | |
public long ExpiresIn { get; set; } | |
public string ExpiresInParameter | |
{ | |
get | |
{ | |
return "seconds"; | |
} | |
} | |
} | |
public class Roles | |
{ | |
public const string USER = "user"; | |
public const string REFRESH = "refresh"; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Security.Claims; | |
using JwtHandler.Helpers; | |
public class Program | |
{ | |
private static JwtTokenHandler tokenHandler; | |
private const string USERNAME = "mykeels"; | |
private const string PLAIN_TEXT_SECURITY_KEY = "ThisIsMykeelsSecurityKey"; | |
public static void Main(string[] args) | |
{ | |
createTokenHandler(); | |
string token = createNewToken(USERNAME); | |
Console.WriteLine(token); | |
validateToken(token); | |
Console.ReadLine(); | |
} | |
private static void validateToken(string token) | |
{ | |
var compound = tokenHandler.GetClaims(token); | |
Console.WriteLine(compound.Token.ToString()); | |
} | |
private static void createTokenHandler() | |
{ | |
tokenHandler = JwtTokenHandler.GetTokenHandler(new JwtTokenHandler.Config() | |
{ | |
Audiences = new[] { "https://example.com" }, | |
GetAudience = () => "https://example.com", | |
GetIssuer = () => "https://api.example.com", | |
Issuers = new[] { "https://api.example.com" }, | |
SecurityKey = PLAIN_TEXT_SECURITY_KEY | |
}); | |
} | |
private static string createNewToken(string username) | |
{ | |
var plainToken = tokenHandler.GetPlainToken(new ClaimsIdentity(new List<Claim>() | |
{ | |
new Claim(ClaimTypes.NameIdentifier, username), | |
new Claim(ClaimTypes.Role, JwtTokenHandler.Roles.USER) | |
})); | |
return tokenHandler.GetSignedToken(plainToken); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment