drenso / symfony-oidc-bundle
Symfony 的 OpenID connect 扩展包
Requires
- php: >=8.1
- ext-curl: *
- ext-filter: *
- ext-hash: *
- ext-json: *
- ext-mbstring: *
- lcobucci/jwt: ^5.0
- phpseclib/phpseclib: ^3.0.36
- psr/clock: ^1.0
- psr/container: ^1.1 || ^2.0
- psr/log: ^1.1 || ^2.0 || ^3.0
- symfony/config: ^5.4 || ^6.3 || ^7.0
- symfony/dependency-injection: ^5.4 || ^6.3 || ^7.0
- symfony/event-dispatcher: ^5.4 || ^6.3 || ^7.0
- symfony/http-foundation: ^5.4 || ^6.3 || ^7.0
- symfony/http-kernel: ^5.4 || ^6.3 || ^7.0
- symfony/property-access: ^5.4 || ^6.3 || ^7.0
- symfony/security-bundle: ^5.4 || ^6.3 || ^7.0
- symfony/security-core: ^5.4 || ^6.3 || ^7.0
- symfony/security-http: ^5.4 || ^6.3 || ^7.0
- symfony/string: ^5.4 || ^6.3 || ^7.0
Requires (Dev)
- drenso/phan-extensions: ^3.0
- friendsofphp/php-cs-fixer: 3.64.0
- rector/rector: 1.2.4
- symfony/cache: ^5.4 || ^6.3 || ^7.0
- symfony/translation-contracts: ^2.0 || ^3.0
Suggests
- symfony/cache: When installed, IdP information will be automatically cached
- v3.4.0
- v3.3.0
- v3.2.0
- v3.1.0
- v3.0.1
- v3.0.0
- v2.x-dev
- v2.13.2
- v2.13.1
- v2.13.0
- v2.12.0
- v2.11.0
- v2.10.0
- v2.9.0
- v2.8.0
- v2.7.0
- v2.6.0
- v2.5.0
- v2.4.0
- v2.3.1
- v2.3.0
- v2.2.0
- v2.1.0
- v2.0.0
- v1.x-dev
- v1.13.1
- v1.13.0
- v1.12.0
- v1.11.4
- v1.11.3
- v1.11.2
- v1.11.1
- v1.11.0
- v1.10.0
- v1.9.0
- v1.8.0
- v1.7.0
- v1.6.1
- v1.6.0
- v1.5.0
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.0
- v1.2.1
- v1.2.0
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.1
- v1.0.0
- dev-master / 3.x-dev
This package is auto-updated.
Last update: 2024-09-16 13:44:25 UTC
README
此扩展包可用于为任何 Symfony 应用程序添加 OIDC 支持。我们仅对其与 SURFconext OIDC 进行了测试,但它应该与任何 OIDC 提供商兼容!
感谢 https://github.com/jumbojett/OpenID-Connect-PHP 的实现,尽管此扩展包已修改以采用面向对象的方法。
注意,此存储库自动从我们的 Gitlab 实例镜像。尽管如此,我们仍将在此处理问题报告和合并请求!
版本说明
自版本 2 开始,此扩展包仅支持 Symfony 5.3 中引入的新认证管理器。随着 Symfony 5.4 中安全管理者的发展,这是此扩展包支持的第一个版本。使用新认证管理器对于 Symfony 6 是必需的!
我们还需要使用 PHP8,因为这显著降低了维护复杂性。
如果您需要此扩展包,但无法启用新认证管理器或使用 PHP8,请查看 v1.x 分支及其文档!
支持以下身份提供者 (IdP)
以下已知的身份提供者与该扩展包兼容
如果您使用此扩展包与任何其他身份提供者,请提交 PR 以添加它!
从旧版本迁移
请参阅 UPGRADE.md!
安装
您可以通过 composer 简单地要求添加此扩展包
composer require drenso/symfony-oidc-bundle
如果您使用 Symfony Flex,则您的 .env
文件应已添加一些环境变量,并在您的配置目录中创建了一个 drenso_oidc.yaml
文件!
设置
OIDC 客户端
请确保在您的 config/packages
目录中的 drenso_oidc.yaml
中配置至少默认的 OIDC 客户端。这可以通过已添加到您的应用程序中的环境变量完成,或通过更新配置文件。您可以配置更多客户端,它们将在 drenso.oidc.client.{name}
下可用,并可以通过使用 OidcClientInterface ${name}OidcClient
自动注入,例如 OidcClientInterface $defaultOidcClient
。如果名称与配置的客户端不匹配,则将自动注入默认客户端。
配置示例
drenso_oidc: #default_client: default # The default client, will be aliased to OidcClientInterface clients: default: # The client name, each client will be aliased to its name (for example, $defaultOidcClient) # Required OIDC client configuration well_known_url: '%env(OIDC_WELL_KNOWN_URL)%' client_id: '%env(OIDC_CLIENT_ID)%' client_secret: '%env(OIDC_CLIENT_SECRET)%' # Extra configuration options #well_known_parser: ~ # Service id for a custom well-known configuration parser #well_known_cache_time: 3600 # Time in seconds, will only be used when symfony/cache is available #jwks_cache_time: 3600 # Time in seconds, will only be used when symfony/cache is available #token_leeway_seconds: 300 # Leeway time in seconds when validating token validity #redirect_route: '/login_check' #custom_client_headers: [] #code_challenge_method: ~ # Code challenge method, can be null, 'S256' or 'plain' #disable_nonce: false # Set to true when nonce verification should not be used # Add any extra client #link: # Will be accessible using $linkOidcClient #well_known_url: '%env(LINK_WELL_KNOWN_URL)%' #client_id: '%env(LINK_CLIENT_ID)%' #client_secret: '%env(LINK_CLIENT_SECRET)%'
用户提供者
您需要更新您的用户提供者以实现来自 OidcUserProviderInterface
的方法。需要实现两个方法
ensureUserExists(string $userIdentifier, OidcUserData $userData)
:实现此方法以使用从传递的OidcUserData
对象中可用的数据启动新账户。标识符是用户数据中的一个可配置属性,默认为sub
。如果无法启动账户,则由于用户提供者无法检索用户,认证将无法进行。loadOidcUser(string $userIdentifier): UserInterface
:实现此方法以根据标识符检索用户。我们使用一个专用方法而不是 Symfony 的默认loadUserByIdentifier
,以便您可以检测登录来源,而无需创建专用用户提供者。如果 OIDC 用户标识符是唯一的,则将到loadUserByIdentifier
的转发应足够。
防火墙配置
如果您使用的是 Symfony <6,请确保在 security.yaml
中启用新认证管理器
security: enable_authenticator_manager: true
在您的防火墙中启用 oidc
监听器,请编辑 security.yml
security: firewalls: main: pattern: ^/ oidc: ~
对于 oidc
监听器,有几个选项可供选择。
您可以直接在防火墙中的 oidc
监听器下进行配置,例如 user_identifier_property
security: firewalls: main: oidc: user_identifier_property: email
开始认证
使用下面的控制器示例将用户转发到 OIDC 服务
/** * This controller forwards the user to the OIDC login * * @throws \Drenso\OidcBundle\Exception\OidcException */ #[Route('/login_oidc', name: 'login_oidc')] #[IsGranted('PUBLIC_ACCESS')] public function surfconext(OidcClientInterface $oidcClient): RedirectResponse { // Redirect to authorization @ OIDC provider return $oidcClient->generateAuthorizationRedirect(); }
您可以为
generateAuthorizationRedirect
方法提供提示、作用域和额外的查询参数。
还可以强制使用“记住我”模式进行重定向。
这就足够了!
用户标识符
默认情况下,此组件使用 sub
属性作为用户标识符,但可以任何检索到的用户数据属性。只需将 user_identifier_property
配置为与 Symfony Property Accessor 兼容的属性路径字符串,即可获取所需值。
请注意,使用基于对象的方法从用户数据中检索属性。
记住我
如果您想启用“记住我”功能,请确保将查询参数 _remember_me=1
添加到用于生成重定向调用的路由(调用 generateAuthorizationRedirect
的那个路由)。
您可以针对每个 OIDC 客户端覆盖 _remember_me
参数。只需在客户端配置中更新 remember_me_parameter
的值。
最后,确保已启用 Symfony 的“记住我”认证器,并在 security.yaml
中将 oidc
认证器的 enable_remember_me
选项设置为 true。
用户认证后,您将看到 REMEMBERME
糖果。您可以通过删除 PHPSESSID
糖果来检查“记住我”功能是否正常工作。
注销
如果 Identity Provider 的 end_session_endpoint
参数存在于 .well-known 端点中,则可以通过启用“注销”功能来启用“注销”。
由于在使用单点登录时注销功能本身存在根本性错误,因此该选项默认禁用。这是因为注销身份提供者(例如:Azure、Facebook 等)无法保证用户已从使用相同身份提供者认证的任何其他服务中注销。
如果您想启用“注销”支持,只需将 enable_end_session_listener: true
添加到防火墙配置中的 oidc 监听器。它仅在您启用了默认的 Symfony logout: true
设置时才能正常工作。
默认情况下,监听器会将注销的 target_path
传递给 OpenID 提供者,因此用户在注销后会重定向回您的应用程序。如果您不希望这样做,并且希望用户留在 OpenID 提供者的注销确认页上,请启用 use_logout_target_path: false
设置。
示例:默认注销路径
security: firewalls: main: logout: true oidc: enable_end_session_listener: true
示例:自定义注销目标路径
security: firewalls: main: logout: target: /my_custom_target_path oidc: enable_end_session_listener: true
示例:禁用重定向到注销 target_path
这将使用户在注销后留在 OpenID 提供者上。
security: firewalls: main: logout: true oidc: enable_end_session_listener: true use_logout_target_path: false
客户端定位器
如果您出于某种原因配置了多个 OIDC 客户端并需要动态检索它们,您可以使用 OidcClientLocator
。
public function surfconext(OidcClientLocator $clientLocator): RedirectResponse { return $clientLocator->getClient('your_client_id')->generateAuthorizationRedirect(); }
当请求的客户端未找到时,定位器会抛出 OidcClientNotFoundException。在没有参数调用时,它将返回配置的默认客户端。
宽容度
此组件在验证访问令牌时使用 300 秒的宽容度。此值可以通过 token_leeway_seconds
客户端选项进行配置。
缓存
当您的项目中可用的 symfony/cache
时,此库将自动缓存已知和 jwks 结果。默认情况下,它将缓存 3600
秒。
您可以通过将 null
传递给 well_known_cache_time
或 jwks_cache_time
客户端选项来分别禁用缓存。
刷新令牌
目前,本捆绑包提供的防火墙实现不提供刷新令牌(因为它不应该有必要)。但是,如果您需要自行刷新令牌以满足您的实现,您可以在 OidcClientInterface
上使用 refreshTokens
方法!
额外的令牌声明验证
如果您需要验证额外的令牌声明,您可以创建一个实现了 OidcTokenConstraintProviderInterface
的服务,并将其服务 ID 添加到您选择的 OIDC 客户端。
示例配置
drenso_oidc: clients: default: additional_token_constraints_provider: App\Security\AdditionalTokenConstraintProvider
示例约束提供者
namespace App\Security; use App\Security\Constraint\HasAudienceContaining; use Drenso\OidcBundle\Enum\OidcTokenType; use Drenso\OidcBundle\OidcTokenConstraintProviderInterface; class AdditionalTokenConstraintProvider implements OidcTokenConstraintProviderInterface { public function getAdditionalConstraints(OidcTokenType $tokenType): array { if (OidcTokenType::ID === $tokenType) { return [ new HasAudienceContaining('abc123'), ]; } if (OidcTokenType::ACCESS === $tokenType) { return [ new HasAudienceContaining('def456'), ]; } return []; } }
解析已知信息
一些提供者返回不正确或不完整的已知信息。您可以通过将 well_known_parser
设置为实现 OidcWellKnownParserInterface
的服务 ID 来为 OidcClient
配置自定义的已知信息解析器。
OAuth 2.0 令牌交换 RFC 8693
此捆绑包支持令牌交换:您可以使用 OidcClient
上的 exchangeTokens
来执行此操作。这是在 #66 中添加的,其中还包含有关此过程的一些背景信息。
已知用法
使用此捆绑包的开源项目的列表
- Zitadel 的 example-symfony-oidc:一个模板仓库,包含基本的 OIDC 认证、用户模型、角色和示例页面。