p7s1-ctf/7pass-php-sdk

此软件包已被弃用且不再维护。未建议替代软件包。

PHP 7Pass SDK

维护者

详细信息

github.com/p7s1-ctf/7pass-php-sdk

主页

安装: 27 566

依赖: 0

建议: 0

安全: 0

星级: 1

关注者: 15

分支: 1

2.0.2 2017-10-24 11:03 UTC

This package is not auto-updated.

Last update: 2020-08-25 13:22:31 UTC


README

Latest Stable Version

7Pass PHP SDK 是一个用于与 7Pass SSO 服务 交互的 PHP 库。您可以使用此库来实现您网站的认证,并利用 7Pass SSO 提供的现有功能。

安装

在开始使用库之前,请确保您的系统满足所需的条件。目前,该库需要 PHP 5.5.0 及以上版本,并支持 cURL。

注意:生产环境和 qa 环境只接受 TLS v1.2 连接 - 请确保您的系统 cURL 库支持它,否则会抛出 SSL connect error 异常。

该库以 composer 包的形式分发。如果您还没有安装,请使用 Composer 的官方说明进行安装。安装 Composer 后,您可以通过以下方式安装库

$ composer require p7s1-ctf/7pass-php-sdk

这将自动将库添加到您应用程序依赖项列表中。

运行示例应用程序

为了演示库的功能,有一个交互式教程/指南可用。在开始设置之前,您需要您的 Web 应用程序客户端。客户端代表您想要认证的服务关联的实体。

要获取客户端凭据,您首先需要联系 7Pass 技术团队。

一旦您有了可用的凭据,您就可以继续安装依赖项

$ composer install

接下来,您可以转到 public_html 目录并创建本地配置文件

$ cd public_html
$ cp config.local.php.example config.local.php

使用您最喜欢的编辑器编辑 config.local.php 文件并填写详细信息。在客户端设置完成后,您应该可以使用所有参数。为了测试,请将环境设置为 qa。完成后,您可以使用 PHP 内置服务器启动应用程序

$ php -S localhost:8000

示例应用程序现在应在 https://:8000 上可用。应用程序将引导您了解库的常见用法,并在过程中展示代码示例和服务器响应。

API 使用

强烈建议您首先查看示例应用程序。它将显示带有更多注释和实际值的 API 调用。随着您的前进,它还将显示 7Pass SSO 服务的真实响应。

要使用库,必须使用我们想要使用的客户端的凭据对其进行初始化。如果您还没有凭据,请参阅上文。

  • client_id(必需)
  • client_secret(必需)

如果您开始开发,始终建议您针对 7Pass SSO 服务的非实时实例进行工作。要指定您想要发出请求的实例(环境),您可以将一个额外的键名为 environment 传递给配置。目前运行有两个环境:QA 和生产。在您将应用程序发布给公众之前,别忘了切换到生产版本。

$config = [
  'client_id' => 'YOUR_CLIENT_ID',
  'client_secret' => 'YOUR_CLIENT_SECRET',
  'environment' => 'qa' // Optional, defaults to 'production'
];

// Creates the configuration object
$ssoConfig = new P7\SSO\Configuration($config);

// Pass the configuration to the SSO object
$sso = new P7\SSO($ssoConfig);

对于这两种环境,都有一个默认的 host URL,7Pass API 端点可以通过它访问。对于 生产 环境,它是 https://sso.7pass.de,而对于 qa 环境,主机为 https://sso.qa.7pass.ctf.prosiebensat1.com。如果需要,可以通过在配置中指定 host 来覆盖它,如下所示

$config = [
    'host' => 'https://mysubdomain.7pass.de'
    // ... other config values
];

认证流程

认证过程很简单,其高级视图如下:用户通过一个特别定制的 URL 被重定向到 7Pass SSO 服务并登录(或注册)。一旦用户完成流程,他们将被带回到您的应用程序,URL 中有一个特殊代码。然后应用程序将使用该代码来获取用户详细信息。具体流程可能因传递的选项而异。

