codewiser/socialiteprovider

Zenit OAuth2 Provider for Laravel Socialite

v1.1.2 2025-03-05 08:49 UTC

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 remote client management compliant to rfc7592. It allows to read OAuth client properties...

use SocialiteProviders\Zenit\ClientConfiguration;

$config = new ClientConfiguration(
    Socialite::driver('zenit')->getClientConfiguration()
);

...and update it programmatically:

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 would authorize incoming requests with bearer tokens, issued by oauth server.

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',
    ]
]

Usually, access_token associated with a user, but client_credentials access_token is not. Such access_token associated with oauth client only.

So, the Authenticatable may be as App\User, as SocialiteProviders\Zenit\Auth\Client class.

We expect that User implements Laravel\Sanctum\Contracts\HasApiTokens, as Client implements it too. If so, the Authenticatable will be injected with incoming token (aka current access token).

Current access token implements Laravel\Sanctum\Contracts\HasAbilities interface, so you may inspect its scopes and abilities.

use Illuminate\Http\Request;
use Laravel\Sanctum\Contracts\HasApiTokens;

public function index(Request $request) {
    $authenticated = $request->user();
    
    // Check scope
    $authenticated->currentAccessToken()->can('my-scope');
}

As current access token looks and behave like Sanctum token, we may protect routes with Laravel\Sanctum\Http\Middleware\CheckAbilities or Laravel\Sanctum\Http\Middleware\CheckForAnyAbility middlewares, as described in official documentation.

Route::get('/orders', function () {
    // Token has both "check-status" and "place-orders" abilities...
})->middleware(['auth:api', 'abilities:check-status,place-orders']);