lampask / oauth
OAuth integration into Nette Framework
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
- league/oauth2-google: ^4.0
- 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
This package is auto-updated.
Last update: 2024-11-18 13:59:55 UTC
README
OAuth
👤 OAuth integration into Nette Framework
Installation
$ composer require 68publishers/oauth
Configuration
$ 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
Integration
Lazy configuration
Sometimes it may be desirable to provide the configuration for an OAuth client dynamically if, for example, we have settings stored in a database. We can do this with the following implementation:
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 # ...
Implementing Authenticator
Authenticator is a class implementing the AuthenticatorInterface
interface.
This class should return the identity of the user and throw an AuthenticationException
exception in case of any problem.
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(/* ... */); } }
Implementing OAuth Presenter
The OAuthPresenterTrait
trait is used for simple implementation.
Next, you need to define three methods that determine what should happen if the authentication is successful or fails.
All three methods should redirect at the end.
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:'); } }
Login button
The login button can be rendered simply as follows
<a n:href="OAuth:authorize, type => 'azure'">Login via Azure</a>
If you store the request (back link) using Presenter::storeRequest()
you can also pass it the URL.
Your OAuthPresenter
will then automatically redirect to this link after successful authentication.
<a n:href="OAuth:authorize, type => 'azure', backLink => $backLink">Login via Azure</a>
License
The package is distributed under the MIT License. See LICENSE for more information.