vunguyen/oauth2-client

OAuth 2.0 客户端库

1.2.2 2016-01-27 09:09 UTC

README

此包使您轻松地将应用程序与 OAuth 2.0 服务提供商集成。

Gitter Chat Source Code Latest Version Software License Build Status HHVM Status Scrutinizer Coverage Status Total Downloads

我们都习惯于在网上看到那些“用Facebook/Google等连接”的按钮,社交网络集成现在是大多数Web应用程序的重要功能。许多这些网站使用OAuth 2.0(RFC 6749)这种认证和授权标准。

此OAuth 2.0客户端库将与符合OAuth 2.0标准的任何OAuth提供者一起工作。默认情况下,我们提供了一个GenericProvider,可用于连接到任何使用Bearer令牌的服务提供商(请参见下面的示例)。

许多服务提供商提供了超出OAuth 2.0标准的功能。因此,此库可以轻松扩展并封装以支持这些附加行为。我们提供了指向所有已知扩展此库的提供者客户端(例如Facebook、GitHub、Google、Instagram、LinkedIn等)的链接。如果你的提供商不在列表中,请随意添加。

此包符合 PSR-1PSR-2PSR-4PSR-7。如果你注意到合规性的疏忽,请通过pull request发送补丁。如果你有兴趣为此库做出贡献,请查看我们的贡献指南

要求

支持以下版本的PHP。

  • PHP 5.5
  • PHP 5.6
  • PHP 7.0
  • HHVM

提供商

可以在提供商列表README中找到官方PHP League提供商和第三方提供商的列表。

要构建自己的提供者,请参阅提供者指南README

使用方法

在大多数情况下,您可能想使用特定的提供者客户端库而不是此基本库。

查看README.PROVIDERS.md,了解提供者客户端库的列表。

如果使用Composer要求特定的提供者客户端库,您不需要也要求此库。Composer将为您处理依赖关系。

授权码授予

以下示例使用了此库提供的默认GenericProvider。如果您正在寻找特定的提供者(例如Facebook、Google、GitHub等),请查看我们的提供者客户端库列表提示:您可能正在寻找特定的提供者。

授权码授予类型是当使用第三方服务进行用户认证时最常用的授权类型。这种授权类型利用客户端(本库)、服务器(服务提供者)和资源所有者(拥有受保护资源或自有资源凭证的用户)来请求访问用户拥有的资源。这通常被称为三方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']) || ($_GET['state'] !== $_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 $accessToken->getToken() . "\n";
        echo $accessToken->getRefreshToken() . "\n";
        echo $accessToken->getExpires() . "\n";
        echo ($accessToken->hasExpired() ? 'expired' : 'not expired') . "\n";

        // 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());

}

安装

通过Composer

$ composer require league/oauth2-client

贡献

请参阅CONTRIBUTING以获取详细信息。

许可证

MIT许可证(MIT)。有关更多信息,请参阅许可证文件