如何为API Platform接入外部OpenID提供商(Azure OAuth2)实现认证
在Symfony 6中为API Platform接入Azure OpenID OAuth2认证
以下是基于你现有JWT和API Platform配置的完整实现步骤:
1. 安装依赖
首先安装OAuth2客户端工具包和Azure提供商:
composer require knpuniversity/oauth2-client-bundle league/oauth2-azure
2. 配置Azure Active Directory应用
在Azure门户完成以下操作:
- 创建应用注册,记录
客户端ID、客户端密钥、租户ID - 设置重定向URI为
https://你的后端域名/login/azure/check - 在应用的令牌配置中启用
ID令牌(OpenID Connect必需)
3. 配置OAuth2客户端
编辑config/packages/knpu_oauth2_client.yaml:
knpu_oauth2_client: clients: azure: type: azure client_id: '%env(AZURE_CLIENT_ID)%' client_secret: '%env(AZURE_CLIENT_SECRET)%' tenant_id: '%env(AZURE_TENANT_ID)%' redirect_route: azure_check redirect_params: {}
在.env文件中添加环境变量:
AZURE_CLIENT_ID=你的Azure客户端ID AZURE_CLIENT_SECRET=你的Azure客户端密钥 AZURE_TENANT_ID=你的Azure租户ID
4. 配置Security防火墙
修改config/packages/security.yaml,整合Azure OAuth2登录和JWT认证:
security: providers: app_user_provider: entity: class: App\Entity\User property: email firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false main: lazy: true provider: app_user_provider oauth2_login: provider: azure login_path: /login/azure check_path: /login/azure/check success_handler: App\Security\AzureAuthenticationSuccessHandler logout: path: /logout target: / api: pattern: ^/api stateless: true jwt: ~ entry_point: jwt access_control: - { path: ^/login/azure, roles: PUBLIC_ACCESS } - { path: ^/api, roles: ROLE_USER }
5. 创建认证成功处理器
这个类负责将Azure用户关联到本地用户,并生成JWT返回给前端:
<?php namespace App\Security; use App\Entity\User; use Doctrine\ORM\EntityManagerInterface; use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; class AzureAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface { public function __construct( private EntityManagerInterface $em, private JWTTokenManagerInterface $jwtManager, private UserProviderInterface $userProvider ) {} public function onAuthenticationSuccess(Request $request, TokenInterface $token): JsonResponse { $azureUser = $token->getUser(); $email = $azureUser->getEmail(); // 查找本地用户,不存在则创建 try { $user = $this->userProvider->loadUserByIdentifier($email); } catch (\Exception $e) { $user = new User(); $user->setEmail($email); $user->setUsername($azureUser->getName()); $user->setRoles(['ROLE_USER']); $this->em->persist($user); $this->em->flush(); } // 生成JWT令牌 $jwt = $this->jwtManager->create($user); return new JsonResponse([ 'token' => $jwt, 'user' => [ 'id' => $user->getId(), 'email' => $user->getEmail(), 'roles' => $user->getRoles() ] ]); } }
确保你的User实体实现了Symfony\Component\Security\Core\User\UserInterface,并包含email、username、roles等必要字段。
6. 添加路由
编辑config/routes.yaml,添加Azure登录和回调的路由:
azure_login: path: /login/azure methods: GET azure_check: path: /login/azure/check methods: GET|POST
7. 配置API Platform权限
在你的API资源实体上添加安全注解,确保只有认证用户能访问:
use ApiPlatform\Core\Annotation\ApiResource; use Symfony\Component\Security\Core\Annotation\IsGranted; /** * @ApiResource( * security="is_granted('ROLE_USER')", * collectionOperations={"get", "post"}, * itemOperations={"get", "put", "delete"} * ) * @IsGranted("ROLE_USER") */ class YourResource { // 实体字段和方法 }
8. 前端React适配
- 添加登录按钮,跳转到后端的Azure登录路由:
<button onClick={() => window.location.href = 'https://你的后端域名/login/azure'}> 使用Azure登录 </button>
- 登录成功后,后端返回包含JWT的JSON,前端将令牌存储到本地,后续请求API时携带:
// 示例:获取并存储令牌 fetch('https://你的后端域名/login/azure/check') .then(res => res.json()) .then(data => { localStorage.setItem('jwt_token', data.token); }); // 示例:携带令牌请求API fetch('https://你的后端域名/api/your-resources', { headers: { 'Authorization': `Bearer ${localStorage.getItem('jwt_token')}` } })
9. 测试验证
- 启动Symfony后端,确认环境变量配置正确
- 点击前端登录按钮,完成Azure账号登录
- 拿到JWT后,请求API Platform接口,验证是否能正常访问受保护资源
内容的提问来源于stack exchange,提问作者Amin Hoseiny
相关产品推荐
相关产品推荐

