oauth2-server-php-docs 概念

 

PHP的OAuth2服务器库

将OAuth2.0干净地安装到您的PHP应用程序中。 从GitHub 下载代码开始。php

要求

这个库须要PHP 5.3.9+然而,有一个稳定的版本开发分支PHP 5.2.x-5.3.8为好。html

安装

这个库遵循zend PSR-0标准。有一些自动加载器能够自动加载这个库,可是若是你不使用它,你能够注册OAuth2\Autoloadermysql

require_once('/path/to/oauth2-server-php/src/OAuth2/Autoloader.php'); OAuth2\Autoloader::register();

使用Composer执行如下命令:git

composer.phar require bshaffer/oauth2-server-php "^1.10"github

这会将需求添加到composer.json并安装库。web

强烈建议您查看v1.10.0标签以确保您的应用程序不会由于向后兼容性问题而中断。可是,若是您想保持开发的最前沿,您能够将其设置为dev-masterredis

开始使用这个库

菜谱的例子是最好的入门方法。对于那些仅仅浏览代码示例文档的人来讲,下面是一个简单的OAuth2服务器实现的例子:算法

$storage = new OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password)); $server = new OAuth2\Server($storage); $server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage)); // or any grant type you like! $server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();

有关这个库如何工做的更多信息,请参阅主要概念sql

学习OAuth2.0标准

  1. 若是您是OAuth2的新手,我强烈推荐Knp University的8步屏幕视图中OAuth: 8个步骤中的OAuthshell

  2. 此外,花点时间点击OAuth2演示应用程序, 并查看使用各类受权类型的示例 源代码。 OAuth演示应用程序

  3. 并且,Auth0为实现PHP应用程序的 OAuth2.0提供了一个很好的层次

  4. 最后,请查阅OAuth2.0官方文档,了解不合理的技术规范。

 

主要概念

要更好地了解OAuth规范,请参阅 学习OAuth标准

图书馆涉及几个主要概念:

Grant Types

授予类型容许您展现客户端接收令牌的多种方式。

Controllers

OAuth服务器有3个端点,每一个端点均可以由控制器进行配置每一个端点都在OAuth进程中执行不一样的功能。

  • 受权端点 - 用户在这里由客户端重定向来受权请求
  • 令牌端点 - 客户端向该端点发出请求以得到访问令牌
  • 资源端点 - 客户端请求资源,为认证令牌提供访问令牌。该库支持许多不一样的受权类型,包括由官方OAuth规范定义的全部受权类型。

Storage Objects

该库使用存储接口来容许与多个数据层进行交互。如下存储类随库提供,但接口容许您自定义:

Other Concepts

 

授予类型

OAuth2规范中有许多支持的受权类型,而且该库容许添加自定义受权类型。支持的受权类型以下:

受权码

Authorization Code补助类型是最多见的OAuth2.0的流动。它实现3腿OAuth并涉及授予客户一个受权码,用户能够交换访问令牌的用户。点击现场演示查看这个受权类型的实际操做。

资源全部者密码凭证

资源全部者的用户名和密码做为请求的一部分提交,而且在成功认证时发出令牌。

json
$ curl -u testclient:testpass "http://localhost/token.php" -d 'grant_type=password&username=someuser&password=somepassword' {"access_token":"206c80413b9a96c1312cc346b7d2517b84463edd","expires_in":3600,"token_type":"bearer","scope":null}

客户端凭证

客户端使用他们的凭证直接检索访问令牌,这容许在客户端的控制下访问资源

json
$ curl -u testclient:testpass "http://localhost/token.php" -d 'grant_type=client_credentials' {"access_token":"6f05ad622a3d32a5a81aee5d73a5826adb8cbf63","expires_in":3600,"token_type":"bearer","scope":null}

刷新令牌

若是访问令牌已过时,客户端能够提交刷新令牌并接收新的访问令牌。

