codewiser / socialiteprovider
Zenit OAuth2 Provider for Laravel Socialite
Requires
- php: ^7.4 || ^8.0
- ext-json: *
- laravel/framework: >=10.0
- laravel/sanctum: >=3.0
- league/oauth2-client: ^2.7
- socialiteproviders/manager: ~4.0
Requires (Dev)
- phpunit/phpunit: ^10.0
README
composer require codewiser/socialiteprovider
Installation & Basic Usage
Please see the Base Installation Guide, then follow the provider specific instructions below.
Add configuration to config/services.php
'zenit' => [ 'base_uri' => env('ZENIT_SERVER'), 'client_id' => env('ZENIT_CLIENT_ID'), 'client_secret' => env('ZENIT_CLIENT_SECRET'), 'redirect' => env('ZENIT_REDIRECT_URI'), // optional attributes (with default values): 'auth_endpoint' => 'auth', 'token_endpoint' => 'oauth/token', 'user_endpoint' => 'api/user', 'token_introspect_endpoint' => 'token_info', 'client_manage_endpoint' => 'oauth/client', ],
Add provider event listener
Configure the package's listener to listen for SocialiteWasCalled
events.
Add the event to your listen[]
array in app/Providers/EventServiceProvider
.
See the Base Installation Guide for
detailed instructions.
protected $listen = [ \SocialiteProviders\Manager\SocialiteWasCalled::class => [ // ... other providers \SocialiteProviders\Zenit\ZenitExtendSocialite::class, ], ];
Usage
You should now be able to use the provider like you would regularly use Socialite (assuming you have the facade installed):
return Socialite::driver('zenit')->redirect();
Returned User fields
id
nickname
name
email
avatar
Access Token
Access Token is now an object, not just a string.
$user = Socialite::driver('zenit')->user(); $token = $user->token; // \League\OAuth2\Client\Token\AccessToken
Error Response
Package provides response error handling compliant to rfc6749.
try { $user = Socialite::driver('zenit')->user(); } catch (OAuth2Exception $e) { return match ($e->getError()) { // Show response to the user 'access_denied', 'server_error', 'temporarily_unavailable' => redirect() ->to(route('login')) ->with('error', $e->getMessage()), // Silently 'interaction_required' => redirect()->to('/'), // Unrecoverable default => throw $e, }; }
Token Introspection
Package provides token introspection compliant to rfc7662.
use \Illuminate\Http\Request; use \SocialiteProviders\Zenit\rfc7662\IntrospectedTokenInterface; public function api(Request $request) { /** @var IntrospectedTokenInterface $token */ $token = Socialite::driver('zenit') ->introspectToken($request->bearerToken()); if ($token->isActive()) { // } }
Get user using existing token
$user = Socialite::driver('zenit') ->userFromToken($request->bearerToken());
Refreshing Token
$token = Socialite::driver('zenit') ->refreshToken($refresh_token);
Client Token
$token = Socialite::driver('zenit') ->grantClientCredentials('scope-1 scope-2');
Token by username and password
$token = Socialite::driver('zenit') ->grantPassword($username, $password, 'scope-1 scope-2');
Token by custom grant
$token = Socialite::driver('zenit') ->grant('custom_grant', [/* any request params */]);
Manage client
Package provides token introspection compliant to rfc7592.
use SocialiteProviders\Zenit\ClientConfiguration; $config = new ClientConfiguration( Socialite::driver('zenit')->getClientConfiguration() );
use SocialiteProviders\Zenit\ClientConfiguration; use SocialiteProviders\Zenit\ClientScope; $config = new ClientConfiguration(); $config->name = 'name'; $config->namespace = 'namespace'; $config->redirect_uri = 'https://example.com'; $scope = new ClientScope(); $scope->name = 'name'; $scope->description = 'description'; $scope->aud = ['personal']; $scope->realm = 'public'; $config->scopes->add($scope) // etc Socialite::driver('zenit')->updateClientConfiguration($config->toUpdateArray());
Token authorization
Register auth driver, that authorizes incoming requests with bearer tokens, issued by some OAuth 2.0 server.
Socialite provider should implement TokenIntrospectionInterface
.
use SocialiteProviders\Zenit\Auth\TokenAuthorization; use Laravel\Socialite\Facades\Socialite; use Illuminate\Support\Facades\Auth; Auth::viaRequest('access_token', new TokenAuthorization( socialiteProvider: 'zenit', userProvider: Auth::createUserProvider(config('auth.guards.api.provider')), cache: cache()->driver() ));
Next, register driver for the guard:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'access_token', 'provider' => 'users', ] ]
As access_token may not be associated with a user, the Authenticatable
object is a Client
class. It exists only during request.
use Illuminate\Http\Request; use Laravel\Sanctum\Contracts\HasApiTokens; public function index(Request $request) { $authenticated = $request->user(); if ($authenticated instanceof HasApiTokens) { // Check scope $authenticated->currentAccessToken()->scope(); } }
Other hand, you may use the ScopedToken
middleware to inspect token scopes:
use Illuminate\Support\Facades\Route; use SocialiteProviders\Zenit\Middlewares\ScopedToken; Route::get('example', 'ctl') ->middleware([ScopedToken::class.':my-scope,foo,bar'])