如何从 JWT access_token (bshaffer oauth library) 中提取 user_id

Posted

技术标签:

【中文标题】如何从 JWT access_token (bshaffer oauth library) 中提取 user_id【英文标题】:How to extract user_id from JWT access_token (bshaffer oauth library) 【发布时间】:2018-04-16 09:00:01 【问题描述】:

我跟着 JWT 教程https://bshaffer.github.io/oauth2-server-php-docs/overview/jwt-access-tokens/

我已按如下方式创建了 access_token:

$publicKey  = file_get_contents(dirname(__FILE__) .'/Keys/pubkey.pem');
$privateKey = file_get_contents(dirname(__FILE__) .'/Keys/privkey.pem');

// create storage
$storage = new \OAuth2\Storage\Memory([
    'keys' => [
        'public_key'  => $publicKey,
        'private_key' => $privateKey,
    ],
    'client_credentials' => [
        'api' => ['client_secret' => 'secret']
    ],
]);

$server = new \OAuth2\Server($storage, array(
    'use_jwt_access_tokens' => true,
));
$server->addGrantType(new \OAuth2\GrantType\ClientCredentials($storage));

$tokenData = json_decode($server->handleTokenRequest(\OAuth2\Request::createFromGlobals())->getResponseBody(), true);

回应是


    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6IjM1NWM5YjEzNjRkNmUzMmM2YTM0YWQ2NDgzMWM2NzZjZjllYmEyZGIiLCJqdGkiOiIzNTVjOWIxMzY0ZDZlMzJjNmEzNGFkNjQ4MzFjNjc2Y2Y5ZWJhMmRiIiwiaXNzIjoiIiwiYXVkIjoiYXBpIiwic3ViIjpudWxsLCJleHAiOjE1MDk3MjQ5NDYsImlhdCI6MTUwOTcyMTM0NiwidG9rZW5fdHlwZSI6ImJlYXJlciIsInNjb3BlIjpudWxsfQ.QzCb-nFYHaiJQcj8NsiAN8WoPo24MC5xIgNxWCCNO1WCPzJ_iZ7In6YWcdfe3xVcJQRUzECrveYmKFZizVf7P2UYeGiZjd0tUqM972YiF_9ZrIEjVN_L9QSfGCCAQlhCvXFUdWrfMyiLjUi4D4LYELKyPpkDrJ-0QG5ngtBX_-Iy2zH7BaXf_AGAIyJPScdVvhs_4trroWSaJn7I8KRMtihZCV6ucAUVjkiXJ5rL6Pyem--3PRXJX6IoOQtbKUyRxwhUZfHefPHWaHUdwJY3f83gRnJrSfXql0KdF5i1SdUf1VGwEldmdHPnGHCfKKVypjeXzaP9lHqeO63CXVeY2A",
    "expires_in": 3600,
    "token_type": "bearer",
    "scope": null,

现在我可以按如下方式验证令牌

$publicKey  = file_get_contents(dirname(__FILE__) .'/Keys/pubkey.pem');

// no private key necessary
    $keyStorage = new \OAuth2\Storage\Memory(array('keys' => array(
'public_key'  => $publicKey,
)));

$server = new \OAuth2\Server($keyStorage, array(
    'use_jwt_access_tokens' => true,
));
$validation = $server->verifyResourceRequest(\OAuth2\Request::createFromGlobals());

if (!$validation) 
    $server->getResponse()->send();
    die;

因此它验证了令牌,但根据教程有效负载文档,我找不到提取 user_id 或“sub”的方法


  "id": "394a71988caa6cc30601e43f5b6569d52cd7f6df",
  "jti": "394a71988caa6cc30601e43f5b6569d52cd7f6df",
  "iss": "issuer_id",
  "aud": "client_id",
  "sub": "user_id",
  "exp": 1483711650,
  "iat": 1483708050,
  "token_type": "bearer",
  "scope": "onescope twoscope"

我希望从有效令牌(通过标题)中获取 user_id,并使用它从我的数据库中收集相关的用户数据。我该怎么做?

【问题讨论】:

请阅读bshaffer.github.io/oauth2-server-php-docs/overview/… 感谢您的链接,我确实阅读了它,但我不明白它对我有什么帮助?我希望将 user_id 存储在令牌中,然后再对其进行解码。 OpenID Connect 示例最后显示 user_id 为空,并且没有讨论存储它。我错过了什么吗? 【参考方案1】:

好吧,既然你说你已经成功地达到了以下步骤:

$validation = $server->verifyResourceRequest(\OAuth2\Request::createFromGlobals());
if (!$validation) 

  $server->getResponse()->send();
  die;
 

这意味着一个有效的访问令牌已经发布,存储在某个地方,现在它被客户端使用,那么你可以像这样轻松地检索相关的 user_id:

  $token = $server->getAccessTokenData( $request->createFromGlobals() );
  print_r( "The associated userid with this token is $token['user_id']" );

否则,在成功创建访问令牌并拥有它之后,您可以像这样拆分它:

$tokenData = json_decode($server->handleTokenRequest(\OAuth2\Request::createFromGlobals())->getResponseBody(), true); //here you have the response body as a string and make it a php object
$separator = '.';

list($header, $payload, $signature) = explode($separator, $tokenData->access_token);
//In your case you need only $payload but it's a copy paste from my code testI
$payloadAsString = base64_decode($payload);
$payloadAsObject = json_decode($payloadAsString);
$tokenData->sub = $payloadAsObject->sub ; // Add a new property to your $tokenData object

现在在 $tokenData 你有 sub (user_id)。你可以随心所欲。 Json_decode 它等或使用它来查询您的数据库用户表。

希望对某人有所帮助..

【讨论】:

【参考方案2】:

我能够按照本指南实现所需的功能:https://bshaffer.github.io/oauth2-server-php-docs/grant-types/jwt-bearer/

【讨论】:

以上是关于如何从 JWT access_token (bshaffer oauth library) 中提取 user_id的主要内容,如果未能解决你的问题,请参考以下文章

如何在 access_token JWT 中添加更多数据

NESTJS 网关/Websocket - 如何通过 socket.emit 发送 jwt access_token

如何从 auth0 中的访问令牌中获取 jwt 令牌

jwt中为什么用refresh_token去刷新access_token,直接把access_token的有效期设置长一点不行吗?

Spring boot security oauth2 从 cookie 获取 access_token

access_token过期后如何刷新token