api de gestion de ticket, basé sur php-crud-api. Le but est de décorrélé les outils de gestion des données, afin
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.

JwtAuthMiddleware.php 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. <?php
  2. namespace Tqdev\PhpCrudApi\Middleware;
  3. use Tqdev\PhpCrudApi\Controller\Responder;
  4. use Tqdev\PhpCrudApi\Middleware\Base\Middleware;
  5. use Tqdev\PhpCrudApi\Record\ErrorCode;
  6. use Tqdev\PhpCrudApi\Request;
  7. use Tqdev\PhpCrudApi\Response;
  8. class JwtAuthMiddleware extends Middleware
  9. {
  10. private function getVerifiedClaims(String $token, int $time, int $leeway, int $ttl, String $secret, array $requirements): array
  11. {
  12. $algorithms = array('HS256' => 'sha256', 'HS384' => 'sha384', 'HS512' => 'sha512');
  13. $token = explode('.', $token);
  14. if (count($token) < 3) {
  15. return array();
  16. }
  17. $header = json_decode(base64_decode(strtr($token[0], '-_', '+/')), true);
  18. if (!$secret) {
  19. return array();
  20. }
  21. if ($header['typ'] != 'JWT') {
  22. return array();
  23. }
  24. $algorithm = $header['alg'];
  25. if (!isset($algorithms[$algorithm])) {
  26. return array();
  27. }
  28. $hmac = $algorithms[$algorithm];
  29. $signature = bin2hex(base64_decode(strtr($token[2], '-_', '+/')));
  30. if ($signature != hash_hmac($hmac, "$token[0].$token[1]", $secret)) {
  31. return array();
  32. }
  33. $claims = json_decode(base64_decode(strtr($token[1], '-_', '+/')), true);
  34. if (!$claims) {
  35. return array();
  36. }
  37. foreach ($requirements as $field => $values) {
  38. if (!empty($values)) {
  39. if (!isset($claims[$field]) || !in_array($claims[$field], $values)) {
  40. return array();
  41. }
  42. }
  43. }
  44. if (isset($claims['nbf']) && $time + $leeway < $claims['nbf']) {
  45. return array();
  46. }
  47. if (isset($claims['iat']) && $time + $leeway < $claims['iat']) {
  48. return array();
  49. }
  50. if (isset($claims['exp']) && $time - $leeway > $claims['exp']) {
  51. return array();
  52. }
  53. if (isset($claims['iat']) && !isset($claims['exp'])) {
  54. if ($time - $leeway > $claims['iat'] + $ttl) {
  55. return array();
  56. }
  57. }
  58. return $claims;
  59. }
  60. private function getArrayProperty(String $property, String $default): array
  61. {
  62. return array_filter(array_map('trim', explode(',', $this->getProperty($property, $default))));
  63. }
  64. private function getClaims(String $token): array
  65. {
  66. $time = (int) $this->getProperty('time', time());
  67. $leeway = (int) $this->getProperty('leeway', '5');
  68. $ttl = (int) $this->getProperty('ttl', '30');
  69. $secret = $this->getProperty('secret', '');
  70. $requirements = array(
  71. 'alg' => $this->getArrayProperty('algorithms', ''),
  72. 'aud' => $this->getArrayProperty('audiences', ''),
  73. 'iss' => $this->getArrayProperty('issuers', ''),
  74. );
  75. if (!$secret) {
  76. return array();
  77. }
  78. return $this->getVerifiedClaims($token, $time, $leeway, $ttl, $secret, $requirements);
  79. }
  80. private function getAuthorizationToken(Request $request): String
  81. {
  82. $parts = explode(' ', trim($request->getHeader('Authorization')), 2);
  83. if (count($parts) != 2) {
  84. return '';
  85. }
  86. if ($parts[0] != 'Bearer') {
  87. return '';
  88. }
  89. return $parts[1];
  90. }
  91. public function handle(Request $request): Response
  92. {
  93. if (session_status() == PHP_SESSION_NONE) {
  94. session_start();
  95. }
  96. $token = $this->getAuthorizationToken($request);
  97. if ($token) {
  98. $claims = $this->getClaims($token);
  99. $_SESSION['claims'] = $claims;
  100. if (empty($claims)) {
  101. return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, 'JWT');
  102. }
  103. }
  104. if (empty($_SESSION['claims'])) {
  105. $authenticationMode = $this->getProperty('mode', 'required');
  106. if ($authenticationMode == 'required') {
  107. return $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
  108. }
  109. }
  110. return $this->next->handle($request);
  111. }
  112. }