bigfork/silverstripe-oauth

SilverStripe OAuth2认证,基于PHP League的OAuth2客户端

安装次数: 72,787

依赖者: 1

建议者: 0

安全性: 0

星标: 9

关注者: 7

分支: 11

开放问题: 2

类型:silverstripe-vendormodule

2.2.2 2024-07-26 08:05 UTC

This package is auto-updated.

Last update: 2024-08-26 08:21:29 UTC


README

SilverStripe OAuth2认证,基于PHP League的OAuth2客户端

本模块的功能

此模块包括获取访问令牌的基本功能。它提供向OAuth提供者创建请求、使用各种范围/权限获取访问令牌以及为处理返回的令牌注册处理程序的方法。

本模块不做什么

此模块不提供“通过 <提供者> 登录”按钮、“从 <提供者> 获取联系人”按钮或与其他提供者交互的任何其他功能 - 它只获取允许您执行此操作的令牌。您需要安装适当的第三方提供者包,并实现利用访问令牌从这些提供者获取数据的功能。

如果您正在寻找“通过 <提供者> 登录”功能,请查看此模块的附加组件:SilverStripe OAuth Login

此模块也不在数据库中存储访问令牌。如果这是您应用程序的要求,您需要构建自己的模型来处理此问题,并设置适当的令牌处理程序。

安装

必须使用composer安装此模块。在命令行中运行composer require bigfork/silverstripe-oauth:*,然后运行dev/build

配置

使用SilverStripe的YAML配置将提供者注册为Injector服务。这允许您指定“内部”名称(在URL和会话数据中传递),提供者的PHP类(扩展League\OAuth2\Client\Provider\AbstractProvider)以及构造函数参数和类属性。

例如,要设置Facebook作为提供者,首先安装Facebook OAuth2包,然后向您的YAML配置中添加以下内容

SilverStripe\Core\Injector\Injector:
  Bigfork\SilverStripeOAuth\Client\Factory\ProviderFactory:
    properties:
      providers:
        'Facebook': '%$FacebookProvider'
  FacebookProvider:
    class: 'League\OAuth2\Client\Provider\Facebook'
    constructor:
      Options:
        clientId: '12345678987654321'
        clientSecret: 'geisjgoesingoi3h1521onnro12rin'
        graphApiVersion: 'v2.6'

注意,在上面的示例中,缺少必要的redirectUri构造函数参数。此模块将自动更新服务配置,为所有提供者添加此参数,以节省在环境/域名之间移动时更新URL的需要。如果存在redirectUri参数,则不会覆盖它。

使用方法

如果您正在寻找“通过 <提供者> 登录”功能,请查看此模块的附加组件:SilverStripe OAuth Login

为了实际与OAuth令牌交互,您需要在回调过程中注册一个令牌处理程序(实现Bigfork\SilverStripeOAuth\Client\Handler\TokenHandler),以执行此操作。每个处理程序都有一个可选的数字优先级(用于控制它们被调用的顺序),以及一个“上下文”。上下文选项用于确保处理程序仅在执行某些操作时运行,并匹配在发行令牌请求时指定的上下文参数(请参阅辅助部分)。注册上下文为*的处理程序将始终被调用,无论提供的上下文如何。

以下是一个负责从用户Facebook个人资料获取事件并注册它的令牌处理程序的示例。我们使用上下文参数来确保处理程序仅在执行此操作时运行(例如,我们不希望在用户登录时运行它)。

在这里,我们注册了一个名为 import_events 的上下文的令牌处理器。

Bigfork\SilverStripeOAuth\Client\Control\Controller:
  token_handlers:
    importeventshandler:
      priority: 1
      context: 'import_events'
      class: 'ImportEventsHandler'

接下来,我们需要构建一个指定该上下文的授权 URL。

use Bigfork\SilverStripeOAuth\Client\Helper\Helper;

