cirrusidentity/simplesamlphp-module-authoauth2

OAuth2认证源的SSP模块

安装次数: 62,473

依赖项: 0

建议者: 0

安全性: 0

星标: 31

关注者: 13

分支: 28

开放问题: 13

类型:simplesamlphp-module


README

Build Status

SimpleSAMLphp OAuth2认证源模块

这是一个用于对OAuth2或OIDC服务器进行认证的通用模块。它执行authorization_code流程,然后使用生成的访问令牌查询端点以获取用户的属性。它是围绕优秀的PHP League OAuth2 Client的包装。

SSP 2

SSP2的兼容性工作将在ssp2分支中完成。

SSP作为OIDC服务器

如果您对使用SSP作为OIDC OP感兴趣,请参阅OIDC模块

目录 DocToc生成

安装

该模块可以使用composer安装。

composer require cirrusidentity/simplesamlphp-module-authoauth2

如果您使用SSP 2,请使用版本4。如果您使用SSP 1.X,请使用版本3。

或者您可以从master分支安装最新版本

composer require cirrusidentity/simplesamlphp-module-authoauth2:dev-master

如果您将SSP安装到tar包分发的SSP中,那么composer默认还会安装SSP和此模块的所有dev依赖项。这可能是一个很长的列表。如果您不想安装dev依赖项,则可以使用。

composer require --no-update cirrusidentity/simplesamlphp-module-authoauth2 && composer update --no-dev cirrusidentity/simplesamlphp-module-authoauth2

变更日志

查看变更日志

用法

通用OAuth2客户端配置如下

  • OAuth2服务器端点
  • 客户端密钥/ID
  • 可选的scope参数
  • 可选的授权URL查询参数

重定向URI

几乎所有的OAuth2/OIDC供应商都会要求您注册重定向URI。使用以下形式的URL,并将主机名、SSP_PATH以及可选地端口设置为正确的值。

https://hostname/SSP_PATH/module.php/authoauth2/linkback.php

供应商特定提示

scope或scopes:可以传递哪些参数?

大多数配置项都通过到provider实现传递,因此将取决于您选择的供应商。如果您使用authsource authoauth2:OAuth2而没有覆盖providerClass,则“通用用法”中的选项将有效。如果您使用authoauth2:OpenIDConnect,则可用的配置选项集将不同。

scope与scopes:由authoauth2:OAuth2使用的默认供应商支持设置'scopes' => ['email']或通过在urlAuthorizeOptions中设置scope。其他供应商可能只支持后者(在urlAuthorizeOptions中设置)。

通用用法

通用用法提供了足够的配置参数,可以与任何OAuth2或OIDC服务器一起使用。

       'oauth2' => array(
              'authoauth2:OAuth2',
              // *** Required for all integrations ***
              'urlAuthorize' => 'https://www.example.com/oauth2/authorize',
              'urlAccessToken' => 'https://www.example.com/oauth2/token',
              'urlResourceOwnerDetails' => 'https://api.example.com/userinfo',
              // You can add query params directly to urlResourceOwnerDetails or use urlResourceOwnerOptions.
              'urlResourceOwnerOptions' => [
                 'fields' => 'id,name,first_name,last_name,email'
              ],
              // allow fields from token response to be query params on resource owner details request
              'tokenFieldsToUserDetailsUrl' => [
                   'fieldName' => 'queryParamName',
                   'access_token' => 'access_token',
                   'user_id' > 'user_id',
              ],
              // *** Required for most integrations ***
              // Test App.
              'clientId' => '133972730583345',
              'clientSecret' => '36aefb235314bad5df075363b79cbbcd',
              // *** Optional ***
              // Custom query parameters to add to authorize request
              'urlAuthorizeOptions' => [
                  'prompt' => 'always',
                  // The underlying OAuth2 library also supports overriding requested scopes
                  //'scope' => ['other']
              ],
              // Default scopes to request
              'scopes' => ['email', 'profile'],
              'scopeSeparator' => ' ',
              // Customize redirect, if you don't want to use the standard /module.php/authoauth2/linkback.php
              'redirectUri' => 'https://myapp.example.com/callback',
              // See League\OAuth2\Client\Provider\GenericProvider for more options
              
              // Guzzle HTTP config
              // Wait up to 3.4 seconds for Oauth2 servers to respond
              //http://docs.guzzlephp.org/en/stable/request-options.html#timeout 
              'timeout' => 3.4,
              // http://docs.guzzlephp.org/en/stable/request-options.html#proxy
              'proxy' => [
              ],
              
              // All attribute keys will have this prefix
              'attributePrefix' => 'someprefix.',
              // Enable logging of request/response. This *will* leak you client secret and tokens into the logs
              'logHttpTraffic' => true, //default is false
              'logMessageFormat' => 'A Guzzle MessageFormatter format string', // default setting is sufficient for most debugging
              'logIdTokenJson' => true, //default false. Log the json in the ID token.
              
          ),

