facile-it / php-openid-client
OpenID (OIDC) 客户端
Requires
- php: ^7.4 || ^8.0
- ext-json: *
- facile-it/php-jose-verifier: ^0.3 || ^0.4.3
- php-http/discovery: ^1.6
- psr/http-client: ^1.0
- psr/http-client-implementation: ^1.0
- psr/http-factory: ^1.0
- psr/http-factory-implementation: ^1.0
- psr/http-message: ^1.0 || ^2.0
- psr/http-message-implementation: ^1.0
- psr/http-server-middleware: ^1.0
- web-token/jwt-checker: ^2.0 || ^3.0
- web-token/jwt-core: ^2.0 || ^3.0
- web-token/jwt-encryption: ^2.0 || ^3.0
- web-token/jwt-key-mgmt: ^2.0.7 || ^3.0
- web-token/jwt-signature: ^2.0 || ^3.0
- web-token/jwt-signature-algorithm-rsa: ^2.0 || ^3.0
Requires (Dev)
- dflydev/fig-cookies: ^2.0 || ^3.0
- facile-it/facile-coding-standard: ^0.5.2
- friendsofphp/php-cs-fixer: ^3.0
- laminas/laminas-component-installer: ^2.1 || ^3.0
- laminas/laminas-config-aggregator: ^1.1
- laminas/laminas-di: ^3.1
- laminas/laminas-diactoros: ^2.1 || ^3.0
- laminas/laminas-servicemanager: ^3.4
- php-http/cache-plugin: ^1.6
- php-http/curl-client: ^2.0
- php-http/guzzle7-adapter: ^0.1.0 || ^1.0
- phpspec/prophecy: ^1.10.3
- phpspec/prophecy-phpunit: ^2.0
- phpunit/phpunit: ^8.5.14 || ^9.3
- symfony/console: ^4.3 || ^5.0 || ^6.0
- vimeo/psalm: ^5.6.0
- web-token/jwt-encryption-algorithm-aescbc: ^2.0 || ^3.0
- web-token/jwt-encryption-algorithm-aesgcm: ^2.0 || ^3.0
- web-token/jwt-encryption-algorithm-aesgcmkw: ^2.0 || ^3.0
- web-token/jwt-encryption-algorithm-aeskw: ^2.0 || ^3.0
- web-token/jwt-encryption-algorithm-dir: ^2.0 || ^3.0
- web-token/jwt-encryption-algorithm-ecdh-es: ^2.2.0 || ^3.0
- web-token/jwt-encryption-algorithm-experimental: ^2.0 || ^3.0
- web-token/jwt-encryption-algorithm-pbes2: ^2.0 || ^3.0
- web-token/jwt-encryption-algorithm-rsa: ^2.0 || ^3.0
- web-token/jwt-signature-algorithm-ecdsa: ^2.0 || ^3.0
- web-token/jwt-signature-algorithm-eddsa: ^2.0 || ^3.0
- web-token/jwt-signature-algorithm-experimental: ^2.0 || ^3.0
- web-token/jwt-signature-algorithm-hmac: ^2.0 || ^3.0
- web-token/jwt-signature-algorithm-none: ^2.0 || ^3.0
Suggests
- dflydev/fig-cookies: To use the SessionCookieMiddleware
- facile-it/php-oauth2-http-client: To use a PSR HTTP client to interact with OAuth2/OpenID protected APIs
- web-token/jwt-signature-algorithm-hmac: To use the client_secret_jwt auth method and symmetric key signature
This package is auto-updated.
Last update: 2024-08-27 13:36:21 UTC
README
完整的 OpenID 客户端实现。
大多数库代码基于出色的 node-openid-client
。
可能需要 PHP 扩展 gmp
。
实现规范和功能
- OAuth 2.0 RFC 6749 & OpenID Connect Core 1.0
- 授权(授权码流程、隐式流程、混合流程)
- 用户信息端点和 ID 令牌,包括签名和加密(使用 JWT 框架 库)
- 通过值或引用传递请求对象,包括签名和加密
- 离线访问/刷新令牌授权
- 客户端凭据授权
- 客户端身份验证,包括
client_secret_jwt
和private_key_jwt
方法
- OpenID Connect Discovery 1.0
- OpenID Connect 动态客户端注册 1.0 和 RFC7591 OAuth 2.0 动态客户端注册协议
- OAuth 2.0 表单提交响应模式
- RFC7009 - OAuth 2.0 令牌撤销
- RFC7662 - OAuth 2.0 令牌洞察
- RFC7592 - OAuth 2.0 动态客户端注册管理协议
支持以下草案规范
- OAuth 令牌洞察的 JWT 响应 - 草案 03
- OAuth 2.0 JWT 安全授权响应模式(JARM)- 草案 02
- OAuth 2.0 JWT 安全授权请求(JAR)
- OAuth 2.0 互信 TLS 客户端身份验证和证书绑定访问令牌(MTLS)- 草案 15
安装
要求
psr/http-client-implementation
实现psr/http-factory-implementation
实现psr/http-message-implementation
实现
composer require facile-it/php-openid-client
RSA
签名算法已从 JWT 框架包中包含。如果您需要其他算法,您应手动安装它。
基本用法
对于基本用法,您不需要其他依赖项包。
每个构建器都有方法可以自定义带有其他依赖项的实例。
use Facile\OpenIDClient\Client\ClientBuilder; use Facile\OpenIDClient\Issuer\IssuerBuilder; use Facile\OpenIDClient\Client\Metadata\ClientMetadata; use Facile\OpenIDClient\Service\Builder\AuthorizationServiceBuilder; use Facile\OpenIDClient\Service\Builder\UserInfoServiceBuilder; use Psr\Http\Message\ServerRequestInterface; $issuer = (new IssuerBuilder()) ->build('https://example.com/.well-known/openid-configuration'); $clientMetadata = ClientMetadata::fromArray([ 'client_id' => 'client-id', 'client_secret' => 'my-client-secret', 'token_endpoint_auth_method' => 'client_secret_basic', // the auth method tor the token endpoint 'redirect_uris' => [ 'https://my-rp.com/callback', ], ]); $client = (new ClientBuilder()) ->setIssuer($issuer) ->setClientMetadata($clientMetadata) ->build(); // Authorization $authorizationService = (new AuthorizationServiceBuilder())->build(); $redirectAuthorizationUri = $authorizationService->getAuthorizationUri( $client, ['login_hint' => 'user_username'] // custom params ); // you can use this uri to redirect the user // Get access token /** @var ServerRequestInterface::class $serverRequest */ $serverRequest = null; // get your server request $callbackParams = $authorizationService->getCallbackParams($serverRequest, $client); $tokenSet = $authorizationService->callback($client, $callbackParams); $idToken = $tokenSet->getIdToken(); // Unencrypted id_token, if returned $accessToken = $tokenSet->getAccessToken(); // Access token, if returned $refreshToken = $tokenSet->getRefreshToken(); // Refresh token, if returned // check if we have an authenticated user if ($idToken) { $claims = $tokenSet->claims(); // IdToken claims } else { throw new \RuntimeException('Unauthorized') } // Refresh token $tokenSet = $authorizationService->refresh($client, $tokenSet->getRefreshToken()); // Get user info $userInfoService = (new UserInfoServiceBuilder())->build(); $userInfo = $userInfoService->getUserInfo($client, $tokenSet);
客户端注册
请参阅 OpenID Connect 动态客户端注册 1.0 和 RFC7591 OAuth 2.0 动态客户端注册协议。
use Facile\OpenIDClient\Service\Builder\RegistrationServiceBuilder; $registration = (new RegistrationServiceBuilder())->build(); // registration $metadata = $registration->register( $issuer, [ 'client_name' => 'My client name', 'redirect_uris' => ['https://my-rp.com/callback'], ], 'my-initial-token' ); // read $metadata = $registration->read($metadata['registration_client_uri'], $metadata['registration_access_token']); // update $metadata = $registration->update( $metadata['registration_client_uri'], $metadata['registration_access_token'], array_merge($metadata, [ // new metadata ]) ); // delete $registration->delete($metadata['registration_client_uri'], $metadata['registration_access_token']);
令牌洞察
use Facile\OpenIDClient\Service\Builder\IntrospectionServiceBuilder; $service = (new IntrospectionServiceBuilder())->build(); $params = $service->introspect($client, $token);
令牌撤销
use Facile\OpenIDClient\Service\Builder\RevocationServiceBuilder; $service = (new RevocationServiceBuilder())->build(); $params = $service->revoke($client, $token);
请求对象
您可以使用 Facile\OpenIDClient\RequestObject\RequestObjectFactory
类创建授权请求的 请求对象。
这将创建基于您的客户端元数据的签名(可选加密)JWT 令牌。
use Facile\OpenIDClient\RequestObject\RequestObjectFactory; $factory = new RequestObjectFactory(); $requestObject = $factory->create($client, [/* custom claims to include in the JWT*/]);
然后您可以使用它来创建 AuthRequest
use Facile\OpenIDClient\Authorization\AuthRequest; $authRequest = AuthRequest::fromParams([ 'client_id' => $client->getMetadata()->getClientId(), 'redirect_uri' => $client->getMetadata()->getRedirectUris()[0], 'request' => $requestObject, ]);
聚合和分布式声明
该库可以处理 聚合和分布式声明
use Facile\OpenIDClient\Claims\AggregateParser; use Facile\OpenIDClient\Claims\DistributedParser; $aggregatedParser = new AggregateParser(); $claims = $aggregatedParser->unpack($client, $userInfo); $distributedParser = new DistributedParser(); $claims = $distributedParser->fetch($client, $userInfo);
使用中间件
有一些中间件和处理程序可用
SessionCookieMiddleware
此中间件应始终位于中间件链的顶部,以提供用于 state
和 nonce
参数的会话。
要使用它,您应该安装 dflydev/fig-cookies
包。
$ composer require "dflydev/fig-cookies:^2.0"
use Facile\OpenIDClient\Middleware\SessionCookieMiddleware; use Psr\SimpleCache\CacheInterface; // Use your PSR-16 simple-cache implementation to persist sessions /** @var CacheInterface $cache */ $middleware = new SessionCookieMiddleware($cache/* , $cookieName = "openid", $ttl = 300 */);
该中间件提供了一个带有 Facile\OpenIDClient\Session\AuthSessionInterface
状态实例的 Facile\OpenIDClient\Session\AuthSessionInterface
属性,用于持久化会话数据。
使用其他会话存储
如果您有其他会话存储,您可以在 Facile\OpenIDClient\Session\AuthSessionInterface
属性中处理它并提供一个 Facile\OpenIDClient\Session\AuthSessionInterface
实例。
ClientProviderMiddleware
此中间件应始终位于中间件链的顶部,以向其他中间件提供客户端。
use Facile\OpenIDClient\Middleware\ClientProviderMiddleware; $client = $container->get('openid.clients.default'); $middleware = new ClientProviderMiddleware($client);
AuthRequestProviderMiddleware
此中间件提供用于与 AuthRedirectHandler
一起使用的身份验证请求。
use Facile\OpenIDClient\Middleware\AuthRequestProviderMiddleware; use Facile\OpenIDClient\Authorization\AuthRequest; $authRequest = AuthRequest::fromParams([ 'scope' => 'openid', // other params... ]); $middleware = new AuthRequestProviderMiddleware($authRequest);
AuthRedirectHandler
此处理器将用户重定向到 OpenID 授权页面。
use Facile\OpenIDClient\Middleware\AuthRedirectHandler; use Facile\OpenIDClient\Service\AuthorizationService; /** @var AuthorizationService $authorizationService */ $authorizationService = $container->get(AuthorizationService::class); $middleware = new AuthRedirectHandler($authorizationService);
CallbackMiddleware
此中间件将处理来自 OpenID 提供者的回调。
它将提供一个带有最终 TokenSet 对象的 Facile\OpenIDClient\Token\TokenSetInterface
属性。
use Facile\OpenIDClient\Middleware\CallbackMiddleware; use Facile\OpenIDClient\Service\AuthorizationService; /** @var AuthorizationService $authorizationService */ $authorizationService = $container->get(AuthorizationService::class); $middleware = new CallbackMiddleware($authorizationService);
UserInfoMiddleware
此中间件将从 userinfo 端点获取用户数据,并将用户信息作为数组提供 Facile\OpenIDClient\Middleware\UserInfoMiddleware
属性。
use Facile\OpenIDClient\Middleware\UserInfoMiddleware; use Facile\OpenIDClient\Service\UserInfoService; /** @var UserInfoService $userInfoService */ $userInfoService = $container->get(UserInfoService::class); $middleware = new UserInfoMiddleware($userInfoService);
生产环境中的性能改进
使用缓存以避免在每次请求时都检索发行者配置和密钥是很重要的。
use Psr\SimpleCache\CacheInterface; use Facile\OpenIDClient\Issuer\IssuerBuilder; use Facile\OpenIDClient\Issuer\Metadata\Provider\MetadataProviderBuilder; use Facile\JoseVerifier\JWK\JwksProviderBuilder; /** @var CacheInterface $cache */ $cache = $container->get(CacheInterface::class); // get your simple-cache implementation $metadataProviderBuilder = (new MetadataProviderBuilder()) ->setCache($cache) ->setCacheTtl(86400*30); // Cache metadata for 30 days $jwksProviderBuilder = (new JwksProviderBuilder()) ->setCache($cache) ->setCacheTtl(86400); // Cache JWKS for 1 day $issuerBuilder = (new IssuerBuilder()) ->setMetadataProviderBuilder($metadataProviderBuilder) ->setJwksProviderBuilder($jwksProviderBuilder); $issuer = $issuerBuilder->build('https://example.com/.well-known/openid-configuration');
使用 Psalm
如果您需要使用 Psalm,您可以在 psalm.xml
中包含插件。
<plugins>
<pluginClass class="Facile\JoseVerifier\Psalm\Plugin" />
</plugins>