clissmancamacho / php-openid-connect-client
OAuth2/OpenID Connect 客户端库
Requires
- php: >=5.3.3
- zendframework/zend-crypt: >=2.2.1
- zendframework/zend-eventmanager: >=2.2.1
- zendframework/zend-filter: >=2.2.1
- zendframework/zend-http: >=2.2.1
- zendframework/zend-json: >=2.2.1
- zendframework/zend-session: >=2.8.0
- zendframework/zend-stdlib: >=2.2.1
README
库的目的是提供工具和构建块,用于创建基于 OAuth2 协议的客户端,并侧重于 OpenID Connect 规范的授权/认证委托。
功能
- 灵活和可扩展
- 依赖注入方法
- 覆盖单元测试
- 基于 Zend Framework 2 的部分
兼容性
库已经与以下身份提供者进行了测试并成功
要求
- Zend Framework >= 2.2.1
文档
安装
使用 composer
将以下要求添加到您的 composer.json
文件中
"require": {
"ivan-novakov/php-openid-connect-client": "dev-master"
}
不使用 composer
只需克隆存储库或下载并解压最新的 版本,并相应地配置您的自动加载器。
基本用法
您需要一个在身份提供者处注册的 client_id
和 client_secret
,并且您必须知道提供者端点的 URL。
最常用的流程是
- 生成授权请求 URL
- 将用户重定向到授权 URL 或让用户点击“登录”按钮
- 处理回调请求并检索授权代码
- 使用授权代码进行令牌请求并检索访问令牌
- (可选) 使用访问令牌进行用户信息请求并检索有关用户的信息
库引入了一个“流程”对象,将上述操作整合为两个调用
getAuthorizationRequestUri
- 生成用户授权的 URL,然后由开发者决定如何将用户重定向到该 URLprocess
- 一次性执行上述列表中的 3、4 和 5 个操作
简单示例
use InoOicClient\Flow\Basic;
$config = array(
'client_info' => array(
'client_id' => '<client ID>',
'redirect_uri' => '<redirect URI>',
'authorization_endpoint' => 'https://#/o/oauth2/auth',
'token_endpoint' => 'https://#/o/oauth2/token',
'user_info_endpoint' => 'https://www.googleapis.com/oauth2/v1/userinfo',
'authentication_info' => array(
'method' => 'client_secret_post',
'params' => array(
'client_secret' => '<client secret>'
)
)
)
);
$flow = new Basic($config);
if (! isset($_GET['redirect'])) {
try {
$uri = $flow->getAuthorizationRequestUri('openid email profile');
printf("<a href=\"%s\">Login</a>", $uri);
} catch (\Exception $e) {
printf("Exception during authorization URI creation: [%s] %s", get_class($e), $e->getMessage());
}
} else {
try {
$userInfo = $flow->process();
} catch (\Exception $e) {
printf("Exception during user authentication: [%s] %s", get_class($e), $e->getMessage());
}
}
分发器
“流程”对象只是一个外观。真正的“工作”是由所谓的“分发器”完成的
InoOicClient\Oic\Authorization\Dispatcher
- 生成授权请求 URI 并处理回调请求InoOicClient\Oic\Token\Dispatcher
- 发送令牌请求InoOicClient\Oic\UserInfo\Dispatcher
- 发送用户信息请求
HTTP 客户端
库使用 Zend Framework 2 HTTP 客户端与 cURL 连接适配器,它提供了最佳的安全性能,特别是关于安全的 HTTPS 连接。HTTP 客户端通过工厂创建,默认情况下配置客户端验证服务器证书。客户端还执行 CN 匹配验证。您可以在 此博客文章 中找到有关使用 Zend Framework 2 的安全 HTTPS 连接的更多信息。
然而,您也可以注入配置不同的 HTTP 客户端实例。
客户端认证
根据 OpenID Connect 规范(另见 OAuth2 规范),库支持以下客户端认证方法
client_secret_basic
- 客户端密钥以Authorization
HTTP 头的形式发送client_secret_post
- 客户端密钥作为POST参数发送
状态持久化
规范建议在请求授权时使用 state
参数。服务器随后必须返回相同的值。这可以防止跨站请求伪造攻击。
库自动处理状态
- 在创建授权URI期间生成一个不透明的状态值
- 将状态保存在用户会话中
- 检查从服务器发送的状态值与保存的状态值是否一致
默认情况下,生成的状态值保存在用户会话中(来自Zend框架的会话容器)。可以通过实现 InoOicClient\Oic\Authorization\State\Storage\StorageInterface
使用其他存储。
高级使用
如果您需要构建自定义流程或扩展/修改某些功能,您可以实现自己的流程对象(有关详细信息,请参阅 InoOicClient\Flow\Basic
),或者您可以直接使用分发器。然后,您可以构建和配置相关的对象(分发器、请求、响应等),以满足您的使用场景。
创建客户端信息对象
use InoOicClient\Client\ClientInfo;
$clientOptions = array(
'client_id' => '<client ID>',
'redirect_uri' => '<redirect URI>',
'authorization_endpoint' => 'https://#/o/oauth2/auth',
'token_endpoint' => 'https://#/o/oauth2/token',
'user_info_endpoint' => 'https://www.googleapis.com/oauth2/v1/userinfo',
'authentication_info' => array(
'method' => 'client_secret_post',
'params' => array(
'client_secret' => '<client secret>'
)
)
);
$clientInfo = new ClientInfo();
$clientInfo->fromArray($clientOptions);
准备授权请求URI
use InoOicClient\Oic\Authorization;
$stateManager = new Manager();
$dispatcher = new Authorization\Dispatcher();
$dispatcher->setStateManager($stateManager);
$request = new Authorization\Request($clientInfo, 'code', 'openid profile email');
$uri = $dispatcher->createAuthorizationRequestUri($request);
从回调中检索授权码
$stateManager = new Manager();
$dispatcher = new Authorization\Dispatcher();
$dispatcher->setStateManager($stateManager);
$response = $dispatcher->getAuthorizationResponse();
printf("OK<br>Code: %s<br>State: %s<br>", $response->getCode(), $response->getState());
执行令牌请求
$httpClientFactory = new Http\ClientFactory();
$httpClient = $httpClientFactory->createHttpClient();
$tokenDispatcher = new Token\Dispatcher($httpClient);
$tokenRequest = new Token\Request();
$tokenRequest->setClientInfo($clientInfo);
$tokenRequest->setCode($authorizationCode);
$tokenRequest->setGrantType('authorization_code');
$tokenResponse = $tokenDispatcher->sendTokenRequest($tokenRequest);
printf("Access token: %s<br>", $tokenResponse->getAccessToken());
TODO
- 为不同的提供者提供用户友好的演示
- 添加对JWT和ID令牌验证的支持
规范
OpenID Connect
OAuth2