Login with Socialite
Register the provider
Since Laravel 11 there is no default EventServiceProvider. Add the listener in the boot() method of your AppServiceProvider:
use Illuminate\Support\Facades\Event;
public function boot(): void
{
Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) {
$event->extendSocialite('anikeen', \Anikeen\Id\Socialite\Provider::class);
});
}The user model
Your users table needs the user's Anikeen ID and their tokens:
Schema::table('users', function (Blueprint $table) {
$table->string('anikeen_id')->nullable()->unique();
$table->text('anikeen_id_access_token')->nullable();
$table->text('anikeen_id_refresh_token')->nullable();
});Add the Billable trait. Keep the tokens encrypted and out of JSON:
use Anikeen\Id\Billable;
class User extends Authenticatable
{
use Billable;
protected $hidden = ['password', 'remember_token', 'anikeen_id_access_token', 'anikeen_id_refresh_token'];
protected function casts(): array
{
return [
'anikeen_id_access_token' => 'encrypted',
'anikeen_id_refresh_token' => 'encrypted',
];
}
}All user methods ($user->orders(), $user->subscriptions(), …) call the API with the user's access token from anikeen_id_access_token.
Other column names
If your columns are named differently, set them in AppServiceProvider::boot():
use Anikeen\Id\AnikeenId;
AnikeenId::useAccessTokenField('anikeen_id_access_token');
AnikeenId::useRefreshTokenField('anikeen_id_refresh_token');
AnikeenId::useUserIdField('anikeen_id'); // the column holding the user's Anikeen IDLogin and callback
Ask for the scopes your app needs. Without any, the provider asks for user:read. A shop selling orders and subscriptions typically asks for:
use Laravel\Socialite\Facades\Socialite;
Route::get('auth/redirect', fn () => Socialite::driver('anikeen')
->scopes(['user:read', 'addresses:read', 'orders', 'subscriptions'])
->redirect());
Route::get('auth/callback', function () {
$account = Socialite::driver('anikeen')->user();
$user = User::updateOrCreate(['anikeen_id' => $account->getId()], [
'name' => $account->getName() ?: $account->getNickname(),
'email' => $account->getEmail(),
'anikeen_id_access_token' => $account->token,
'anikeen_id_refresh_token' => $account->refreshToken,
]);
Auth::login($user, remember: true);
return redirect()->intended('/');
});The Socialite user maps id, nickname (the username), name, email and avatar; the raw profile is in $account->getRaw().
The user's role (trusted apps)
Trusted apps also get the user's Anikeen ID role, admin (runs Anikeen) or user (constants on Anikeen\Id\Enums\Role); for other apps it is null. Read it at sign-in and keep it current with the user.updated webhook:
use Anikeen\Id\Enums\Role;
$account = Socialite::driver('anikeen')->user();
$user->update(['role' => $account->role ?? Role::USER]);Refreshing tokens
Access tokens expire. Get a new one with the refresh token (or send the user through the login again):
$result = app(\Anikeen\Id\AnikeenId::class)->refreshToken($user->anikeen_id_refresh_token);
if ($result->success()) {
$user->update([
'anikeen_id_access_token' => $result->data()->access_token,
'anikeen_id_refresh_token' => $result->data()->refresh_token,
]);
}Logging out of Anikeen ID
$url = Socialite::driver('anikeen')->getLogoutUrl(url('/'));sends the user to Anikeen ID's logout, which redirects back to your app.