json
$ curl -u testclient:testpass "http://localhost/token.php" -d 'grant_type=refresh_token&refresh_token=c54adcfdb1d99d10be3be3b77ec32a2e402ef7e3' {"access_token":"0e9d02499fe06762ecaafb9cfbb506676631dcfd","expires_in":3600,"token_type":"bearer","scope":null}

含蓄

这与Authorization Code上面受权类型类似,可是从受权请求返回的受权码而不是受权码,令牌返回给客户端。这对客户端证书没法安全存储的客户端设备(即移动设备)最为常见。

Implicit经过将该allow_implicit选项设置为true来为authorize端点使用授予类型

$storage = new OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password)); $server = new OAuth2\Server($storage, array('allow_implicit' => true)); $server->handleAuthorizeRequest(OAuth2\Request::createFromGlobals())->send();

重要的是要注意,这不是做为Grant Type添加的,由于隐式受权类型是使用authorize端点而不是token端点来请求

智威汤逊旗手

客户端能够向令牌端点提交请求中的JWT(JSON Web令牌)。而后直接返回一个访问令牌(没有刷新令牌)。

延期补助金

经过实现OAuth2\GrantType\GrantTypeInterface并将其添加到OAuth2服务器对象来建立您本身的授予类型JWT Bearer 上面格兰特类型就是一个例子。

多个受权类型

若是您想要支持多个授予类型,则能够在建立服务器对象时添加更多:

$server->addGrantType(new OAuth2\GrantType\UserCredentials($storage)); $server->addGrantType(new OAuth2\GrantType\RefreshToken($storage)); $server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage));

##限制授予类型给客户

客户机可用grant_type的授予类型由客户机存储器中的字段和受权服务器内提供的授予类型的组合来控制

当客户端拥有配置的受权类型列表时,客户端仅限于使用这些授予类型。若是没有配置受权类型,则客户端可使用的受权类型不受限制,它可使用受权服务器内可用的全部受权类型。

控制器

...最终用户(资源全部者)能够授予打印服务(客户端)访问存储在照片共享服务(资源服务器)中的受保护照片,而没必要与打印服务共享她的用户名和密码。相反,她直接使用照片共享服务(受权服务器)信任的服务器进行身份验证,受权服务器发布打印服务委派特定凭据(访问令牌)。

