Accueil > OpenID Connect OAuth Serveur dédié > Développer > OAuth 2.0 > Demande d’autorisation avec JWT (JWT Bearer Authorization Grant)

Demande d’autorisation avec JWT (JWT Bearer Authorization Grant)

La particularité de ce flux est d’interroger le point d’accès token sans les identifiants (credentials) de l’application cliente, mais en passant un jeton JWT signé.

Spécification du flux JWT Bearer

(traduction d’extrait de la spécification draft-ietf-oauth-jwt-bearer-07 section 1)

2.1. Utilisation de JWT en tant qu’accord d’autorisation (Authorization Grants)

Pour utiliser un jeton JWT pour la demande d’autorisation, émettez une requête de jeton d’accès telle que définie dans la section 4 de la spécification ’Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants [I-D.ietf-oauth-assertions]’ avec les valeurs de paramètres et encodages spécifiques suivants.

La valeur du paramètre "grant_type" DOIT être "urn : ietf : params : oauth : grant-type : jwt-bearer".

La valeur du paramètre "assertion" DOIT contenir un seul JWT.

Le paramètre "scope" peut être utilisé pour indiquer la portée demandée.

L’authentification du client est facultative, comme décrit dans la Section 3.2.1 de OAuth 2.0 [RFC6749] et par conséquent, le "client_id" n’est nécessaire que lorsqu’un type d’authentification client qui repose sur ce paramètre est utilisé.

...

3.1. Traitement des accords d’autorisations

Les autorisations JWT peuvent être utilisées avec ou sans authentification ou identification du client. Que l’authentification du client soit requise ou non en conjonction avec un accord d’autorisation JWT, ainsi que les types d’authentification des clients pris en charge, sont des décisions de politique à la discrétion du serveur d’autorisation.
Cependant, si les informations d’identification du client sont présentes dans la demande, le serveur d’autorisation DOIT les valider.

Test du flux JWT Bearer avec OAuthSD

Il est possible de mettre ce flux en oeuvre avec OAuthSD. Le script ci-dessous donne un exemple d’appel au point de terminaison Token avec un jeton JWT fabriqué localement.

PHP

  1. <?php
  2. /* test_JWTBearer.php
  3.  
  4. Usage :  https://oa.dnc.global/oidc/tests/test_JWTBearer.php
  5.  
  6. Author :
  7. Bertrand Degoy https://degoy.com
  8. Credits :
  9. bschaffer https://github.com/bshaffer/oauth2-server-php
  10. Licence : MIT licence
  11. */
  12.  
  13. ini_set('display_errors', 1);
  14.  
  15. // Autoloading by Composer
  16. require __DIR__ . '/../../vendor/autoload.php';
  17. OAuth2\Autoloader::register();
  18.  
  19. //***** Configuration *****
  20.  
  21. $client_id = 'testopenid';   // iss
  22. $user_id = 'bebert';  // subject
  23.  
  24. $server = 'oa.dnc.global';
  25. $token_endpoint = 'https://' . $server . '/token';
  26.  
  27. define('PRIVATE', true);
  28. require_once __DIR__.'/../../oidc/includes/configure.php';        
  29. require_once __DIR__.'/../../oidc/includes/utils.php';
  30.  
  31. //*** End of configuration ***
  32.  
  33. // Connect to database
  34. $cnx = new \PDO($connection['dsn'], $connection['username'], $connection['password']);
  35. // Get private key
  36. $stmt = $cnx->prepare($sql = "SELECT * FROM spip_public_keys WHERE client_id=:client_id");
  37. $stmt->execute(compact('client_id'));
  38. $keyinfo = $stmt->fetch(\PDO::FETCH_ASSOC);
  39. if ( empty($keyinfo) ) {
  40.     $response->setError(401, 'invalid_token', "Invalid aud");   //DEBUG only
  41.     $response->send();
  42.     die;
  43. }
  44. $private_key = $keyinfo['private_key'];
  45.  
  46. $grant_type  = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
  47.  
  48. $jwt = generateJWT($private_key, $client_id, $user_id, 'https://' . $server);
  49.  
  50. passthru("curl " . $token_endpoint . " -d 'grant_type=$grant_type&assertion=$jwt'");
  51.  
  52. /**
  53. * Generate a JWT
  54. *
  55. * @param $privateKey The private key to use to sign the token
  56. * @param $iss The issuer, usually the client_id
  57. * @param $sub The subject, usually a user_id
  58. * @param $aud The audience, usually the URI for the oauth server
  59. * @param $exp The expiration date. If the current time is greater than the exp, the JWT is invalid
  60. * @param $nbf The "not before" time. If the current time is less than the nbf, the JWT is invalid
  61. * @param $jti The "jwt token identifier", or nonce for this JWT
  62. *
  63. * @return string
  64. */
  65. function generateJWT($privateKey, $iss, $sub, $aud, $exp = null, $nbf = null, $jti = null)
  66. {
  67.     if (!$exp) {
  68.         $exp = time() + 1000;
  69.     }
  70.  
  71.     $params = array(
  72.         'iss' => $iss,
  73.         'sub' => $sub,
  74.         'aud' => $aud,
  75.         'exp' => $exp,
  76.         'iat' => time(),
  77.     );
  78.  
  79.     if ($nbf) {
  80.         $params['nbf'] = $nbf;
  81.     }
  82.  
  83.     if ($jti) {
  84.         $params['jti'] = $jti;
  85.     }
  86.  
  87.     $jwtUtil = new OAuth2\Encryption\Jwt();
  88.  
  89.     return $jwtUtil->encode($params, $privateKey, 'RS256');
  90. }

Télécharger

En cas de succès, le serveur retourne quelque chose comme :

{"access_token":"8d2bea8d956f74030d8837deacd6154dbc0df262","expires_in":3600,"token_type":"Bearer","scope":"basic"}
Il existe des informations complémentaires, connectez vous pour les voir.