1. 获取重定向 URL

库会自动处理生成用户需要重定向到的 URL。唯一的必需参数是 redirect_uri URL。该 URL 需要是绝对路径,可以是任意的(只要它在客户端注册了),但根据惯例应指向同一主机和一个名为 "callback" 的路由。

state 参数的使用是可选的但推荐使用,以避免 CSRF 攻击——该值通常存储在会话中,并在处理回调请求时与 $sso->authorization()->callback() 方法一起使用。

$callbackUri = 'https://example.com/callback';
$options = [
  'redirect_uri' => $callbackUri, // Required.
  'scope' => 'openid profile email', // Optional, default value.
  'response_type' => 'code' // Optional, default value.
  'state' => $sessionState // Optional, but recommended to avoid CSRF attacks
];

$redirectUrl = $sso->authorization()->authorizeUri($options);

库将自动设置 client_idnonce(一个唯一的请求标识符)参数。

2. 重定向用户

现在需要将用户重定向到生成的 URL。在纯 PHP 中,你可以设置 Location 头部

header('Location: ' . $redirectUrl);
exit;

3. 处理 7Pass 回调

用户完成登录/注册对话框后,他们会被重定向到重定向 URI URL,并带有登录过程的成果。用户可能已成功认证,也可能选择取消流程或发生其他错误。因此,适当的错误处理很重要。

无论何时发生错误,URL 中都会出现两个查询参数 - error 和 error_description。error 参数包含错误代码,error_description 包含对错误的可读描述。处理错误并向最终用户显示适当的消息。

你可以选择如下手动处理错误。否则,如果发生错误,调用 $sso->authorization()->callback() 方法将抛出 AuthorizeCallbackException

if(!empty($_GET['error'])) {
  $error = $_GET['error'];
  $errorDescription = $_GET['error_description'];

  // Handle the error and display appropriate message to your end-user.
}

库会自行处理检索令牌,你只需要提供 redirect_uri 以及来自请求的查询参数,这些参数应包括 code。这允许你检索可用于稍后获取有关用户实际信息的令牌。这些令牌对特定用户是特定的,并且是私有的。你需要确保它们的安全,不要与任何人分享。

$sessionState 参数是可选的,但如果与 $sso->authorization()->authorizeUri() 方法一起使用,则应提供相同的值。当提供的 state 值与从查询参数 $_GET 中检索的值不匹配时,将抛出 AuthorizeCallbackException

$tokens = $sso->authorization()->callback($callbackUri, $_GET, $sessionState);

接收到的响应将具有以下结构。运行示例应用程序以查看实际值。

P7\SSO\TokenSet(
    [access_token] => ACCESS_TOKEN
    [token_type] => 'Bearer'
    [refresh_token] => REFRESH_TOKEN
    [expires_in] => 7200
    [id_token] => JWT_STRING
    [id_token_decoded] => DECODED_JWT,
    [received_at] => RECEIVED_AT_TIMESTAMP
)

注意:从id_token字段解码并验证id_token_decoded值。如果令牌验证失败,将抛出P7\SSO\Exception\TokenVerificationException异常。

此外,如果code已经被使用或无效,调用可能会抛出P7\SSO\Exception\ApiException异常。

4. 缓存访问令牌

令牌以类型为P7\SSO\TokenSet的单个对象表示。您可以直接序列化该对象,但我们建议您首先将TokenSet转换为更简单的数组对象,并对其进行序列化。一旦需要再次使用TokenSet,您可以将数组对象传递给其构造函数。

// Serialize the TokenSet object and store it in e.g. the current session
$_SESSION['tokens'] = $tokens->getArrayCopy();

// Deserialize and get the TokenSet object again
$tokens = new \P7\SSO\TokenSet($_SESSION['tokens']);

访问令牌的有效期为expires_in字段中指定的秒数。一旦访问令牌过期,它就无法再使用。您可以使用以下方式使用刷新令牌获取新的令牌