〜OAuth2(草稿#31

大多数的OAuth2的API将有终点Authorize RequestsToken RequestsResource RequestsOAuth2\Server对象具备处理每一个请求的方法。

下面的每一个控制器经过相同的名称对应于端点。

存储

概观

该库支持多个不一样存储引擎的适配器。其中包括PDO(用于MySQL,SQLite,PostgreSQL等), MongoDBRedis和 Cassandra

这是经过多个PHP接口完成的,这个接口决定了如何存储不一样的对象。接口容许对多个平台进行扩展和定制,使得编写本身的存储类容易 

存储接口还能够轻松地将对象存储在 多个数据存储系统中

请求和响应

请求对象

每一个服务器调用都以一个请求开始。这个库使用本身的简单对象来验证对服务器的调用。你几乎老是会这样建立:

$request = OAuth2\Request::createFromGlobals(); // call the OAuth server with it $server->handleTokenRequest($request);

由于这使用PHP接口,因此咱们能够很容易地扩展它为咱们正在使用的框架:

// use HttpFoundation Requests instead, for Symfony / Twig / Laravel 4 / Drupal 8 / etc! $symfony_request = Symfony\Component\HttpFoundation\Request::createFromGlobals(); $request = OAuth2\HttpFoundationBridge\Request::createFromRequest($symfony_request) // call the OAuth server with it $server->handleTokenRequest($request);

响应对象

响应对象服务于使您的服务器符合OAuth2的目的。它将为有效或无效的oauth请求设置适当的状态码,标题和响应正文。要使用它做为最简单的级别,只需发送输出并退出:

$request = OAuth2\Request::createFromGlobals(); $response = new OAuth2\Response(); // will set headers, status code, and json response appropriately for success or failure $server->grantAccessToken($request, $response); $response->send();

响应对象也能够用来自定义输出。在下面,若是请求无效,则错误被发送到浏览器:

if (!$token = $server->grantAccessToken($request, $response)) { $response->send(); die(); } echo sprintf('Your token is %s!!', $token);

这将填充适当的错误标题,并返回一个JSON错误响应。若是您不想发送JSON响应,则可使用响应对象以任何其余格式显示信息:

if (!$token = $server->grantAccessToken($request, $response)) { $parameters = $response->getParameters(); // format as XML header("HTTP/1.1 " . $response->getStatusCode()); header("Content-Type: text/xml"); echo "<error><name>".$parameters['error']."</name><message>".$parameters['error_description']."</message></error>"; }

在框架或现有代码库中工做时,这很是有用,由于这个库不能彻底控制响应。

请参阅HttpFoundation Bridge库,使用HttpFoundation将您的请求/响应插入到框架中

范围

配置您的范围

在OAuth2应用程序中使用范围一般是正确许可的关键。范围用于限制资源全部者授予客户的受权。这个最受欢迎的用途是Facebook用户向客户受权各类不一样功能的能力(“访问基本信息”,“贴在墙上”等)。

在这个库中,范围是经过实现来处理的OAuth2\Storage\ScopeInterface这可使用你本身的实现,或者利用现有的OAuth2\Storage\Memory类来完成:

// configure your available scopes $defaultScope = 'basic'; $supportedScopes = array( 'basic', 'postonwall', 'accessphonenumber' ); $memory = new OAuth2\Storage\Memory(array( 'default_scope' => $defaultScope, 'supported_scopes' => $supportedScopes )); $scopeUtil = new OAuth2\Scope($memory); $server->setScopeUtil($scopeUtil);

这是最简单的方法,但范围也能够动态配置:

// configure your available scopes $doctrine = Doctrine_Core::getTable('OAuth2Scope'); $scopeUtil = new OAuth2\Scope($doctrine); $server->setScopeUtil($scopeUtil);

这个例子假设正在使用的类实现OAuth2\Storage\ScopeInterface

class OAuth2ScopeTable extends Doctrine_Table implements OAuth2\Storage\ScopeInterface { public function getDefaultScope($client_id = null) { //... } public function scopeExists($scope, $client_id = null) { //... } }

验证你的范围

在服务器类中配置范围将确保客户端请求的范围是有效的。可是,要确保正确验证范围,须要执行两个步骤。首先,请求的范围必须在受权的状况下暴露给资源全部者。在这个库中,这个被实现了100%。用户界面或必须清楚受权的范围。其次,资源请求自己必须指定访问它所需的范围:

// https://api.example.com/resource-requiring-postonwall-scope $request = OAuth2\Request::createFromGlobals(); $response = new OAuth2\Response(); $scopeRequired = 'postonwall'; // this resource requires "postonwall" scope if (!$server->verifyResourceRequest($request, $response, $scopeRequired)) { // if the scope required is different from what the token allows, this will send a "401 insufficient_scope" error $response->send(); }

定制您的范围

因为每一个应用程序的“范围”的实现可能会有很大差别,所以提供除OAuth2 \ Scope之外的其余类别可能会有所帮助。OAuth2\ScopeInterface在自定义类中实现以彻底自定义。

state参数默认为受权重定向所必需的。这至关于一个CSRF令牌,并为您的受权请求提供会话验证。有关 状态的更多信息,请参阅OAuth2.0规范

为了安全起见,这是默认启用的,可是当你配置你的服务器时,你能够删除这个需求:

// on creation $server = new OAuth2\Server($storage, array('enforce_state' => false)); // or after creation $server = new OAuth2\Server(); $server->setConfig('enforce_state', false);

使用多个范围

您能够经过在受权请求中提供以空格分隔(可是网址安全)的做用域列表来请求多个做用域。它看起来像这样:

文本
https://mydomain.com/authorize
   ?client_id=MY_CLIENT
   &response_type=code
   &scope=onescope%20twoscope%20redscope%20bluescope

注意:额外的换行符仅用于可读性

这将建立一个受权代码,具备如下四个范围:“onescope”,“twoscope”,“redscope”和“bluescope”

而后这四个范围将根据使用OAuth2\ScopeUtil该类的可用范围进行验证,以确保它们存在。若是您收到错误invalid_scope: An unsupported scope was requested,这是由于您须要在服务器对象上设置可用的做用域,以下所示:

$scope = new OAuth2\Scope(array( 'supported_scopes' => array('onescope', 'twoscope', 'redscope', 'bluescope') )); $server->setScopeUtil($scope);

##将范围限制到客户端客户端可用的范围由scope客户端存储器中的字段和范围存储器中定义的可用范围列表的组合来控制

当客户端有一个配置的范围列表时,客户端被限制为仅使用那些范围。当没有配置范围时,客户端可使用的范围不受限制,它可使用受权服务器内可用的全部范围。

 

用户ID

将本地用户与访问令牌相关联

一旦你对一个用户进行了认证并发布了一个访问令牌(好比一个受权控制器),那么你可能想知道当访问令牌被使用时,哪一个用户使用了一个访问令牌。

您能够经过使用如下可选的user_id参数来执行此操做handleAuthorizeRequest

$userid = 1234; // A value on your server that identifies the user $server->handleAuthorizeRequest($request, $response, $is_authorized, $userid);

这将使用访问令牌将用户标识保存到数据库中。当令牌被客户端使用时,您能够检索关联的ID:

if (!$server->verifyResourceRequest(OAuth2\Request::createFromGlobals())) { $server->getResponse()->send(); die; } $token = $server->getAccessTokenData(OAuth2\Request::createFromGlobals()); echo "User ID associated with this token is {$token['user_id']}";

OpenID Connect

例子

您能够在演示站点上看到运行OpenID Connect 的示例(选择OpenID Connect选项卡),以及 使用密钥存储对象配置选项设置 的代码use_openid_connect

概观

使用OpenID Connect包含两个主要组件:

1.生成公钥和私钥

建立公钥和私钥pem文件的细节超出了本文档的范围,但能够在网上找到说明 

2.确保id_token列存在受权码存储。

例如,若是使用PDO,请运行如下查询:

sql
ALTER TABLE oauth_authorization_codes ADD id_token VARCHAR(1000) NULL DEFAULT NULL;

3.设置use_openid_connectissuer配置参数

// create storage object $storage = new OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password)); // configure the server for OpenID Connect $config['use_openid_connect'] = true; $config['issuer'] = 'brentertainment.com'; // create the server $server = new OAuth2\Server($storage, $config);

4.建立您的密钥存储并将其添加到服务器:

$publicKey = file_get_contents('/path/to/pubkey.pem'); $privateKey = file_get_contents('/path/to/privkey.pem'); // create storage $keyStorage = new OAuth2\Storage\Memory(array('keys' => array( 'public_key' => $publicKey, 'private_key' => $privateKey, ))); $server->addStorage($keyStorage, 'public_key');

注意:经过建立公钥表也能够将密钥存储在您的PDO数据库中:

sql
CREATE TABLE oauth_public_keys ( client_id VARCHAR(80), public_key VARCHAR(2000), private_key VARCHAR(2000), encryption_algorithm VARCHAR(100) DEFAULT 'RS256' )

验证OpenID Connect

若是您的服务器正确配置了OpenID Connect,则当您请求访问令牌并将其openid做为请求的做用域之一包含时,访问令牌响应将包含一个id_token

// create a request object to mimic an authorization code request $request = new OAuth2\Request(array( 'client_id' => 'SOME_CLIENT_ID', 'redirect_uri' => 'http://brentertainment.com', 'response_type' => 'code', 'scope' => 'openid', 'state' => 'xyz', )); $response = new OAuth2\Response(); $server->handleAuthorizeRequest($request, $response, true); // parse the returned URL to get the authorization code $parts = parse_url($response->getHttpHeader('Location')); parse_str($parts['query'], $query); // pull the code from storage and verify an "id_token" was added $code = $server->getStorage('authorization_code') ->getAuthorizationCode($query['code']); var_export($code);

若是您的应用程序正确配置为OpenID,则您的输出应以下所示:

array ( 'code' => '3288362b828be2cf9eb2327bb30773a45c3fc151', 'client_id' => 'SOME_CLIENT_ID', 'user_id' => NULL, 'redirect_uri' => 'http://brentertainment.com', 'expires' => 1442944611, 'scope' => 'openid', 'id_token' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJvY XV0aDItc2VydmVyLWJ1bmRsZSIsInN1YiI6bnVsbCwiYXVkIjoidGVzdC1jbGllbn QtNTM4MDM0ODkyIiwiaWF0IjoxNDQyOTQ0NTgxLCJleHAiOjE0NDI5NDgxODEsImF 1dGhfdGltZSI6MTQ0Mjk0NDU4MX0.Ev-vPTeL1CxmSRpvV0l1nyeogpeKO2uQDuVt YbVCphfA8sLBWAVFixnCqsZ2BSLf30KzDCSzQCvSh8jgKOTQAsznE69ODSXurj3NZ 0IBufgOfLjGi0E4JvI_KksAVewy53mcN2DBSRmtJjwZ8BKjzQnOIJ77LGpQKvpW4S kmZE4', )

该物业"id_token"代表OpenID Connect正在运行。若是遇到问题,请确保SOME_CLIENT_ID使用有效的客户端ID进行替换

智威汤逊访问令牌

概观

JWT访问令牌提供了一种建立和验证访问令牌的方法,而不须要像数据库这样的中央存储。在验证访问令牌时减小了 OAuth2服务的延迟

JWT访问令牌使用JSON Web签名 (第6.2章)和 公钥加密 来肯定其有效性。OAuth2.0服务器使用a标记令牌private key,其余方可使用服务器验证令牌public key

格式

JWT访问令牌具备如下格式:

文本
HEADER.PAYLOAD.SIGNATURE

HEADER是如下JSON的Base64 URL安全编码:

json
{"typ": "JWT", "alg":"RS256"}

PAYLOAD是一个带有如下字段的JSON对象的Base64 URL安全编码:

json
{
  "id": "394a71988caa6cc30601e43f5b6569d52cd7f6df", "jti": "394a71988caa6cc30601e43f5b6569d52cd7f6df", "iss": "issuer_id", "aud": "client_id", "sub": "user_id", "exp": 1483711650, "iat": 1483708050, "token_type": "bearer", "scope": "onescope twoscope" }
  • id - 令牌的内部标识
  • jti - 令牌的惟一令牌标识符(JWT ID)
  • iss - 颁发令牌的服务器的ID(颁发者)
  • aud - 请求令牌的客户的身份(受众)
  • sub - 令牌被释放的用户的标识(主题)
  • exp - 令牌到期时的UNIX时间戳(到期)
  • iat - 建立令牌时的UNIX时间戳(发出时间)
  • token_type - 这种象征,将成为持有者
  • scope - 发布令牌的空间分隔的做用域列表

使用JWT访问令牌与此库

建立公钥和私钥对

要开始,你须要一个公钥/私钥对。这些可使用如下命令在任何基于Unix的操做系统上生成:

巴什
# private key
$ openssl genrsa -out privkey.pem 2048

# public key
$ openssl rsa -in privkey.pem -pubout -out pubkey.pem

基本用法

配置服务器的最简单方法是为use_jwt_access_tokens OAuth服务器的配置提供选项:

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

这将须要您建立一个PublicKey存储对象。您可使用内置Memory存储:

// your public key strings can be passed in however you like $publicKey = file_get_contents('/path/to/pubkey.pem'); $privateKey = file_get_contents('/path/to/privkey.pem'); // create storage $storage = new OAuth2\Storage\Memory(array('keys' => array( 'public_key' => $publicKey, 'private_key' => $privateKey, ))); $server = new OAuth2\Server($storage, array( 'use_jwt_access_tokens' => true, ));

这是使用JWT访问令牌时的最小配置,而且将是ResourceController惟一有效的对于完整的服务器配置,您必须提供Client存储和一些受权类型。

如下是完整的服务器配置示例:

// token.php // error reporting (this is a demo, after all!) ini_set('display_errors',1);error_reporting(E_ALL); // Autoloading (composer is preferred, but for this example let's just do this) require_once('oauth2-server-php/src/OAuth2/Autoloader.php'); OAuth2\Autoloader::register(); // your public key strings can be passed in however you like // (there is a public/private key pair for testing already in the oauth library) $publicKey = file_get_contents('oauth2-server-php/test/config/keys/id_rsa.pub'); $privateKey = file_get_contents('oauth2-server-php/test/config/keys/id_rsa'); // create storage $storage = new OAuth2\Storage\Memory(array( 'keys' => array( 'public_key' => $publicKey, 'private_key' => $privateKey, ), // add a Client ID for testing 'client_credentials' => array( 'CLIENT_ID' => array('client_secret' => 'CLIENT_SECRET') ), )); $server = new OAuth2\Server($storage, array( 'use_jwt_access_tokens' => true, )); $server->addGrantType(new OAuth2\GrantType\ClientCredentials($storage)); // minimum config // send the response $server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();

如今您能够调用您的服务器并接收JWT访问令牌:

巴什
# start the PHP built-in web server
$ php -S localhost:3000 &
$ curl -i -v http://localhost:3000/token.php -u 'CLIENT_ID:CLIENT_SECRET' -d "grant_type=client_credentials"

服务器将返回一个包含JWT访问令牌的响应:

json
{
    "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6IjYzMjIwNzg0YzUzODA3ZjVmZTc2Yjg4ZjZkNjdlMmExZTIxODlhZTEiLCJjbGllbnRfaWQiOiJUZXN0IENsaWVudCBJRCIsInVzZXJfaWQiOm51bGwsImV4cGlyZXMiOjEzODAwNDQ1NDIsInRva2VuX3R5cGUiOiJiZWFyZXIiLCJzY29wZSI6bnVsbH0.PcC4k8Q_etpU-J4yGFEuBUdeyMJhtpZFkVQ__sXpe78eSi7xTniqOOtgfWa62Y4sj5Npta8xPuDglH8Fueh_APZX4wGCiRE1P4nT4APQCOTbgcuCNXwjmP8znk9F76ID2WxThaMbmpsTTEkuyyUYQKCCdxlIcSbVvcLZUGKZ6-g", "client_id":"CLIENT_ID", "user_id":null, "expires":1382630473, "scope":null }

资源服务器配置

若是您的资源服务器与您的受权服务器分开,则能够在没有受权服务器的私钥的状况下配置您的服务器:

/* for a Resource Server (minimum config) */ $publicKey = file_get_contents('/path/to/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, ));

这容许您的服务器验证访问令牌,而不向Authorization Server或任何其余共享资源发出任何请求。

// verify the JWT Access Token in the request if (!$server->verifyResourceRequest(OAuth2\Request::createFromGlobals())) { exit("Failed"); } echo "Success!";

如今你能够请求这个,并尝试发送上面生成的令牌!

巴什
# start the PHP built-in web server
$ php -S localhost:3000 &
$ curl "http://localhost:3000/resource.php?access_token=eyJ0eXAi..."
Success!

使用辅助存储

该库容许您将访问令牌备份到辅助存储。只是经过实施一个对象OAuth2\Storage\AccessTokenInterfaceJwtAccessToken对象到具备存储在一个附加的位置的访问令牌:

$pdoStorage = new OAuth2\Storage\Pdo($pdo); // access token will also be saved to PDO $keyStorage = new OAuth2\Storage\Memory(array('keys' => array( 'public_key' => $publicKey, 'private_key' => $privateKey, )));

此示例从Memory存储中提取公钥/私钥,并Pdo在签名后将授予的访问令牌保存到存储。

特定于客户端的加密密钥

制做特定于客户端的密钥是一个好主意。这样,若是密钥对受到攻击,只有一个客户端受到影响。双方MemoryPdo支持这种类型的存储。这里是一个使用Memory存储的例子

$keyStorage = new OAuth2\Storage\Memory(array('keys' => array( 'ClientID_One' => array( 'public_key' => file_get_contents('/path/to/client_1_rsa.pub'), 'private_key' => file_get_contents('/path/to/client_1_rsa'), ), 'ClientID_Two' => array( 'public_key' => file_get_contents('/path/to/client_2_rsa.pub'), 'private_key' => file_get_contents('/path/to/client_2_rsa'), ), // declare global keys as well 'public_key' => file_get_contents('/path/to/global_rsa.pub'), 'private_key' => file_get_contents('/path/to/global_rsa'), )));

对于Pdo,运行如下查询:

sql
/* create the database table */ CREATE TABLE oauth_public_keys (client_id VARCHAR(80), public_key VARCHAR(8000), private_key VARCHAR(8000), encryption_algorithm VARCHAR(80) DEFAULT "RS256")

使用这样的插入样本数据:

sql
/* insert global keys into the database */ INSERT INTO oauth_public_keys (client_id, public_key, private_key, encryption_algorithm) VALUES (NULL, "...", "...", "RS256"); /* add client-specific key pairs */ INSERT INTO oauth_public_keys (client_id, public_key, private_key, encryption_algorithm) VALUES ("ClientID_One", "...", "...", "RS256"); INSERT INTO oauth_public_keys (client_id, public_key, private_key, encryption_algorithm) VALUES ("ClientID_Two", "...", "...", "RS256");

并实例化PDO存储对象:

$dsn = 'mysql:dbname=my_oauth2_db;host=localhost'; $username = 'root'; $password = ''; $pdoStorage = new OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password));

配置不一样的算法

JwtAccessTokens支持如下算法:

  • “HS256” - 使用hash_hmac/ sha256
  • “HS384” - 使用hash_hmac/ sha384
  • “HS512” - 使用hash_hmac/ sha512
  • “RS256” - 使用openssl_sign/ sha256
  • “RS384” - 使用openssl_sign/ sha384
  • “RS512” - 使用openssl_sign/ sha512

在你的OAuth2\Storage\PublicKeyInterface实例中进行配置当使用Memory存储时,这看起来像这样:

$storage = new OAuth2\Storage\Memory(array('keys' => array( 'public_key' => $publicKey, 'private_key' => $privateKey, 'encryption_algorithm' => 'HS256', // "RS256" is the default )));

客户端验证

签名能够用任何编程语言进行验证使用标准的 Public Key加密方法来验证访问令牌签名。这是在PHP中的一个例子:

$token = json_decode($curlResponse); $jwt_access_token = $token['access_token']; $separator = '.'; if (2 !== substr_count($jwt_access_token, $separator)) { throw new Exception("Incorrect access token format"); } list($header, $payload, $signature) = explode($separator, $jwt_access_token); $decoded_signature = base64_decode(str_replace(array('-', '_'), array('+', '/'), $signature)); // The header and payload are signed together $payload_to_verify = utf8_decode($header . $separator . $payload); // however you want to load your public key $public_key = file_get_contents('/path/to/pubkey.pem'); // default is SHA256 $verified = openssl_verify($payload_to_verify, $decoded_signature, $public_key, OPENSSL_ALGO_SHA256); if ($verified !== 1) { throw new Exception("Cannot verify signature"); } // output the JWT Access Token payload var_dump(base64_decode($payload));
相关文章
相关标签/搜索