Last active
August 29, 2015 13:55
-
-
Save stonetip/8745656 to your computer and use it in GitHub Desktop.
JWT token validation class
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
internal class TokenValidationHandler : DelegatingHandler | |
{ | |
// This function retrieves ACS token (in format of OAuth 2.0 Bearer Token type) from | |
// the Authorization header in the incoming HTTP request from the client. | |
private static bool TryRetrieveToken(HttpRequestMessage request, out string token) | |
{ | |
try | |
{ | |
token = null; | |
IEnumerable<string> authHeaders; | |
request.Headers.TryGetValues("Authorization", out authHeaders); | |
var authHeadersList = authHeaders.ToList(); | |
if (authHeadersList.Count() != 1) | |
{ | |
// Fail if no Authorization header or more than one Authorization headers | |
// are found in the HTTP request | |
return false; | |
} | |
token = authHeadersList.FirstOrDefault(); | |
return true; | |
} | |
catch (Exception err) | |
{ | |
Debug.WriteLine(err.Message); | |
token = null; | |
return false; | |
} | |
} | |
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | |
{ | |
string token; | |
if (!TryRetrieveToken(request, out token)) | |
{ | |
return | |
Task<HttpResponseMessage>.Factory.StartNew( | |
() => new HttpResponseMessage(HttpStatusCode.Unauthorized), cancellationToken); | |
} | |
try | |
{ | |
// Use JwtSecurityTokenHandler to validate the JWT token | |
var tokenHandler = new JwtSecurityTokenHandler(); | |
var convertedSecret = EncodeSigningToken(ConfigurationManager.AppSettings["ClientSecret"]); | |
// Set the expected properties of the JWT token in the TokenValidationParameters | |
var validationParameters = new TokenValidationParameters() | |
{ | |
AllowedAudience = ConfigurationManager.AppSettings["AllowedAudience"], | |
ValidIssuer = ConfigurationManager.AppSettings["Issuer"], | |
SigningToken = new BinarySecretSecurityToken(convertedSecret) | |
}; | |
Thread.CurrentPrincipal = tokenHandler.ValidateToken(token, validationParameters); | |
if (HttpContext.Current != null) | |
{ | |
HttpContext.Current.User = Thread.CurrentPrincipal; | |
} | |
// Treat as ClaimsPrincipal, extract JWT expiration and inject it into request headers | |
var cp = (ClaimsPrincipal)Thread.CurrentPrincipal; | |
request.Headers.Add("JWT-Expiration", cp.FindFirst("exp").Value); | |
return base.SendAsync(request, cancellationToken); | |
} | |
catch (SecurityTokenValidationException stvErr) | |
{ | |
Debug.WriteLine(stvErr.Message); | |
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Unauthorized)); | |
} | |
catch (Exception err) | |
{ | |
Debug.WriteLine(err.Message); | |
return Task.FromResult((new HttpResponseMessage(HttpStatusCode.InternalServerError))); | |
} | |
} | |
public static byte[] StrToByteArray(string str) | |
{ | |
var encoding = new UTF8Encoding(); | |
return encoding.GetBytes(str); | |
} | |
public static byte[] EncodeSigningToken(string token) | |
{ | |
try | |
{ | |
var sha256 = new SHA256Managed(); | |
var secretBytes = StrToByteArray(token + "JWTSig"); | |
var signingKey = sha256.ComputeHash(secretBytes); | |
return signingKey; | |
} | |
catch (Exception) | |
{ | |
return null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment