mperusso/openid-connect-php

简易的 OpenID Connect 客户端

v1.1.0 2024-07-11 12:59 UTC

This package is auto-updated.

Last update: 2024-09-11 13:23:02 UTC


README

这是一个简单的库,允许应用程序通过基本的 OpenID Connect 流进行用户身份验证。这个库希望通过使其足够简单,以便对 OpenID Connect 协议了解不多的开发者能够设置身份验证来鼓励使用 OpenID Connect。

特别感谢 Justin Richer 和 Amanda Anganes 对该协议的帮助和支持。

要求

  1. PHP 7.0 或更高版本
  2. CURL 扩展
  3. JSON 扩展

安装

  1. 使用 composer 安装库
composer require jumbojett/openid-connect-php
  1. 包含 composer 自动加载器
require __DIR__ . '/vendor/autoload.php';

示例 1:基本客户端

use Jumbojett\OpenIDConnectClient;

$oidc = new OpenIDConnectClient('https://id.provider.com',
                                'ClientIDHere',
                                'ClientSecretHere');
$oidc->setCertPath('/path/to/my.cert');
$oidc->authenticate();
$name = $oidc->requestUserInfo('given_name');

查看 openid 规范以获取可用用户属性

示例 2:动态注册

use Jumbojett\OpenIDConnectClient;

$oidc = new OpenIDConnectClient("https://id.provider.com");

$oidc->register();
$client_id = $oidc->getClientID();
$client_secret = $oidc->getClientSecret();

// Be sure to add logic to store the client id and client secret

示例 3:网络和安全

// Configure a proxy
$oidc->setHttpProxy("http://my.proxy.com:80/");

// Configure a cert
$oidc->setCertPath("/path/to/my.cert");

示例 4:请求客户端凭证令牌

use Jumbojett\OpenIDConnectClient;

$oidc = new OpenIDConnectClient('https://id.provider.com',
                                'ClientIDHere',
                                'ClientSecretHere');
$oidc->providerConfigParam(['token_endpoint'=>'https://id.provider.com/connect/token']);
$oidc->addScope(['my_scope']);

// this assumes success (to validate check if the access_token property is there and a valid JWT) :
$clientCredentialsToken = $oidc->requestClientCredentialsToken()->access_token;

示例 5:请求资源所有者令牌(带有客户端身份验证)

use Jumbojett\OpenIDConnectClient;

$oidc = new OpenIDConnectClient('https://id.provider.com',
                                'ClientIDHere',
                                'ClientSecretHere');
$oidc->providerConfigParam(['token_endpoint'=>'https://id.provider.com/connect/token']);
$oidc->addScope(['my_scope']);

//Add username and password
$oidc->addAuthParam(['username'=>'<Username>']);
$oidc->addAuthParam(['password'=>'<Password>']);

//Perform the auth and return the token (to validate check if the access_token property is there and a valid JWT) :
$token = $oidc->requestResourceOwnerToken(TRUE)->access_token;

示例 6:基本客户端用于隐式流,例如与 Azure AD B2C(请参阅 http://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth

use Jumbojett\OpenIDConnectClient;

$oidc = new OpenIDConnectClient('https://id.provider.com',
                                'ClientIDHere',
                                'ClientSecretHere');
$oidc->setResponseTypes(['id_token']);
$oidc->setAllowImplicitFlow(true);
$oidc->addAuthParam(['response_mode' => 'form_post']);
$oidc->setCertPath('/path/to/my.cert');
$oidc->authenticate();
$sub = $oidc->getVerifiedClaims('sub');

示例 7:访问令牌的审查(请参阅 https://tools.ietf.org/html/rfc7662

use Jumbojett\OpenIDConnectClient;

$oidc = new OpenIDConnectClient('https://id.provider.com',
                                'ClientIDHere',
                                'ClientSecretHere');
$data = $oidc->introspectToken('an.access-token.as.given');
if (!$data->active) {
    // the token is no longer usable
}

示例 8:PKCE 客户端

use Jumbojett\OpenIDConnectClient;

$oidc = new OpenIDConnectClient('https://id.provider.com',
                                'ClientIDHere',
                                null);
$oidc->setCodeChallengeMethod('S256');
$oidc->authenticate();
$name = $oidc->requestUserInfo('given_name');

示例 9:反向通道注销

反向通道身份验证假设您可以在服务器端代表用户结束会话(而不依赖于他们的浏览器)。请求是从 OP 直接到您的 RP 的 POST 请求。通过这种方式,使用此库可以确保您的 RP 即使用户没有在浏览器或其他设备上打开您的 RP,但仍然在那里有一个活动会话,也能为用户执行“单点注销”。

注销令牌中可能可访问 sid 或 sub。您可以使用 getSidFromBackChannel()getSubjectFromBackChannel() 来检索它们,如果有帮助将其与一个会话匹配以便销毁它。

以下确保使用此库验证反向通道注销令牌,但之后只是一个假设的方法来查找这样的会话并销毁它。根据您的 RP 的需求进行调整。

function handleLogout() {
    // NOTE: assumes that $this->oidc is an instance of OpenIDConnectClient()
    if ($this->oidc->verifyLogoutToken()) {
        $sid = $this->oidc->getSidFromBackChannel();

        if (isset($sid)) {
            // Somehow find the session based on the $sid and
            // destroy it. This depends on your RP's design,
            // there is nothing in the OIDC spec to mandate how.
            //
            // In this example, we find a Redis key, which was
            // previously stored using the sid we obtained from
            // the access token after login.
            //
            // The value of the Redis key is that of the user's
            // session ID specific to this hypothetical RP app.
            //
            // We then switch to that session and destroy it.
            $this->redis->connect('127.0.0.1', 6379);
            $session_id_to_destroy = $this->redis->get($sid);
            if ($session_id_to_destroy) {
                session_commit();
                session_id($session_id_to_destroy); // switches to that session
                session_start();
                $_SESSION = []; // effectively ends the session
            }
        }
    }
}

示例 10:启用令牌端点身份验证方法

默认情况下,客户端上只启用了 client_secret_basic,这长期以来是唯一支持的。最近添加了 client_secret_jwtprivate_key_jwt,但它们直到明确启用之前仍然是禁用的。

use Jumbojett\OpenIDConnectClient;

$oidc = new OpenIDConnectClient('https://id.provider.com',
                                'ClientIDHere',
                                null);
# enable 'client_secret_basic' and 'client_secret_jwt'                                
$oidc->setTokenEndpointAuthMethodsSupported(['client_secret_basic', 'client_secret_jwt']);

# for 'private_key_jwt' in addition also the generator function has to be set.
$oidc->setTokenEndpointAuthMethodsSupported(['private_key_jwt']);
$oidc->setPrivateKeyJwtGenerator(function(string $token_endpoint) {
    # TODO: what ever is necessary
})

开发环境

在某些情况下,您可能需要在您的开发系统上禁用 SSL 安全性。注意:在生产系统上不推荐这样做。

$oidc->setVerifyHost(false);
$oidc->setVerifyPeer(false);

此外,您的本地系统可能不支持 HTTPS,因此您可能需要禁用升级到它。

$oidc->setHttpUpgradeInsecureRequests(false);

待办事项

  • 动态注册不支持注册身份验证令牌和端点

贡献

  • 所有合并后的拉取请求应添加到 CHANGELOG.md 文件中。