if($tokens->isAccessTokenExpired()) {
  $tokens = $sso->authorization()->refresh([
    'refresh_token' => $tokens->refresh_token
  ]);
}

注意:上述refresh()方法也接受P7\SSO\TokenSet对象作为参数。

5. 调用我们的API端点

既然我们已经确认令牌是最新的,我们就可以开始向7Pass SSO服务发送请求以获取用户数据。

与前面的示例相同,运行示例应用程序以查看实际的服务器响应。

$accountClient = $sso->accountClient($tokens);
$response = $accountClient->get('me');

7Pass SSO服务提供了相当多的这些端点。要了解更多信息,您可以访问官方文档的概述

客户端凭据请求

库支持多种类型的“客户端”。这些客户端通常在所需的配置参数以及之后的功能上有所不同。“客户端凭据”客户端是一种特殊的客户端,它不与用户账户相关联,只能用于调用“客户端”API。

您可以在文档中查看所有可用的端点,其中accessType参数等于client

$config = [
  'environment' => 'qa', // Optional, defaults to 'production',
  'client_id' => 'CLIENT_ID',
  'client_secret' => 'CLIENT_SECRET'
];

// Creates the configuration object
$ssoConfig = new P7\SSO\Configuration($config);

// Pass the configuration to the SSO object
$sso = new P7\SSO($ssoConfig);

// Get the tokens using the client credentials grant type
$tokens = $sso->authorization()->clientCredentials();

// Use the client
$client = $sso->clientCredentialsClient($tokens);
$response = $client->post('checkPassword', [
  'password' => 'PASSWORD'
]);

设备流程

通过设备流程,人们可以轻松、安全地使用7Pass账户在输入或显示功能有限的设备上登录应用程序和服务。这包括智能电视、数字相框或物联网设备。

设备(您的应用程序)指示最终用户使用另一台计算机或设备连接到7Pass以批准访问请求。由于您的应用程序无法接收传入的请求,它将反复轮询7Pass授权服务器,直到最终用户完成批准过程。

您的应用程序通过向令牌端点发出HTTP POST请求以从授权服务器请求一组验证码来启动流程。

$deviceCodeResponse = $sso->authorization()->deviceCode();

$deviceCodeResponse将是如下所示的stdClass对象

stdClass(
    [code] => CODE         // used along with poll requests (see below)
    [user_code] => Q9CFLH  // the code which user should enter on LINK page 
    [expires_in] => 600    // expiration of the code (in seconds) 
    [interval] => 5        // recommended interval for repeating poll requests (in seconds)
    [link] => LINK_URL     // verification URL user should use to authenticate
    [link_qr] => IMAGE_URL // image URL of QR code encoded link
)

现在应提示用户访问另一个设备上的link URL以输入user_codelink_qr是表示QR代码的link URL的图像的URL。这可以供使用移动设备的用户使用,他们可以扫描它,并在他们的移动浏览器中打开link URL,而无需手动输入。

当用户尝试在link URL上进行身份验证时,您的应用程序将反复轮询7Pass服务器。建议的间隔由interval值指定。

以下示例中的$code可以是来自$sso->authorization()->deviceCode()方法调用的$deviceCodeResponse对象,包含code项的数组,或者简单地是一个包含code值的字符串。

// repeat every [interval] seconds.
try {
    $response = $sso->authorization()->deviceCodePoll($code);
    if($response instanceof \P7\SSO\TokenSet) {
        // stop polling - user has authorized from another device successfully
    }
    // $reponse === false in case 'authorization_pending' response is received
} catch(ApiException $e) {
    // handle the error appropriately
    // $e->getError() is set to one of error codes 'code_expired', 'slow_down', 'invalid_grant'
}

后台请求

库也可以用来执行“后台”请求。这些请求无需用户直接参与,旨在用于管理目的。您的客户端需要允许backoffice_code授权类型。您还需要知道您要与之工作的用户的ID。

后台请求用于代表其他用户进行API调用。要获取这些请求的访问令牌,您需要使用特殊的授权类型'backoffice_code'并提供account_id。在成功验证后,您将获得与使用上述标准流程相同的令牌集。