OpenID Connect用法

对于支持OpenID Connect发现协议的供应商,配置可以简化一些。只需要提供发行者URL、客户端ID和客户端密钥。

不是所有来自 authoauth2:OAuth2 的配置选项都在 OpenIDConnect 中受支持

       'openidconnect' => array(
              'authoauth2:OpenIDConnect',
              // *** Required for all integrations ***
              'issuer' => 'https://www.example.com', # e.g https://#
              'clientId' => '133972730583345',
              'clientSecret' => '36aefb235314bad5df075363b79cbbcd',

              // Most Optional settings for OAuth2 above can be used
              // *** Optional ***
              // Customize post logout redirect, if you don't want to use the standard /module.php/authoauth2/loggedout.php
              'postLogoutRedirectUri' => 'https://myapp.example.com/loggedout'

              // Set a specific discovery url. Default is $issuer/.well-known/openid-configuration
              'discoveryUrl' => 'https://login.microsoftonline.com/common/.well-known/openid-configuration',
              // Check if the issuer in the ID token matches the one from discovery. Default true. For some multi-tenant
              // applications (for example cross tenant Azure logins) the token issuer varies with tenant
              'validateIssuer' => false,

              // Earlier version OpenIDConnect authsource doesn't support using `scopes` for overriding scope
              //'urlAuthorizeOptions' => [
              //    'scope' => 'openid'
              //]
          ),

如果你的 OP 支持前端单点登出,你可以配置 https://hostname/SSP_PATH/module.php/authoauth2/logout.php?authSource=AUTHSOURCE 其中 AUTHSOURCE 是你的 authsource 在 authsources 配置中的 id(如上例中的 openidconnect

供应商特定用法

有众多官方第三方提供商,你可以使用这些提供商而不是通用的 OAuth2 提供商。使用这些提供商之一可以简化配置。

要使用提供商,你必须首先安装它 composer require league/oauth2-some-provider 然后配置它。

    'providerExample' => array(
        // Must install correct provider with: composer require league/oauth2-example
        'authoauth2:OAuth2',
        'providerClass' => 'League\OAuth2\Client\Provider\SomeProvider',
        'clientId' => 'my_id',
        'clientSecret' => 'my_secret',
    ),

模板特定用法

对于某些 OAuth2 提供商,通用的端点配置已经定义在 ConfigTemplate 中。你可以参考这些来减少在 authsource 中需要输入的内容。

    'google' => array_merge(\SimpleSAML\Module\authoauth2\ConfigTemplate::GoogleOIDC, [
        'clientId' => '3473456456-qqh0n4b5rrt7vkapgk3e4osre40.apps.googleusercontent.com',
        'clientSecret' => 'shhh',
        'urlAuthorizeOptions' => [
            'hd' => 'example.com',
        ],
    ]),

或者使用模板选项

    'providerExample' => array(
        'authoauth2:OAuth2',
        'template' => 'GoogleOIDC',
        'clientId' => 'my_id',
        'clientSecret' => 'my_secret',
    ),

示例

