beyondbluesky / oauth2-pkce-client
使用PKCE的OAuth2客户端实现
1.3.8
2023-11-07 05:14 UTC
Requires
- php: >=7.3
- beyondbluesky/lib-jwt: 1.*
- symfony/dependency-injection: ^5.1|^5.2|^6.3
- symfony/framework-bundle: ^5.1|^5.2|^6.3
- symfony/http-foundation: ^5.1|^5.2|^6.3
- symfony/routing: ^5.1|^5.2|^6.3
Requires (Dev)
- php: >=7.3
- beyondbluesky/lib-jwt: 1.*
- symfony/dependency-injection: ^5.1|^5.2|^6.3
- symfony/framework-bundle: ^5.1|^5.2|^6.3
- symfony/http-foundation: ^5.1|^5.2|^6.3
- symfony/routing: ^5.1|^5.2|^6.3
Suggests
- symfony/security-guard: For integration with Symfony's Guard Security layer
README
这个Symfony扩展允许Symfony4/5/6安装通过使用PKCE扩展来验证OAuth2服务器上的用户。
PKCE扩展RFC-7636 (https://tools.ietf.org/html/rfc7636)为OAuth2协议增加了额外的安全性,并在OAuth2的未来版本中将成为强制性。
此实现需要生成以下内容:
- 认证器
- 控制器以接收来自OAuth2服务器的响应
- 存储会话信息(oauth2_session)的表。该表用于存储会话信息,包括挑战和验证器字符串,用于在PKCE扩展部分中保护通信。
- 存储client_id、oauth2 uris等信息的所需配置文件。
- 修改security.yml以包含所有之前配置的配置
以下将列出配置它的所有步骤。别担心...
安装
要安装它,您需要按照以下步骤操作
- 下载扩展的最新版本
$ composer require beyondbluesky/oauth2-pkce-client
- 使用名为config/packages的文件配置您的OAuth2服务器的端点
config/packages/oauth2_pkce_client.yaml
oauth2_pkce_client: server_uris: auth_uri: https://oauth2.localnet/oauth2/auth token_uri: https://oauth2.localnet/oauth2/token owner_uri: https://oauth2.localnet/oauth2/owner client: id: client_id_provided from our oauth2 server secret: secret provided from our oauth2 server scope: 'authorization_code,user_info,user_auth' redirect_uri: https://oauth2client.localnet/oauth2/check
- 创建一个控制器来接收令牌,该控制器必须与redirect_uri路径匹配。以下是一个示例代码,您可以根据需要进行修改
src/Controller/OAuth2Controller.php
namespace App\Controller; use Symfony\Component\Routing\Annotation\Route; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\SessionInterface; use BeyondBlueSky\OAuth2PKCEClient\Entity\OAuth2Session; use BeyondBlueSky\OAuth2PKCEClient\DependencyInjection\OAuth2PKCEClientExtension as OAuth2PKCEClient; /** * Default App controller. * * @Route("/oauth2") */ class OAuth2Controller extends AbstractController { /** * @Route("/login", name="oauth_login", methods={"GET"}) */ public function oauthLogin(Request $request, OAuth2PKCEClient $oauth2) { $session = new OAuth2Session(); $response= $oauth2->getAuthRedirect($session); $this->getDoctrine()->getManager()->persist($session); $this->getDoctrine()->getManager()->flush(); return $response; } /** * @Route("/check", name="oauth_check", methods={"GET"}) */ public function oauthRedirect(Request $request) { $user= $this->getUser(); if ($user == null ) { return new Response(json_encode( ['status' => false, 'message' => "User not found!"] ) ); } else { return $this->redirectToRoute('homepage'); } } }
- 创建一个用户类。最小信息应该是用户名。所有其他字段都是可选的,并在本指南的第5点中填充。在我们的情况下,我们将在Entity文件夹中创建一个Security\User。
如果您是初学者,我强烈建议您使用以下命令
$ bin/console make:entity
并遵循提出的问题,添加用户名字段以及您项目需要的所有字段。这将生成一个配置了所有所需信息的ORM配置实体。
创建您的用户后,编辑它并实现UserInterface接口,以告诉Symfony您的用户实体是Symfony用户
class User implements \Symfony\Component\Security\Core\User\UserInterface
实现UserInterface后,您必须添加一些Symfony函数
public function getRoles(): array { return ['ROLE_USER']; } public function getPassword() { return "-"; } public function getSalt() { return 1; } public function eraseCredentials() { return ; } public function getUsername(): string { return $this->email; }
- 现在我们需要一个新的认证器。使用以下代码作为模板。请考虑getUser函数,您必须用从您的OAuth2服务器收到的字段填写您的用户对象。如果您不确定接收到了什么,可以var_dump oauthUser
src/Security/OAuth2Authenticator.php
namespace App\Security; use App\Entity\Security\User; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\User\UserProviderInterface; use Doctrine\ORM\EntityManagerInterface; use BeyondBlueSky\OAuth2PKCEClient\DependencyInjection\OAuth2PKCEClientExtension as OAuth2PKCEClient; use BeyondBlueSky\OAuth2PKCEClient\Security\OAuth2PKCEAuthenticator; /** */ class OAuth2Authenticator extends OAuth2PKCEAuthenticator { public function supports(Request $request): bool{ return $request->getPathInfo() == '/oauth2/check' && $request->isMethod('GET'); } public function getUser($credentials, UserProviderInterface $userProvider) { // With this function we fetch the user's data from the credentials $oauthUser = $this->fetchUser($credentials); $login = $oauthUser->login; $user = $this->em->getRepository(User::class)->findOneBy(['username' => $login]); if (! $user ) { // Now we have to adapt to our local User $user = new User(); $user->setUsername($oauthUser->login); $user->setEmail($oauthUser->email); $user->setName($oauthUser->name); $user->setSurname1($oauthUser->surname1); $user->setSurname2($oauthUser->surname2); $user->setPassword('-'); $user->setRoles(['ROLE_USER']); //$user->setFullname($oauthUser['name']. " ".$oauthUser['surname1']. " ".$oauthUser['surname2']); $user->setCreatedAt(new \DateTime(date('Y-m-d H:i:s'))); $this->em->persist($user); $this->em->flush(); } return $user; } }
- 更新您的数据库模式:schema:update或doctrine:migrations,您选择。
$ bin/console doctrine:schema:update --force
- 配置security.yaml以指向我们新的认证器
在提供商部分中,将内存中的行替换为
config/packages/security.yaml
oauth_user_provider: entity: class: App\Entity\Security\User property: username
在firewalls > main中,引用您的新用户提供程序并添加我们在步骤5中创建的认证器
firewalls: main: anonymous: lazy provider: oauth_user_provider guard: authenticators: - App\Security\OAuth2Authenticator
- 享受您的新OAuth2认证!为了做到这一点,请转到您的Symfony根目录并在浏览器中向URL添加oauth2/login(如果您没有更改OAuth2Controller中的路径)。现在您应该看到OAuth2服务器的登录页面。
祝您玩得开心!