codewiser/socialiteprovider

Zenit OAuth2 Provider for Laravel Socialite

v1.1.0 2024-10-31 15:05 UTC

This package is auto-updated.

Last update: 2024-12-31 00:27:11 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 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'])