这些示例中有几个展示了如何配置通用端点以验证 Facebook、Amazon 和 Google 等。在许多情况下,你可以从 ConfigTemplate 中使用模板来使配置更简洁,或者你可以使用特定于提供商的 OAuth2 客户端的基本实现。

通用Facebook

你可以使用 Facebook 模板 'template' => 'Facebook', 然后只需提供 clientIdclientSecret 以获得更简洁的配置。

    'templateFacebook' => [
       'authoauth2:OAuth2',
       'template' => 'Facebook',
        'clientId' => '13397273example',
        'clientSecret' => '36aefb235314baexample',
    ],
    'genericFacebookTest' => array(
        'authoauth2:OAuth2',
        // *** Facebook endpoints ***
        'urlAuthorize' => 'https://#/dialog/oauth',
        'urlAccessToken' => 'https://graph.facebook.com/oauth/access_token',
        // Add requested attributes as fields
        'urlResourceOwnerDetails' => 'https://graph.facebook.com/me?fields=id,name,first_name,last_name,email',
        // *** My application ***
        'clientId' => '13397273example',
        'clientSecret' => '36aefb235314baexample',
        'scopes' => 'email',
        // *** Optional ***
        // Custom query parameters to add to authorize request
        'urlAuthorizeOptions' => [
            // Force use to reauthenticate
            'auth_type' => 'reauthenticate',
        ],
    ),

通用Amazon

    'genericAmazonTest' => array(
        'authoauth2:OAuth2',
        // *** Amazon Endpoints ***
        'urlAuthorize' => 'https://www.amazon.com/ap/oa',
        'urlAccessToken' => 'https://api.amazon.com/auth/o2/token',
        'urlResourceOwnerDetails' => 'https://api.amazon.com/user/profile',
        // *** My application ***
        'clientId' => 'amzn1.application-oa2-client.94d04152358dexample',
        'clientSecret' => '8681bdd290df87example',
        'scopes' => 'profile',
    ),

通用Google

查看完整的 Google 指令

'genericGoogleTest' => array(
        'authoauth2:OAuth2',
        // *** Google Endpoints ***
        'urlAuthorize' => 'https://#/o/oauth2/auth',
        'urlAccessToken' => 'https://#/o/oauth2/token',
        'urlResourceOwnerDetails' => 'https://www.googleapis.com/oauth2/v3/userinfo',
        // *** My application ***
        'clientId' => '685947170891-exmaple.apps.googleusercontent.com',
        'clientSecret' => 'wV0FdFs_example',
        'scopes' =>  array(
            'openid',
            'email',
            'profile'
        ),
        'scopeSeparator' => ' ',
    ),

供应商特定Google

查看完整的 Google 指令

   'googleProvider' => array(
       // Must install correct provider with: composer require league/oauth2-google
       'authoauth2:OAuth2',
       'providerClass' => 'League\OAuth2\Client\Provider\Google',
       'clientId' => 'client_id',
       'clientSecret' => 'secret',
   ),

调试

HTTP日志记录

你可以使用 logHttpTraffic 标志启用 http 记录,并可选地使用 logMessageFormat 自定义格式。有关如何定义格式字符串的示例,请参阅 Guzzle 的 MessageFormatter 类。

安全提示:启用 http 记录会使你的客户端密钥和任何返回的访问或 id 令牌出现在你的日志中。

使用Curl

你可以使用命令行中的 curl 与 OAuth2/OIDC 服务器交互。

获取代码

第一步是获取一个有效的代码,并确保模块不会尝试使用它。这可以通过构建一个具有无效状态值但所有其他参数都正确的授权 URL 来完成。

https://as.example.com/openid/authorize?state=invalid-state&scope=openid&response_type=code&redirect_uri=https%3A%2F%2Fmyapp.example.com%2Fsimplesaml%2Fmodule.php%2Fauthoauth2%2Flinkback.php&client_id=my_client

