68publishers / oauth
Nette 框架中的 OAuth 集成
v1.0.0
2024-01-29 01:14 UTC
Requires
- php: ^8.1
- ext-json: *
- league/oauth2-client: ^2.7
- nette/application: ^3.1
- nette/di: ^3.0
- nette/http: ^3.2
- nette/security: ^3.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.48
- kubawerlos/php-cs-fixer-custom-fixers: ^3.19
- league/oauth2-facebook: ^2.2
- mockery/mockery: ^1.6
- nette/bootstrap: ^3.1
- nette/tester: ^2.5
- phpstan/phpstan: ^1.10
- roave/security-advisories: dev-latest
- thenetworg/oauth2-azure: ^2.2
Conflicts
- nette/component-model: <3.0.2
README
OAuth
👤 Nette 框架中的 OAuth 集成
安装
$ composer require 68publishers/oauth
配置
$ composer require league/oauth2-facebook
extensions: 68publishers.oauth: SixtyEightPublishers\OAuth\Bridge\Nette\DI\OAuthExtension 68publishers.facebook: SixtyEightPublishers\OAuth\Bridge\Nette\DI\FacebookOAuthExtension 68publishers.facebook: flowName: facebook # default, not necessary to define config: enabled: true # default, not necessary to define clientId: '<client id>' clientSecret: '<client id>' graphApiVersion: '<graph api version>' options: [] # additional options that are passed into the client authenticator: App\OAuth\FacebookAuthenticator
Azure
$ composer require thenetworg/oauth2-azure
extensions: 68publishers.oauth: SixtyEightPublishers\OAuth\Bridge\Nette\DI\OAuthExtension 68publishers.azure: SixtyEightPublishers\OAuth\Bridge\Nette\DI\FacebookOAuthExtension 68publishers.azure: flowName: azure # default, not necessary to define config: enabled: true # default, not necessary to define clientId: '<client id>' clientSecret: '<client id>' tenantId: '<tenant id>' # optional, use this option only if your Azure Entra ID application is configured as a single tenant. options: [] # additional options that are passed into the client authenticator: App\OAuth\AzureAuthenticator
集成
懒配置
有时可能需要动态地提供 OAuth 客户端的配置,例如,如果我们在数据库中存储了设置。我们可以通过以下实现来完成这项工作:
namespace App\OAuth\Config; use SixtyEightPublishers\OAuth\Config\Config; use SixtyEightPublishers\OAuth\Config\LazyConfig; use App\SettingsProvider; final class AzureConfig extends LazyConfig { public function __construct(SettingsProvider $provider) { parent::__construct( configFactory: static function (): Config { return new Config( flowEnabled: $provider->get('azure.enabled'), options: [ 'clientId' => $provider->get('azure.clientId'), 'clientSecret' => $provider->get('azure.clientSecret'), ], ); } ); } }
# ... 68publishers.azure: config: App\OAuth\Config\AzureConfig # ...
实现 Authenticator
Authenticator 是一个实现了 AuthenticatorInterface
接口的类。这个类应该返回用户的身份,并在出现任何问题时抛出 AuthenticationException
异常。
namespace App\OAuth; use SixtyEightPublishers\OAuth\Authentication\AuthenticatorInterface; use SixtyEightPublishers\OAuth\Exception\AuthenticationException; use SixtyEightPublishers\OAuth\Authorization\AuthorizationResult; use Nette\Security\IIdentity; use Nette\Security\SimpleIdentity; final class AzureAuthenticator implements AuthenticatorInterface { public function authenticate(string $flowName, AuthorizationResult $authorizationResult): IIdentity { $accessToken = $authorizationResult->accessToken; $resourceOwner = $authorizationResult->resourceOwner; if ($userCannotBeAuthenticated) { throw new AuthenticationException('User can not be authenticated.'); } return new SimpleIdentity(/* ... */); } }
实现 OAuth Presenter
使用 OAuthPresenterTrait
特性进行简单实现。接下来,你需要定义三个方法,这些方法决定了如果认证成功或失败时应该发生什么。所有三个方法都应该在最后进行重定向。
namespace App\Presenter; use Nette\Application\UI\Presenter; use SixtyEightPublishers\OAuth\Bridge\Nette\Application\OAuthPresenterTrait; use SixtyEightPublishers\OAuth\Exception\OAuthExceptionInterface; final class OAuthPresenter extends Presenter { use OAuthPresenterTrait; protected function onAuthorizationRedirectFailed(string $flowName, OAuthExceptionInterface $error): void { $this->flashMessage('Authentication failed', 'error'); $this->redirect('SignIn:'); } abstract protected function onAuthenticationFailed(string $flowName, OAuthExceptionInterface $error): void { $this->flashMessage('Authentication failed', 'error'); $this->redirect('SignIn:'); } abstract protected function onUserAuthenticated(string $flowName): void { $this->flashMessage('You have been successfully logged in', 'success'); $this->redirect('Homepage:'); } }
登录按钮
登录按钮可以简单地按照以下方式渲染
<a n:href="OAuth:authorize, type => 'azure'">Login via Azure</a>
如果你使用 Presenter::storeRequest()
存储请求(回链),你也可以传递 URL。然后,你的 OAuthPresenter
将在成功认证后自动重定向到该链接。
<a n:href="OAuth:authorize, type => 'azure', backLink => $backLink">Login via Azure</a>
许可证
该软件包在 MIT 许可证下分发。有关更多信息,请参阅 LICENSE。