Symfony 5 中带PKCE的Authorization Code Grant实现报错咨询
1. 修正客户端持久化配置
你当前league_oauth2_server.yaml中persistence.doctrine设为null,代表使用内存存储客户端,命令行执行create-client生成的客户端仅存在于命令进程内存中,web请求完全读取不到,这是最高概率的报错原因。
修正方式:
修改./config/packages/league_oauth2_server.yaml的持久化配置:
league_oauth2_server: # 其余原有配置保持不变 persistence: doctrine: entity_manager: default
执行命令生成数据库表存储oauth相关数据:
bin/console make:migration bin/console doctrine:migrations:migrate
重新创建客户端,必须指定和实际回调一致的redirect_uri:
bin/console league:oauth2-server:create-client api-client \ --grant-type "authorization_code" \ --redirect-uri "你的实际回调地址"
如果是供前端、移动端使用的公开客户端,额外添加--public参数。
2. 补全授权请求必填参数
Authorization Code 授权流要求/authorize请求必须携带redirect_uri参数,且参数值必须和创建客户端时填写的完全一致,不能有域名、路径、参数的差异,完整请求示例:
/authorize?client_id=ee0b46d...&response_type=code&state=随机防篡改字符串&redirect_uri=https://你的实际回调地址
如果是公开客户端,还需要额外传递code_challenge和code_challenge_method参数,因为你配置中开启了require_code_challenge_for_public_clients: true。
3. 修复AuthorizationCodeListener代码bug
你当前的监听类存在两个未声明依赖的错误,会导致授权请求跳转时参数丢失,触发后续校验失败:
- 未注入
UrlGenerator依赖却调用$this->urlGenerator - 未获取请求对象却调用
$request->query->all()
修正后的完整代码:
<?php declare(strict_types=1); namespace App\EventListener; use League\Bundle\OAuth2ServerBundle\Event\AuthorizationRequestResolveEvent; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\User\UserInterface; final class AuthorizationCodeListener { public function __construct( private Security $security, private UrlGeneratorInterface $urlGenerator, ) { } public function onAuthorizationRequest(AuthorizationRequestResolveEvent $event): void { $user = $this->security->getUser(); if ($user instanceof UserInterface) { $event->setUser($user); $event->resolveAuthorization(true); } else { $request = $event->getRequest(); $response = new RedirectResponse( $this->urlGenerator->generate( 'app_consent', $request->query->all() ), 307 ); $event->setResponse($response); } } }
4. 验证客户端配置有效性
执行以下命令查看所有已持久化的客户端,确认你使用的client_id对应的记录:
- 状态正常未被禁用
grant_type包含authorization_coderedirect_uri和请求中传递的参数完全一致
bin/console league:oauth2-server:list-clients
5. 校验加密密钥一致性
确认.env文件中OAUTH2_ENCRYPTION_KEY的值,和你生成公私钥时替换<REPLACE_WITH_OAUTH2_ENCRYPTION_KEY>的字符串完全相同,否则无法正确解密存储的客户端信息,也会触发客户端校验失败错误。
内容的提问来源于stack exchange,提问作者Kerrial Beckett Newham