// Build a URL for fetching a Facebook access token with the required 'user_events' permission
// Will return a URL like: http://mysite.com/oauth/authenticate/?provider=Facebook&context=import_events&scope%5B2%5D=user_events
$url = Helper::buildAuthorisationUrl('Facebook', 'import_events', ['user_events']);
echo "<a href=" . $url . ">Import events from Facebook</a>";

当用户从 Facebook 返回时,我们的令牌处理器将在回调过程中被调用。

use Bigfork\SilverStripeOAuth\Client\Handler\TokenHandler;
use League\OAuth2\Client\Provider\Facebook;
use League\OAuth2\Client\Token\AccessToken;

class ImportEventsHandler implements TokenHandler
{
    public function handleToken(AccessToken $token, Facebook $provider)
    {
        $baseUrl = 'https://graph.facebook.com/v2.8';
        $params = http_build_query([
            'fields' => 'id,name,start_time',
            'limit' => '5',
            'access_token' => $token->getToken(),
            'appsecret_proof' => hash_hmac('sha256', $token->getToken(), '{facebook-app-secret}'),
        ]);
        $response = file_get_contents($baseUrl.'/me/events?'.$params);
        $data = json_decode($response, true);

        $this->importEvents($data);
    }
}

handleToken() 方法抛出异常将导致所有其他处理器被取消,异常信息将被记录,并向用户显示一个 "400 Bad Request" 错误页面。该方法还可以返回一个 SS_HTTPResponse 实例,该实例将在所有剩余处理器运行后输出到浏览器。

错误处理

有时,OAuth 提供商可能会返回由用户引起的错误。最常见的例子是当用户拒绝授予您请求的权限时。由于每个提供商以不同的方式提供错误消息,您需要构建自己的错误处理逻辑。错误处理器可以像令牌处理器一样注册,例如

Bigfork\SilverStripeOAuth\Client\Control\Controller:
  error_handlers:
    importeventserrorhandler:
      priority: 1
      context: 'import_events'
      class: 'ImportEventsErrorHandler'
use Exception;
use League\OAuth2\Client\Provider\AbstractProvider;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Security\Security;

class ImportEventsErrorHandler implements ErrorHandler
{
    public function handleError(AbstractProvider $provider, HTTPRequest $request, Exception $exception)
    {
        if ($request->getVar('error_message')) {
            return Security::permissionFailure(null, $request->getVar('error_message'));
        }
    }
}

错误记录

默认情况下,致命的 OAuth 错误将被记录到 PHP 的错误日志中。您可以通过覆盖 Psr\Log\LoggerInterface.oauth: 注入器服务定义来设置自己的日志记录。例如,要将错误记录到 oauth.log 文件中

---
After: silverstripe-oauth-logging
---
SilverStripe\Core\Injector\Injector:
  Psr\Log\LoggerInterface.oauth:
    calls: null # Reset - without this, the below "calls" would be merged in instead of replacing the original
---
After: silverstripe-oauth-logging
---
SilverStripe\Core\Injector\Injector:
  Psr\Log\LoggerInterface.oauth:
    calls:
      pushDisplayErrorHandler: [ pushHandler, [ '%$OAuthLogFileHandler' ] ]
  OAuthLogFileHandler:
    class: Monolog\Handler\StreamHandler
    constructor:
       - '../oauth.log'
       - 'error'

SameSite / POST cookies

一些提供商,如 Apple,将使用 POST 请求重定向回您的网站。当这种情况发生时,默认的浏览器行为是不将cookie与请求一起发送,这意味着无法验证请求,因为用户的会话已丢失。有两种方法可以解决这个问题

  1. 按照以下方式标记您的会话cookie为 SameSite=None; Secure,详情请见 这里
  2. 设置以下 YAML 值
Bigfork\SilverStripeOAuth\Client\Control\Controller:
  enable_samesite_workaround_redirect: true

当此功能启用时,您的网站将处理从 OAuth 提供商接收到的 POST 请求,通过重定向用户进行 GET 请求。当发出此 GET 请求时,网站再次可以访问用户的会话 cookie,因此授权过程可以像平常一样继续。