venveo / craft-oauthclient
简单的OAuth 2.0客户端
Requires
- craftcms/cms: ^3.1.34.3
- league/oauth2-client: ^2.2.1
- league/oauth2-facebook: ^2.0
- league/oauth2-github: ^2.0
- league/oauth2-google: ^2.2
README
此插件为开发者提供了一种简单集中化的方法来管理和存储OAuth 2.0客户端和令牌。
它提供了一个易于使用的API和前端,用于授权令牌以执行内部业务逻辑。但它不会作为认证提供者,让用户登录到CMS。
特性
- 用于集成League OAuth提供者的简单API
- 为开发者提供大量事件
- 用于刷新令牌的CLI
- 项目配置支持
- 在您的模块中生成认证UI的一行Twig辅助工具
示例用例
- 构建自定义CRM集成
- 从Google Sheets读取和写入
- 查询企业Facebook页面上的数据
示例非用例
- 在前端登录用户
- 允许用户通过社交账户访问CP
- 跟踪许多CMS用户的社交账户
要求
此插件应在Craft CMS 3.1.34.3或更高版本上运行
安装
要安装插件,请按照以下说明操作。
-
打开您的终端并转到您的Craft项目
cd /path/to/project
-
然后告诉Composer加载插件
composer require venveo/craft-oauthclient
-
在控制面板中,转到设置→插件,并点击OAuth 2.0客户端的“安装”按钮。
-
在Craft设置页面上配置
提供者
在此上下文中,提供者是一个通过令牌授权公开API的OAuth 2.0服务器。默认情况下,此插件附带以下提供者
- GitHub
插件利用了由thephpleague广泛使用的oauth2-client
项目,以尽可能轻松地添加提供者。我们为此抽象添加了一个额外的层,以混合Craft的要求。
创建提供者
假设您的服务已经存在一个League提供者,您可以轻松地创建自己的实现。在您的模块或插件中,为提供者创建一个文件并遵循以下大纲
<?php use League\OAuth2\Client\Provider\YOUR_PROVIDER_CLASS as LeagueProvider; use venveo\oauthclient\base\Provider; class MyProvider extends Provider { /** * @inheritDoc */ public static function displayName(): string { // This is what is displayed in the CP when registering an App return 'My Provider'; } public static function getProviderClass(): string { // Return the class name for the league provider return LeagueProvider::class; } }
现在您只需在插件或模块的初始化函数中注册它
```php <?php use venveo\oauthclient\services\Providers; use craft\events\RegisterComponentTypesEvent; use MyProvider; // [...] Event::on(Providers::class, Providers::EVENT_REGISTER_PROVIDER_TYPES, function (RegisterComponentTypesEvent $event) { $event->types[] = MyProvider:class });
一旦注册了提供者,您点击“注册新应用”时,它就会出现在控制面板的提供者下拉列表中。
上面的示例是注册提供者的基本方法。如果您需要,有许多方法可以覆盖和实现,以根据需要自定义提供者的授权流程。
有关此处的可能性,请参阅venveo\oauthclient\base\Provider
。
应用
在此插件中,应用表示已注册OAuth提供者的提供者的实现。大多数人可能只需要一个或两个,但您可以根据需要创建任意多个。要注册应用,您需要从提供者的网站开发选项开始,并创建一个OAuth 2.0应用程序。在某个时候,您将被要求提供登录流程的重定向URI。此URI由插件在应用注册后生成。您需要将其设置为临时值,直到保存应用 - 在此点,您需要将其更新为提供者。
在应用程序注册后,您应该能够访问OAuth应用程序概览页面,并单击应用程序列表右侧的“+”按钮来创建您的第一个令牌。
API使用
此插件假定您在模块或插件中执行实际逻辑。
该插件提供了以下服务
venveo\oauthclient\services\Apps
- 用于检索应用程序及其配置venveo\oauthclient\services\Credentials
- 用于检索和管理应用程序的令牌venveo\oauthclient\services\Providers
- 用于管理可用的提供者venveo\oauthclient\services\Tokens
- 用于管理令牌
通常,您只会使用Apps
和Credentials
服务。
控制认证流程
通常,您可能需要根据具体情况调整认证过程提供者的参数。例如,在某些情况下,您可能希望强制Google提示同意,以便您可以从先前认证的个人那里获取刷新令牌。如果您希望在用户通过应用程序的过程中调整请求的作用域,这也可能很有用。
通常,这可能意味着编写大量的重复代码;然而,我们通过在认证过程中引入“上下文”来解决这个问题。例如,我可能会使用Twig助手在我的模块中渲染一个连接器,并确保用户能够离线访问Google。我首先会使用上下文参数渲染我的连接器,然后在模块中注册事件处理程序来根据上下文调整认证URL。
控制面板中应用程序列表上的连接按钮的上下文是plugin.cp
事件
venveo\oauthclient\services\Apps
Apps:EVENT_BEFORE_APP_SAVED
venveo\oauthclient\events\AppEvent
Apps:EVENT_AFTER_APP_SAVED
venveo\oauthclient\events\AppEvent
Apps:EVENT_BEFORE_APP_DELETED
venveo\oauthclient\events\AppEvent
Apps:EVENT_AFTER_APP_DELETED
venveo\oauthclient\events\AppEvent
Apps:EVENT_GET_URL_OPTIONS
venveo\oauthclient\events\AuthorizationUrlEvent
venveo\oauthclient\services\Tokens
Tokens:EVENT_BEFORE_TOKEN_SAVED
venveo\oauthclient\events\TokenEvent
Tokens:EVENT_BEFORE_TOKEN_SAVED
venveo\oauthclient\events\TokenEvent
venveo\oauthclient\services\Credentials
Credentials:EVENT_BEFORE_REFRESH_TOKEN
venveo\oauthclient\events\TokenEvent
Credentials:EVENT_AFTER_REFRESH_TOKEN
venveo\oauthclient\events\TokenEvent
Credentials::EVENT_TOKEN_REFRESH_FAILED
venveo\oauthclient\events\TokenEvent
venveo\oauthclient\base\Provider
venveo\oauthclient\base\Provide::EVENT_CREATE_TOKEN_MODEL_FROM_RESPONSE
venveo\oauthclient\events\TokenEvent
venveo\oauthclient\controllers\AuthorizeController
venveo\oauthclient\controllers\AuthorizeController::EVENT_BEFORE_AUTHENTICATE
venveo\oauthclient\events\AuthorizationEvent
venveo\oauthclient\controllers\AuthorizeController::EVENT_AFTER_AUTHENTICATE
venveo\oauthclient\events\AuthorizationEvent
Twig变量
OAuth客户端插件提供了一个有用的Twig变量craft.oauth
,可以帮助您构建您的UI。
craft.oauth.getAppByHandle('handle')
如果存在,则返回App模型
命令行界面(CLI)
如果您想要刷新所有令牌,可以利用CLI来自动化此过程。
./craft oauthclient/apps/refresh-tokens <app handle>
如果存在错误,则返回状态码1,如果成功则返回0
示例
与Google Sheets交互
如果您想在Google Sheets账户中管理一些数据,可以轻松地要求Google_Client composer包并发出必要的请求;然而,令牌管理会增加很多开销和复杂性。这正是此插件发挥作用的地方。假设您已经包含了Google_Client,您可以像这样使用此插件
```php use venveo\oauthclient\Plugin; // [...] // Get the plugin instance. Note: make sure you do this after the application has been inited, such as in a route or // event. $plugin = Plugin::$plugin; // Let's grab a valid token - we could pass the current user ID in here to limit it $tokens = $plugin->credentials->getValidTokensForAppAndUser('google'); // Get the app from the apps service $app = $plugin->apps->getAppByHandle('google'); // Show time! Note: you should add some error checking. $client = new Google_Client(); $client->setAccessToken($tokens[0]->accessToken); $client->setClientId($app->getClientId()); $client->setClientSecret($app->getClientSecret()); $service = new Google_Service_Sheets($client); $sheet = $service->spreadsheets->get('some-google-sheet');
使用Twig变量检查当前用户是否已连接
{% set app = craft.oauth.getAppByHandle('google') %} {% if app %} {{ app.name }} {% set tokens = app.getValidTokensForUser() %} {% if tokens|length %} Connected! {% else %} {# This will render some boilerplate UI to connect the app #} {{ app.renderConnector() }} {% endif %} {% else %} Could not find app {% endif %}
有条件地修改认证流程
示例1:修改OAuth提供者设置
在此示例中,我们将使用上下文渲染连接器并注册事件以在渲染连接URL之前修改授权参数。
{% set app = craft.oauth.getAppByHandle('google') %} {{ app.renderConnector('cp') }} {# I can also just render the link URL #} {# Note: As of 2.1.9, a return URL may be sent as a paramter in getRedirectUrl() #} <a href="{{ app.getRedirectUrl('cp', craft.app.request.url) }}">Login</a>
use venveo\oauthclient\events\AuthorizationUrlEvent; use venveo\oauthclient\services\Apps; use yii\base\Event; // [...] Event::on(Apps::class, Apps::EVENT_GET_URL_OPTIONS, function (AuthorizationUrlEvent $e) { if ($e->context === 'cp' && $e->app->handle === 'google') { // Force re-consent during OAuth $e->options['prompt'] = 'consent'; $e->options['access_type'] = 'offline'; $e->options['approval_prompt'] = null; } });
示例2:根据上下文修改OAuth流程
如果我们想要调整用户认证后跳转的返回URL,我们有两种方法。第一种方法非常简单,使用了标准的Craft表单重定向。
<form method="post" action="{{ app.getRedirectUrl(context) }}"> {{ csrfInput() }} {# In this case, we'll just send the user back to this page #} {{ redirectInput(craft.app.request.url) }} <button type="submit" class="btn formsubmit">Connect</button> </form>
第二种情况更复杂,这时候我们没有表单,而只是有一个指向 app.getRedirectUrl()
的按钮。
由于这不是POST请求,我们需要使用 context
来修改流程。我们将我们的上下文命名为 "my-custom-context",并使用该上下文调用重定向URL。
<a href="{{ app.getRedirectUrl('my-custom-context') }}>Login</a>
现在在我们的模块或插件中,我们只需为AuthorizeController控制器注册一个事件处理器。
Event::on(AuthorizeController::class, AuthorizeController::EVENT_BEFORE_AUTHENTICATE, function (AuthorizationEvent $event) { if ($event->context === 'my-custom-context') { $event->returnUrl = 'https://google.com'; } });
成功了!现在登录后,用户将被发送到Google。
由 Venveo 提供