Maison >développement back-end >tutoriel php >Implémentation et test de l'authentification Socialite dans Laravel
Laravel Socialite est un package Laravel propriétaire qui aide les développeurs à implémenter l'authentification sociale OAuth et OAuth2 dans leurs applications. Il prend en charge Facebook, Twitter, Google, LinkedIn, GitHub, GitLab et Bitbucket. Socialite peut soutenir d'autres prestataires via des packages communautaires.
Ce message :
TLDR : vous pouvez voir le projet terminé sur mon GitHub. Jetez-y un œil si vous préférez simplement lire le code complété.
Socialite est un petit package, avec son API principale composée principalement de deux méthodes principales :
Il existe des méthodes de prise en charge supplémentaires pour les étendues de paramètres et les paramètres facultatifs. Vous pouvez en savoir plus sur eux dans la documentation Socialite.
Socialite ne pas faire ce qui suit : il laisse la mise en œuvre de ces fonctionnalités au développeur :
Nous allons mettre en place un petit projet Socialite qui permet à l'utilisateur de s'authentifier via Google. Pour ce faire, vous devez créer une application Google.
Créez d'abord un nouveau projet Google Cloud, puis configurez un écran de consentement OAuth pour le projet. Définissez le type d'utilisateur sur externe, puis activez les étendues suivantes :
Après avoir configuré l'écran de consentement, créez un ID client OAuth 2.0 en visitant la page d'informations d'identification Google Cloud. Conservez le ID client et le secret client : nous les utiliserons plus tard dans le projet.
Créez un nouveau projet Laravel :
laravel new socialite-tests
Sélectionnez les options suivantes dans le programme d'installation :
┌ Would you like to install a starter kit? ────────────────────┐ │ No starter kit │ └──────────────────────────────────────────────────────────────┘ ┌ Which testing framework do you prefer? ──────────────────────┐ │ Pest │ └──────────────────────────────────────────────────────────────┘ ┌ Which database will your application use? ───────────────────┐ │ SQLite │ └──────────────────────────────────────────────────────────────┘ ┌ Would you like to run the default database migrations? ──────┐ │ Yes │ └──────────────────────────────────────────────────────────────┘
Accédez au répertoire du projet et installez Socialite.
laravel new socialite-tests
Créez une nouvelle migration.
┌ Would you like to install a starter kit? ────────────────────┐ │ No starter kit │ └──────────────────────────────────────────────────────────────┘ ┌ Which testing framework do you prefer? ──────────────────────┐ │ Pest │ └──────────────────────────────────────────────────────────────┘ ┌ Which database will your application use? ───────────────────┐ │ SQLite │ └──────────────────────────────────────────────────────────────┘ ┌ Would you like to run the default database migrations? ──────┐ │ Yes │ └──────────────────────────────────────────────────────────────┘
Placez le code suivant dans le fichier de migration nouvellement créé dans base de données/migrations :
cd socialite-tests composer require laravel/socialite
Cette migration ajoute des champs qui seront fournis par Socialite lorsque l'utilisateur s'authentifiera avec succès. Dans notre implémentation, nous ajoutons ces champs directement à la table utilisateur pour plus de simplicité. Si vous souhaitez prendre en charge plus de fournisseurs que Google, vous souhaiterez peut-être créer un tableau distinct pouvant stocker plusieurs fournisseurs par utilisateur.
Nous définissons le mot de passe pour qu'il soit nullable, car un utilisateur ne définira jamais de mot de passe s'il s'authentifie uniquement via Google. Si votre application permet l'authentification sociale et l'authentification par mot de passe, vous devez valider que le mot de passe n'est pas vide ou nul lorsqu'un utilisateur tente de se connecter via un mot de passe.
Exécutez la migration.
php artisan make:migration add_socialite_fields_to_users
Dans config/services.php, ajoutez le bloc de code suivant à la fin du tableau services. Vous pouvez trouver une liste complète des noms de services Socialite valides dans les documents de configuration.
<?php // database/migrations/2024_12_31_075619_add_socialite_fields_to_users.php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::table('users', function (Blueprint $table) { $table->string('google_id')->default(''); $table->string('google_token')->default(''); $table->string('google_refresh_token')->default(''); // If your app allows both password and social logins, you // MUST validate that the password is not blank during login. // If you do not, an attacker could gain access to an account // that uses social login by only knowing the email. $table->string('password')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('google_id'); $table->dropColumn('google_token'); $table->dropColumn('google_refresh_token'); $table->string('password')->nullable(false)->change(); }); } };
Ajoutez ce qui suit à .env, en utilisant les informations d'identification de votre application Google que vous avez créées dans la section « prérequis ».
php artisan migrate
Remplacez le contenu de routes/web.php par le code suivant.
// config/services.php 'google' => [ 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'redirect' => '/auth/google/callback', ],
Le nouveau code de ce fichier implémente les routes pour :
Enfin, remplacez le contenu de resources/views/welcome.php par le balisage suivant.
# .env GOOGLE_CLIENT_ID="your-google-client-id" GOOGLE_CLIENT_SECRET="your-google-client-secret"
Une fois ceci terminé, nous pouvons tester manuellement l'application en exécutant le serveur de développement.
<?php // routes/web.php use App\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Route; use Laravel\Socialite\Facades\Socialite; use Laravel\Socialite\Two\InvalidStateException; use Laravel\Socialite\Two\User as OAuth2User; Route::get('/', function () { return view('welcome'); }); Route::get('/auth/google/redirect', function () { return Socialite::driver('google')->redirect(); }); Route::get('/auth/google/callback', function () { try { /** @var OAuth2User $google_user */ $google_user = Socialite::driver('google')->user(); } catch (InvalidStateException $exception) { abort(400, $exception->getMessage()); } $user = User::updateOrCreate([ 'email' => $google_user->email, ], [ 'google_id' => $google_user->id, 'name' => $google_user->name, 'google_token' => $google_user->token, 'google_refresh_token' => $google_user->refreshToken, ]); Auth::login($user); return redirect('/'); }); Route::get('/auth/logout', function () { Auth::logout(); return redirect('/'); });
Lorsque vous cliquez sur le lien Connexion avec Google, vous devez passer par le flux OAuth2 et être redirigé vers la page d'accueil où vous pouvez voir des informations sur l'utilisateur nouvellement créé par Google.
Nos tests manuels fonctionnent, mais nous aimerions que des tests automatisés vérifient que nous ne cassons pas accidentellement cette fonctionnalité à l'avenir.
Nous pouvons créer un nouveau fichier de test avec la commande suivante.
<!-- resources/views/welcome.php --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Laravel Socialite Testing Example</title> </head> <body> <h1>Laravel Socialite Testing Example</h1> @if (auth()->check()) <p>User is authenticated.</p> <p>Name: {{ auth()->user()->name }}</p> <p>Email: {{ auth()->user()->email }}</p> <p><a href="/auth/logout">Logout</a></p> @else <p>User is not authenticated.</p> <p> <a href="/auth/google/redirect">Login with Google</a> </p> @endif </body> </html>
Remplacez le contenu du test/Feature/AuthRoutesTest.php nouvellement créé par ce qui suit.
php artisan serve
Lors du test de l'itinéraire de redirection, nous testons que Socialite redirige vers la bonne URL et transmet les paramètres d'URL corrects.
Lorsque nous testons les routes de rappel, nous nous moquons de Socialite. La moquerie n'est pas mon option préférée : dans un monde idéal, nous pourrions remplacer Socialite par une autre implémentation OAuth2 et nos tests fonctionneraient toujours. Cependant, il n'existe pas de moyen simple de se connecter à la demande d'autorisation envoyée par Socialite pour saisir le jeton d'accès. Pour cette raison, la moquerie est l’approche la plus pratique pour tester Socialite.
Les API Fluent sont fastidieuses à simuler via Mockery : vous devez commencer par la fin de l'appel et remonter en arrière.
Voici la méthode Socialite invoquée par notre point de terminaison de rappel.
laravel new socialite-tests
Voici comment cela doit être moqué via Mockery :
┌ Would you like to install a starter kit? ────────────────────┐ │ No starter kit │ └──────────────────────────────────────────────────────────────┘ ┌ Which testing framework do you prefer? ──────────────────────┐ │ Pest │ └──────────────────────────────────────────────────────────────┘ ┌ Which database will your application use? ───────────────────┐ │ SQLite │ └──────────────────────────────────────────────────────────────┘ ┌ Would you like to run the default database migrations? ──────┐ │ Yes │ └──────────────────────────────────────────────────────────────┘
Enfin, nous avons un test pour garantir que la navigation directe vers l'URL de rappel en dehors du flux OAuth renvoie un code d'état 400. Nous avons encapsulé l'appel à Socialite::driver('google')->user() dans le point de terminaison de rappel dans un bloc try/catch. Si nous n'avions pas enveloppé l'appel Socialite dans un bloc try/catch et que quelqu'un avait tapé l'URL de rappel dans son navigateur, le point de terminaison lèverait une exception avec un code d'état HTTP 500. Si votre équipe a configuré une surveillance pour 500 codes d'état, quelqu'un pourrait être alerté au milieu de la nuit.
Il s'agit d'une intégration minimale, et il y a beaucoup plus qui pourraient être implémentées. Si nous implémentions une intégration avec un fournisseur social dans laquelle l'adresse e-mail de l'utilisateur pourrait changer, cette implémentation ne fonctionnerait pas car elle correspond à l'adresse e-mail. Si l'utilisateur pouvait modifier son adresse e-mail dans notre application, cette implémentation ne fonctionnerait pas non plus pour la même raison. Cependant, maintenant que vous avez vu comment tester Socialite, vous pouvez écrire des tests pour ces scénarios et modifier l'implémentation sous-jacente afin qu'ils réussissent.
J'ai lu beaucoup d'articles de blog et de forums sur Socialite avant de comprendre comment créer ma propre implémentation, comment la tester et à quoi je dois penser. J'aimerais remercier certains d'entre eux ici.
Lisez-les si vous souhaitez approfondir. Faites-moi également savoir si vous seriez intéressé par la partie 2 de cet article dans laquelle j'examine la gestion de plusieurs fournisseurs sociaux, la gestion lorsqu'un utilisateur modifie son adresse e-mail ou la gestion des jetons d'actualisation.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!