You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
3.5 KiB

1 year ago
  1. using Microsoft.IdentityModel.Tokens;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IdentityModel.Tokens.Jwt;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.Http;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using System.Web;
  11. namespace JsonRx.Helper
  12. {
  13. internal class JwtValidationHandler : DelegatingHandler
  14. {
  15. private static bool TryRetrieveToken(HttpRequestMessage request, out string token)
  16. {
  17. token = null;
  18. IEnumerable<string> authzHeaders;
  19. if (!request.Headers.TryGetValues("Authorization", out authzHeaders) || authzHeaders.Count() > 1)
  20. {
  21. return false;
  22. }
  23. var bearerToken = authzHeaders.ElementAt(0);
  24. token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
  25. return true;
  26. }
  27. protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
  28. {
  29. HttpStatusCode statusCode;
  30. string token;
  31. //determine whether a jwt exists or not
  32. if (!TryRetrieveToken(request, out token))
  33. {
  34. statusCode = HttpStatusCode.Unauthorized;
  35. //allow requests with no token - whether a action method needs an authentication can be set with the claimsauthorization attribute
  36. return base.SendAsync(request, cancellationToken);
  37. }
  38. try
  39. {
  40. const string sec = "401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1";
  41. var now = DateTime.UtcNow;
  42. var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));
  43. SecurityToken securityToken;
  44. JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
  45. TokenValidationParameters validationParameters = new TokenValidationParameters()
  46. {
  47. ValidAudience = "http://localhost:50191",
  48. ValidIssuer = "http://localhost:50191",
  49. ValidateLifetime = true,
  50. ValidateIssuerSigningKey = true,
  51. LifetimeValidator = this.LifetimeValidator,
  52. IssuerSigningKey = securityKey
  53. };
  54. //extract and assign the user of the jwt
  55. Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
  56. HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);
  57. return base.SendAsync(request, cancellationToken);
  58. }
  59. catch (SecurityTokenValidationException e)
  60. {
  61. statusCode = HttpStatusCode.Unauthorized;
  62. }
  63. catch (Exception ex)
  64. {
  65. statusCode = HttpStatusCode.InternalServerError;
  66. }
  67. return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(statusCode) { });
  68. }
  69. public bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
  70. {
  71. if (expires != null)
  72. {
  73. if (DateTime.UtcNow < expires) return true;
  74. }
  75. return false;
  76. }
  77. }
  78. }