effiana / oauth2-client
OAuth 2.0 客户端库
Requires
- php: ^5.6|^7.0
- guzzlehttp/guzzle: ^6.0 || ^7.0
- paragonie/random_compat: ^1|^2|^9.99
Requires (Dev)
- eloquent/liberator: ^2.0
- eloquent/phony-phpunit: ^1.0|^3.0
- jakub-onderka/php-parallel-lint: ^0.9.2
- phpunit/phpunit: ^5.7|^6.0
- squizlabs/php_codesniffer: ^2.3|^3.0
This package is auto-updated.
Last update: 2024-09-24 18:23:20 UTC
README
本软件包可以轻松地将您的应用程序与 OAuth 2.0 服务提供商集成。
我们都习惯了在网上看到那些“通过Facebook/Google等连接”按钮,社交网络集成现在是大多数Web应用的重要功能。许多这些网站使用OAuth 2.0(RFC 6749)这样的认证和授权标准。
这个OAuth 2.0客户端库可以与符合OAuth 2.0标准的任何OAuth提供商一起使用。默认情况下,我们提供了一个GenericProvider
,可以用于连接到任何使用Bearer tokens的服务提供商(请参阅下面的示例)。
许多服务提供商在OAuth 2.0标准之上提供额外的功能。因此,这个库可以很容易地扩展和包装以支持这种行为。我们提供了所有已知扩展此库的提供商客户端(例如Facebook、GitHub、Google、Instagram、LinkedIn等)的链接。如果你的提供商不在列表中,请随时添加。
本软件包符合PSR-1、PSR-2、PSR-4和PSR-7。如果你注意到符合性疏忽,请通过pull request发送补丁。如果你有兴趣为此库做出贡献,请参阅我们的贡献指南。
要求
以下版本的PHP得到支持。
- PHP 5.6
- PHP 7.0
- PHP 7.1
- PHP 7.2
- PHP 7.3
提供商
官方PHP League提供商列表以及第三方提供商列表可在提供商列表README中找到。
要构建自己的提供商,请参阅提供商指南README。
用法
在大多数情况下,您可能希望使用特定的提供商客户端库而不是这个基础库。
请查看提供商列表README以查看提供商客户端库列表。
如果您使用Composer来要求特定的提供商客户端库,您不需要也要求此库。Composer将为您处理依赖关系。
授权码授予
以下示例使用了该库提供的默认GenericProvider
。如果您正在寻找特定的提供商(例如Facebook、Google、GitHub等),请查看我们的提供商客户端库列表。提示:您可能正在寻找特定的提供商。
授权码授予类型是在使用第三方服务验证用户时最常用的授权类型。此授权类型利用客户端(本库)、服务器(服务提供者)和资源所有者(拥有受保护或拥有资源的凭证的用户)来请求访问用户拥有的资源。这通常被称为3方OAuth,因为涉及三方。
以下示例使用Brent Shaffer的名为Lock'd In的演示OAuth 2.0应用程序来说明这一点。运行此代码时,您将被重定向到Lock'd In,您将需要授权客户端代表您请求资源。
现在,您在Lock'd In上实际上没有账户,但为了这个示例,假设您在重定向到那里时已经在Lock'd In上登录。
$provider = new \League\OAuth2\Client\Provider\GenericProvider([ 'clientId' => 'demoapp', // The client ID assigned to you by the provider 'clientSecret' => 'demopass', // The client password assigned to you by the provider 'redirectUri' => 'http://example.com/your-redirect-url/', 'urlAuthorize' => 'http://brentertainment.com/oauth2/lockdin/authorize', 'urlAccessToken' => 'http://brentertainment.com/oauth2/lockdin/token', 'urlResourceOwnerDetails' => 'http://brentertainment.com/oauth2/lockdin/resource' ]); // If we don't have an authorization code then get one if (!isset($_GET['code'])) { // Fetch the authorization URL from the provider; this returns the // urlAuthorize option and generates and applies any necessary parameters // (e.g. state). $authorizationUrl = $provider->getAuthorizationUrl(); // Get the state generated for you and store it to the session. $_SESSION['oauth2state'] = $provider->getState(); // Redirect the user to the authorization URL. header('Location: ' . $authorizationUrl); exit; // Check given state against previously stored one to mitigate CSRF attack } elseif (empty($_GET['state']) || (isset($_SESSION['oauth2state']) && $_GET['state'] !== $_SESSION['oauth2state'])) { if (isset($_SESSION['oauth2state'])) { unset($_SESSION['oauth2state']); } exit('Invalid state'); } else { try { // Try to get an access token using the authorization code grant. $accessToken = $provider->getAccessToken('authorization_code', [ 'code' => $_GET['code'] ]); // We have an access token, which we may use in authenticated // requests against the service provider's API. echo 'Access Token: ' . $accessToken->getToken() . "<br>"; echo 'Refresh Token: ' . $accessToken->getRefreshToken() . "<br>"; echo 'Expired in: ' . $accessToken->getExpires() . "<br>"; echo 'Already expired? ' . ($accessToken->hasExpired() ? 'expired' : 'not expired') . "<br>"; // Using the access token, we may look up details about the // resource owner. $resourceOwner = $provider->getResourceOwner($accessToken); var_export($resourceOwner->toArray()); // The provider provides a way to get an authenticated API request for // the service, using the access token; it returns an object conforming // to Psr\Http\Message\RequestInterface. $request = $provider->getAuthenticatedRequest( 'GET', 'http://brentertainment.com/oauth2/lockdin/resource', $accessToken ); } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) { // Failed to get the access token or user details. exit($e->getMessage()); } }
刷新令牌
一旦您的应用程序被授权,您可以使用刷新令牌来刷新过期的令牌,而不是通过整个获取全新令牌的过程。为此,只需从您的数据存储中重新使用此刷新令牌来请求刷新。
此示例使用Brent Shaffer的名为Lock'd In的演示OAuth 2.0应用程序。有关详细信息,请参阅上面的授权码示例。
$provider = new \League\OAuth2\Client\Provider\GenericProvider([ 'clientId' => 'demoapp', // The client ID assigned to you by the provider 'clientSecret' => 'demopass', // The client password assigned to you by the provider 'redirectUri' => 'http://example.com/your-redirect-url/', 'urlAuthorize' => 'http://brentertainment.com/oauth2/lockdin/authorize', 'urlAccessToken' => 'http://brentertainment.com/oauth2/lockdin/token', 'urlResourceOwnerDetails' => 'http://brentertainment.com/oauth2/lockdin/resource' ]); $existingAccessToken = getAccessTokenFromYourDataStore(); if ($existingAccessToken->hasExpired()) { $newAccessToken = $provider->getAccessToken('refresh_token', [ 'refresh_token' => $existingAccessToken->getRefreshToken() ]); // Purge old access token and store new access token to your data store. }
资源所有者密码凭证授予
一些服务提供者允许您跳过授权码步骤,用用户的凭证(用户名和密码)交换访问令牌。这被称为“资源所有者密码凭证”授权类型。
根据OAuth 2.0标准第1.3.3节(强调部分)
凭证仅应在资源所有者和客户端之间有高度信任时使用(例如,客户端是设备操作系统的部分或高度特权应用程序),并且当其他授权授予类型不可用(如授权码)时。
我们不建议如果服务提供者支持授权码授予类型(见上文),使用此授权类型,因为这会通过允许用户认为信任第三方应用程序的凭据是可接受的,从而强化了密码反模式。
尽管如此,在某些情况下,资源所有者密码凭证授权是可接受和有用的。以下是一个使用Brent Shaffer的名为Lock'd In的演示OAuth 2.0应用程序的示例。关于Lock'd In演示应用程序的更多详细信息,请参阅上面的授权码示例。
$provider = new \League\OAuth2\Client\Provider\GenericProvider([ 'clientId' => 'demoapp', // The client ID assigned to you by the provider 'clientSecret' => 'demopass', // The client password assigned to you by the provider 'redirectUri' => 'http://example.com/your-redirect-url/', 'urlAuthorize' => 'http://brentertainment.com/oauth2/lockdin/authorize', 'urlAccessToken' => 'http://brentertainment.com/oauth2/lockdin/token', 'urlResourceOwnerDetails' => 'http://brentertainment.com/oauth2/lockdin/resource' ]); try { // Try to get an access token using the resource owner password credentials grant. $accessToken = $provider->getAccessToken('password', [ 'username' => 'demouser', 'password' => 'testpass' ]); } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) { // Failed to get the access token exit($e->getMessage()); }
客户端凭证授予
当您的应用程序代表其自身访问服务提供者控制的/拥有的资源时,它可以使用客户端凭证授予类型。当您的应用程序的凭证存储在私密位置且永远不会暴露给最终用户(例如,通过网页浏览器等)时,此用法最佳。此授权类型的功能与资源所有者密码凭证授权类型类似,但它不请求用户的用户名或密码。它仅使用服务提供者颁发给您的客户端的客户端ID和密钥。
与前面的示例不同,以下示例不适用于功能性的演示服务提供者。它仅作为示例提供。
// Note: the GenericProvider requires the `urlAuthorize` option, even though // it's not used in the OAuth 2.0 client credentials grant type. $provider = new \League\OAuth2\Client\Provider\GenericProvider([ 'clientId' => 'XXXXXX', // The client ID assigned to you by the provider 'clientSecret' => 'XXXXXX', // The client password assigned to you by the provider 'redirectUri' => 'http://my.example.com/your-redirect-url/', 'urlAuthorize' => 'http://service.example.com/authorize', 'urlAccessToken' => 'http://service.example.com/token', 'urlResourceOwnerDetails' => 'http://service.example.com/resource' ]); try { // Try to get an access token using the client credentials grant. $accessToken = $provider->getAccessToken('client_credentials'); } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) { // Failed to get the access token exit($e->getMessage()); }
使用代理
您可以使用代理来调试对提供者发出的HTTP调用。您需要做的就是在创建Provider实例时设置proxy
和verify
选项。确保您在代理中启用SSL代理。
$provider = new \League\OAuth2\Client\Provider\GenericProvider([ 'clientId' => 'XXXXXX', // The client ID assigned to you by the provider 'clientSecret' => 'XXXXXX', // The client password assigned to you by the provider 'redirectUri' => 'http://my.example.com/your-redirect-url/', 'urlAuthorize' => 'http://service.example.com/authorize', 'urlAccessToken' => 'http://service.example.com/token', 'urlResourceOwnerDetails' => 'http://service.example.com/resource', 'proxy' => '192.168.0.1:8888', 'verify' => false ]);
安装
通过Composer
$ composer require league/oauth2-client
贡献
请参阅CONTRIBUTING以获取详细信息。
许可
MIT许可证(MIT)。请参阅许可文件以获取更多信息。