wyzenapps / openid-connect-php
简易的 OpenID Connect 客户端
0.10.0
2023-11-07 16:00 UTC
Requires
- php: >=7.1
- ext-curl: *
- ext-json: *
- phpseclib/phpseclib: ~3.0
Requires (Dev)
- phpunit/phpunit: ^9.6
- roave/security-advisories: dev-latest
- yoast/phpunit-polyfills: ^1.0
README
这是一个简单的库,允许应用程序通过基本的 OpenID Connect 流进行用户身份验证。这个库希望通过使其足够简单,即使对 OpenID Connect 协议了解不多的开发者也能轻松设置身份验证。
特别感谢 Justin Richer 和 Amanda Anganes 对该协议的帮助和支持。
需求
- PHP 5.4 或更高版本
- CURL 扩展
- JSON 扩展
安装
使用 composer 安装库
composer require jumbojett/openid-connect-php
包含 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');
示例 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(array('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(array('token_endpoint'=>'https://id.provider.com/connect/token'));
$oidc->addScope('my_scope');
//Add username and password
$oidc->addAuthParam(array('username'=>'<Username>'));
$oidc->addAuthParam(array('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(array('id_token'));
$oidc->addScope(array('openid'));
$oidc->setAllowImplicitFlow(true);
$oidc->addAuthParam(array('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 可从 OP 发送的注销令牌中获取。如果需要将它们与一个会话匹配以销毁它,可以使用 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 = array(); // effectively ends the session
}
}
}
}
示例 10:启用令牌端点认证方法
默认情况下,客户端上只启用了 client_secret_basic
,这是长期唯一支持的。最近添加了 client_secret_jwt
和 private_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 文件中。