$config = [
  'environment' => 'qa' // Optional, defaults to 'production',
  'service_id' => 'SERVICE_ID', // Required for backoffice access
  'backoffice_key' => 'BACKOFFICEC_KEY' // Required for backoffice access
];

// Creates the configuration object
$ssoConfig = new P7\SSO\Configuration($config);

// Pass the configuration to the SSO object
$sso = new P7\SSO($ssoConfig);

// Get the tokens using the backoffice
$tokens = $sso->authorization()->backoffice([
  'account_id' => 'account_id' // Required, the ID of the user you want to access
]);

// Use the client as you normally would when using the standard access
$accountClient = $sso->accountClient($tokens);
$response = $accountClient->get('me');

响应将像往常一样。一旦您获得令牌,7Pass SSO服务将表现得就像使用“标准”方式获得了访问令牌。

客户端/后台注册

当您使用客户端或后台注册API注册新用户时,您可能希望将他们重定向到7Pass SSO服务,以便创建用户的会话并登录用户。

此SDK提供了一个名为autologinUri()的方法,可以用来生成重定向(跳转)URL。该方法接受一个TokenSet作为其第一个参数。您可以通过提供scope参数在使用注册API时检索用户的令牌。有关更多详细信息,请参阅注册API文档。response_type默认为none,但根据需要可以设置为任何其他支持类型

// $client is an instance of ApiClient created using $sso->clientCredentialsClient() or $sso->backofficeClient() methods.
$response = $client->post('registration', [
    'scope' => 'openid profile email'
    // other parameters
]);
$tokens = TokenSet::receiveTokens($response);

$callbackUri = 'https://example.com/callback';

$uri = $sso->authorization()->autologinUri($tokens, [
    'redirect_uri' => $callbackUri, // Required
    'state' => $sessionState // Optional but recommended to use
], [
    'remember_me' => true // Default value: false
])

// Redirect user to $uri

与其他普通授权请求一样,您可以使用Authorization::callback()方法来处理回调请求。如果response_type被设置为none,则该方法返回null

$tokens = $sso->authorization()->callback($callbackUri, $_GET, $sessionState);

缓存

在库能正常工作之前,它需要从配置的7Pass SSO服务的实例中获取OpenID配置。为了确保信息不会每次都下载,库使用可配置的缓存机制。

默认的过期时间为1小时,可以通过向$config设置(以秒为单位)传递cache_config_openid_ttl值来自定义。

库内部会从传递给配置构造函数的所有参数中计算出一个哈希值,并将其用作配置的缓存键。这意味着如果配置发生变化,库将自动重新发现配置。

然而,请注意,如果配置被改回某些先前使用过的状态,并且计算出的配置的键对应于现有的缓存项,您可能会得到一个过时的配置。如果您预计远程OpenID配置会发生变化,您可以清除缓存并让库自行重新发现它,或者您可以有条件地运行rediscover()方法。

在底层,它使用了Stash Caching Library库,并尝试首先使用Apc驱动。如果不可用,它将使用Filesystem驱动

如果需要,您可以按照以下方式配置自己的缓存驱动程序

$config = [
    // ... other configuration settings
    'cache_config_openid_ttl' => 3600 // sets cache expiration time to 1 hour
];
$ssoConfig = new P7\SSO\Configuration($config);

$driver = new Stash\Driver\Memcache(['servers' => ['127.0.0.1', '11211']]);
$ssoConfig->setCachePool(new Stash\Pool($driver));

$sso = new P7\SSO($ssoConfig);

要手动刷新缓存,请使用rediscover方法。在正常情况下,通常不需要这样做。

$sso->getConfig()->rediscover();

如果您有任何疑问或发现某些功能不符合预期,请随时联系7Pass技术团队。

运行测试

该库使用PHPUnit进行测试。推荐版本为4.8,尽管测试也可能在4系列较旧版本上成功运行。

$ composer install
$ ./vendor/bin/phpunit