adexos / m2-oauth2-league-bridge
Oauth2 League Magento2 代理
Requires
- php: >= 7.4
- firebase/php-jwt: ^6.0
- league/oauth2-client: ^2.6
- symfony/property-access: >=4.4
- symfony/serializer: >=4.4
README
本模块旨在成为OAuth 2实现与Magento 2之间的桥梁客户端连接。
安装
您可以通过以下命令进行安装: composer require adexos/m2-oauth2-league-bridge
如何使用?
创建自己的客户端,扩展桥接客户端
<?php declare(strict_types=1); namespace Adexos\MyIdentityOauthModule\Client; use Adexos\Oauth2LeagueBridge\Client\OauthClientFactory; class MyOauthIdentity extends OauthClientFactory { }
此类可以保持为空,它只需创建用于 di.xml
的目的。
然后您可以在 di.xml
中添加自己的配置
<type name="Adexos\MyIdentityOauthModule\Client\MyOauthIdentity"> <arguments> <argument name="baseUrlConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_BASE_URL </argument> <argument name="clientIdConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_CLIENT_ID </argument> <argument name="clientSecretConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_CLIENT_SECRET </argument> <argument name="authorizeEndpointConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_AUTHORIZE_ENDPOINT </argument> <argument name="accessTokenEndpointConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_ACCESS_TOKEN_ENDPOINT </argument> <argument name="resourceOwnerDetailsEndpointConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_RESOURCE_OWNER_DETAILS_ENDPOINT_CONFIG_PATH </argument> <argument name="persistence" xsi:type="object"> Adexos\Oauth2LeagueBridge\Persistence\SessionPersistence </argument> </arguments> </type>
路径引用您的配置。根据您提供的路径,您需要创建自己的 system.xml
。
可选:如果您想以加密方式存储客户端密钥,可以将 config.xml
和 system.xml
中的 backend_model 条目设置为 Magento\Config\Model\Config\Backend\Encrypted
。
示例
<!-- config.xml --> <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd"> <default> <adexos> <oauth2> <client_secret backend_model="Magento\Config\Model\Config\Backend\Encrypted"/> </oauth2> </adexos> </default> </config>
<!-- system.xml --> <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> <tab id="adexos_tab" translate="label" sortOrder="145"> <label>Adexos</label> </tab> <section id="adx" translate="label" sortOrder="300" showInDefault="1" showInWebsite="1" showInStore="1"> <class>separator-top</class> <label>Reach 5</label> <tab>adeo_tab</tab> <resource>Magento_Config::config</resource> <group id="oauth2_identity" translate="label" type="text" sortOrder="0" showInDefault="1" showInWebsite="1" showInStore="1"> <field id="client_secret" translate="label" type="obscure" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Client Secret</label> <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model> </field> </group> </section> </system> </config>
以下是一个示例模板
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> <tab id="adexos_tab" translate="label" sortOrder="145"> <label>Adexos</label> </tab> <section id="adx" translate="label" sortOrder="300" showInDefault="1" showInWebsite="1" showInStore="1"> <class>separator-top</class> <label>Reach 5</label> <tab>adeo_tab</tab> <resource>Magento_Config::config</resource> <group id="oauth2_identity" translate="label" type="text" sortOrder="0" showInDefault="1" showInWebsite="1" showInStore="1"> <label>[ADX Identity] Configuration</label> <field id="is_enabled" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Is enabled</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> <field id="base_url" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Base Endpoint URL</label> </field> <field id="client_id" translate="label" type="obscure" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Client ID</label> <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model> </field> <field id="client_secret" translate="label" type="obscure" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Client Secret</label> <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model> </field> <field id="public_key_jwt_token" translate="label" type="textarea" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>RSA Public Key to decode JWT Token properly and ensure security</label> </field> <field id="authorize_endpoint" translate="label" type="text" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Authorize Endpoint</label> </field> <field id="access_token_endpoint" translate="label" type="text" sortOrder="70" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Access Token Endpoint</label> </field> </group> </section> </system> </config>
请勿忘记创建一个 config.xml
。
最后,您可以这样使用它
<?php declare(strict_types=1); namespace Adexos\MyIdentityOauthModule\Http\Token; use Adexos\MyIdentityOauthModule\Client\MyOauthIdentity; use League\OAuth2\Client\Provider\Exception\IdentityProviderException; use Magento\Framework\Exception\LocalizedException; class IdentityTokenStrategy { private MyOauthIdentity $myOauthIdentity; public function __construct(MyOauthIdentity $myOauthIdentity) { $this->myOauthIdentity = $myOauthIdentity; } /** * @throws LocalizedException * @throws IdentityProviderException */ public function find(): ?string { $accessToken = $this->myOauthIdentity->getAccessTokenWithPersistence( new Password(), 'custom_identifier' ['username' => 'a', 'password' => 'b', 'scope' => 'custom_scopes'] ); if ($accessToken === null) { return null; } return $accessToken->getToken(); } }
当然,您需要根据需要更新 grant_type
和选项。作为第二个参数设置的标识符将用于根据您的配置将令牌持久化。
如果您现在想检索您的令牌并在存在的情况下使用刷新令牌更新它,您可以简单地调用
$accessToken = $this->myOauthIdentity->getCurrentTokenWithRefresh('custom_identifier');
缓存系统
本模块使用两个主要的缓存系统来存储OAuth令牌
- 会话缓存
- 驱动文件、Redis和数据库缓存的Magento本地缓存
会话缓存
此缓存特别适用于与Identity令牌(登录)一起使用,这些令牌必须存储在客户会话数据中,以下是实现方式
<type name="Adexos\MyIdentityOauthModule\Client\MyOauthIdentity"> <arguments> <argument name="baseUrlConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_BASE_URL </argument> <argument name="clientIdConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_CLIENT_ID </argument> <argument name="clientSecretConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_CLIENT_SECRET </argument> <argument name="authorizeEndpointConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_AUTHORIZE_ENDPOINT </argument> <argument name="accessTokenEndpointConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_ACCESS_TOKEN_ENDPOINT </argument> <argument name="resourceOwnerDetailsEndpointConfigPath" xsi:type="string"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_RESOURCE_OWNER_DETAILS_ENDPOINT_CONFIG_PATH </argument> <argument name="persistence" xsi:type="object"> Adexos\Oauth2LeagueBridge\Persistence\SessionPersistence </argument> </arguments> </type>
经典缓存
它使用Magento本地系统,因此您可以使用任何Magento支持的缓存:文件、Redis或数据库。
此缓存在您不需要在当前会话中存储令牌,而在更全局的上下文中(如管理令牌)存储令牌时更有用。
以下是实现方式
<type name="Adexos\MyManagementOauthModule\Client\MyOauthManagement"> <arguments> <argument name="baseUrlConfigPath" xsi:type="const"> Adexos\MyManagementOauthModule\Model\Config::XML_PATH_BASE_URL </argument> <argument name="clientIdConfigPath" xsi:type="const"> Adexos\MyManagementOauthModule\Model\Config::XML_PATH_CLIENT_ID </argument> <argument name="clientSecretConfigPath" xsi:type="const"> Adexos\MyManagementOauthModule\Model\Config::XML_PATH_CLIENT_SECRET </argument> <argument name="authorizeEndpointConfigPath" xsi:type="const"> Adexos\MyManagementOauthModule\Model\Config::XML_PATH_AUTHORIZE_ENDPOINT </argument> <argument name="accessTokenEndpointConfigPath" xsi:type="const"> Adexos\MyManagementOauthModule\Model\Config::XML_PATH_ACCESS_TOKEN_ENDPOINT </argument> <argument name="resourceOwnerDetailsEndpointConfigPath" xsi:type="string"> Adexos\MyManagementOauthModule\Model\Config::XML_PATH_RESOURCE_OWNER_DETAILS_ENDPOINT_CONFIG_PATH </argument> <argument name="persistence" xsi:type="object">AdexosManagementOauthPersistence</argument> </arguments> </type> <virtualType name="AdexosManagementOauthPersistence" type="Adexos\Oauth2LeagueBridge\Persistence\CachePersistence"> <arguments> <argument name="cache" xsi:type="object">AdexosManagementOauthDataCache</argument> </arguments> </virtualType> <virtualType name="AdexosManagementOauthDataCache" type="Magento\Framework\App\Cache"> <arguments> <argument name="cacheIdentifier" xsi:type="string">adexos_management_oauth_data_cache</argument> </arguments> </virtualType>
请注意,cacheIdentifier
将在 env.php
文件中使用以确定您如何存储令牌
数据库
env.php
'cache' => [ 'frontend' => [ 'adexos_management_oauth_data_cache' => [ 'backend' => \Magento\Framework\Cache\Backend\Database::class, 'backend_options' => [] ] ] ]
Redis
env.php
'cache' => [ 'frontend' => [ 'adexos_management_oauth_data_cache' => [ 'backend' => \Magento\Framework\Cache\Backend\Redis::class, 'backend_options' => [ 'server' => 'redis', 'database' => '3', 'port' => '6379', 'compress_data' => '1' ] ] ] ]
/!\ 请使用特定的数据库进行缓存,不要使用与会话相同的数据库。
文件
env.php
'cache' => [ 'frontend' => [ 'adexos_management_oauth_data_cache' => [ 'backend' => 'database', 'backend_options' => [] ] ] ]
缓存有效期
如果您需要为缓存添加特定的有效期(默认为1小时),您可以在 di.xml
中覆盖 specificLifetime
属性
<virtualType name="AdexosManagementOauthPersistence" type="Adexos\Oauth2LeagueBridge\Persistence\CachePersistence"> <arguments> <argument name="cache" xsi:type="object">AdexosManagementOauthDataCache</argument> <!-- 2 days --> <argument name="specificLifetime" xsi:type="number">172800</argument> </arguments> </virtualType>
标签
缓存根据标签进行分组。您可能希望指定标签以清理您创建的特定全局缓存区域。
在默认配置中,标签是: adx_oauth2_league_bridge
您可以通过更新 di.xml
中的 tags
属性来覆盖它
<virtualType name="AdexosManagementOauthPersistence" type="Adexos\Oauth2LeagueBridge\Persistence\CachePersistence"> <arguments> <argument name="cache" xsi:type="object">AdexosManagementOauthDataCache</argument> <!-- 2 days --> <argument name="specificLifetime" xsi:type="number">172800</argument> <argument name="tags" xsi:type="array"> <item name="fstTag" xsi:type="string">my_first_tag</item> <item name="sndTag" xsi:type="string">my_second_tag</item> </argument> </arguments> </virtualType>
您可以添加您想要的许多标签。
解码令牌
在获取令牌后,您可以对其进行解码,它还将使用公钥进行验证以确保接收到的令牌的完整性
$jwtResponse = $this->client->getAccessTokenWithPersistence( new Password(), IdentityTokenStrategy::OAUTH_TOKEN_CACHE_IDENTIFIER, ['username' => $username, 'password' => $password, 'scope' => self::TOKEN_SCOPE] ); $this->jwtDecoder->decode( $token->getValues()['id_token'], IdTokenDTO::class, $this->scopeConfig->getValue(Config::XML_PATH_PUBLIC_KEY_JWT_TOKEN) );
jwtDecoder
类是 Adexos\Oauth2LeagueBridge\Decoder\JwtDecoder
作为 decode
方法的第二个参数,您必须传递一个实现 Adexos\Oauth2LeagueBridge\Decoder\Model\JwtResultInterface
的 DTO,这是令牌的内容表示。之后,您可以通过一个对象来操作令牌结果,并执行您想要的任何操作。
替代选项提供程序(HttpBasicAuth/PostAuth)
关于访问令牌的凭据的默认选项提供程序是 PostAuthOptionProvider
。
然而,在一些系统中,您可能需要使用 HttpBasicAuthOptionProvider
或自定义提供程序。
您只需将其添加到客户端的 di.xml
中即可。
<type name="Adexos\MyIdentityOauthModule\Client\MyOauthIdentity"> <arguments> <argument name="baseUrlConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_BASE_URL </argument> <argument name="clientIdConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_CLIENT_ID </argument> <argument name="clientSecretConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_CLIENT_SECRET </argument> <argument name="authorizeEndpointConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_AUTHORIZE_ENDPOINT </argument> <argument name="accessTokenEndpointConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_ACCESS_TOKEN_ENDPOINT </argument> <argument name="resourceOwnerDetailsEndpointConfigPath" xsi:type="const"> Adexos\MyIdentityOauthModule\Model\Config::XML_PATH_RESOURCE_OWNER_DETAILS_ENDPOINT_CONFIG_PATH </argument> <argument name="persistence" xsi:type="object"> Adexos\Oauth2LeagueBridge\Persistence\SessionPersistence </argument> <argument name="optionProvider" xsi:type="object"> League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider </argument> </arguments> </type>
如果您需要实现自己的身份验证提供程序,只需创建一个实现 League\OAuth2\Client\OptionProvider\OptionProviderInterface
的类。