如果你使用上述链接登录,它将带你回到你的 SSP 实例,并带有 authorization_code(你应该捕获)然后你的 SSP 实例将报告一个关于无效状态参数的错误。状态检查在消耗 authorization_code 之前发生,因此你知道 SSP 没有使用它。

获取访问令牌

现在你可以使用代码并尝试获取一个访问令牌

curl -d "code=REPLACE" \
    -d "client_secret=my_secret" \
    -d "client_id=my_client" \
    -d "redirect_uri=https://myapp.example.com/simplesaml/module.php/authoauth2/linkback.php" \
    -d 'grant_type=authorization_code' \
   https://as.example.com/openid/token

获取用户信息

使用上面的访问令牌调用用户信息端点

curl -H "Authorization: Bearer $ACCESS_TOKEN" https://as.example.com/userInfo

从现有认证模块迁移

如果你正在从现有的认证模块迁移,例如 authfacebook,你需要执行以下操作之一:

  • 将此模块的 authoauth2 重定向 URI 添加到 Facebook 应用中,或者
  • 覆盖 authoauth2 authsource 的重定向 URI 以匹配 authfacebook uri(https://myserver.com/module.php/authfacebook/linkback.php)并执行以下操作之一
    • 编辑 /modules/authfacebook/www/linkback.php 以有条件地调用 OAuth2ResponseHandler(见下文)
    • 配置 Apache 重写规则,将 '/module.php/authfacebook/linkback.php' 修改为 '/module.php/authoauth2/linkback.php'
    • 符号链接或编辑 /modules/authfacebook/www/linkback.php 以调用 /modules/authoauth2/public/linkback.php

一些社交提供商支持多种登录协议,并且旧版 SSP 模块可能使用非 OAuth2 版本进行登录。要迁移到此模块,你可能需要做一些应用程序更改。例如

  • LinkedIn 模块使用 oauth1,你可能需要调整你的应用程序以迁移到他们的 oauth2 API
  • 从 OpenID 2 Yahoo 登录迁移到 OIDC Yahoo 登录需要创建 Yahoo 应用。

调用OAuth2ResponseHandler

要从现有模块迁移,您可以调整该模块的linkback或重定向处理程序,使其条件性地使用OAuth2ResponseHandler。在以下示例中,如果进程是由authoauth2触发的,则代码将使用authoauth2,否则使用现有的处理程序。

$handler = new \SimpleSAML\Module\authoauth2\OAuth2ResponseHandler();
if ($handler->canHandleResponse()) {
   $handler->handleResponse();
   return;
 } 

开发

Docker

包含preprodwarning模块是为了测试authproc过滤器。注意: preprodwarning的1.0.2版本在重定向URL中存在一个错误。如果使用它,您需要将浏览器URL中的showwarning.php更改为warning

docker run --name ssp-oauth2-dev \
   --mount type=bind,source="$(pwd)",target=/var/simplesamlphp/staging-modules/authoauth2,readonly \
  -e STAGINGCOMPOSERREPOS=authoauth2 \
  -e COMPOSER_REQUIRE="cirrusidentity/simplesamlphp-module-authoauth2:@dev simplesamlphp/simplesamlphp-module-preprodwarning" \
  -e SSP_ADMIN_PASSWORD=secret1 \
  -e SSP_ENABLED_MODULES="authoauth2 preprodwarning" \
  --mount type=bind,source="$(pwd)/docker/config/authsources.php",target=/var/simplesamlphp/config/authsources.php,readonly \
  --mount type=bind,source="$(pwd)/docker/config/config-override.php",target=/var/simplesamlphp/config/config-override.php,readonly \
  -p 443:443 cirrusid/simplesamlphp:v2.0.7

然后访问(解析为localhost和Docker容器)测试认证源页面以测试一些预配置的社会集成(是的,您可以看到应用程序密码,这些应用程序仅用于此演示)。

Facebook测试用户

预配置的Facebook应用程序只能通过测试账户访问。您必须从Facebook注销,否则您将收到一个错误,说明应用程序未激活。

代码风格

运行phpcs来检查代码样式。

php vendor/bin/phpcs