Authentification Sociale avec Google
Dans cette dernière partie du tutoriel, nous allons donner aux utilisateurs la possibilité de se connecter avec Google. Actuellement, ils ne peuvent se connecter qu'avec un email et un mot de passe.
Pour ce faire, vous utiliserez le système d'authentification sociale de Foal.
Cette section suppose que vous avez déjà configuré une application Google et que vous avez récupéré votre ID client et votre secret. Si ce n'est pas le cas, vous pouvez d'abord consulter cette page. Les URI de redirection autorisés dans votre application Google doivent inclure
http://localhost:3001/api/auth/google/callback
.
Mots de Passe Nullables
La première étape est de mettre à jour le modèle User
. Certains utilisateurs peuvent n'utiliser que le login social et donc ne pas avoir de mot de passe. Pour prendre cela en compte, nous allons faire en sorte que la colonne password
accepte des valeurs nulles.
Ouvrez user.entity.ts
et mettez à jour son contenu.
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
email: string;
@Column({ nullable: true })
password: string;
@Column()
name: string;
@Column()
avatar: string;
}
export { DatabaseSession } from '@foal/typeorm';
Générez et exécutez les migrations.
npm run makemigrations
npm run migrations
Ouvrez ensuite auth.controller.ts
et ajoutez une condition pour vérifier si la valeur du mot de passe est null
dans la base de données.
if (!user.password) {
return new HttpResponseUnauthorized();
}
if (!(await verifyPassword(password, user.password))) {
return new HttpResponseUnauthorized();
}
Configuration
Maintenant que le problème du mot de passe est résolu, vous pouvez installer les paquets et fournir vos informations d'identification sociale dans la configuration.
npm install @foal/social node-fetch@2
config/default.json
{
"port": "env(PORT)",
"settings": {
...
"social": {
"google": {
"clientId": "env(GOOGLE_CLIENT_ID)",
"clientSecret": "env(GOOGLE_CLIENT_SECRET)",
"redirectUri": "http://localhost:3001/api/auth/google/callback"
}
},
},
...
}
.env
# ...
GOOGLE_CLIENT_ID="your Google client ID"
GOOGLE_CLIENT_SECRET="your Google client secret"
Le Contrôleur Social
Créez le contrôleur.
foal generate controller api/social-auth --register
Ouvrez le fichier et ajoutez deux nouvelles routes.
Point de terminaison | Méthode | Description |
---|---|---|
/api/auth/google | POST | Redirige l'utilisateur vers la page de connexion de Google. |
/api/auth/google/callback | GET | Gère la redirection depuis Google une fois que l'utilisateur a approuvé la connexion. |
import { Context, dependency, Get, HttpResponseRedirect, Session } from '@foal/core';
import { GoogleProvider } from '@foal/social';
import { User } from '../../entities';
import * as fetch from 'node-fetch';
import { Disk } from '@foal/storage';
interface GoogleUserInfo {
email: string;
name?: string;
picture?: string;
}
export class SocialAuthController {
@dependency
google: GoogleProvider;
@dependency
disk: Disk;
@Get('/google')
redirectToGoogle() {
return this.google.redirect();
}
@Get('/google/callback')
async handleGoogleRedirection(ctx: Context<User, Session>) {
const { userInfo } = await this.google.getUserInfo<GoogleUserInfo>(ctx);
if (!userInfo.email) {
throw new Error('Google should have returned an email address.');
}
let user = await User.findOne({ email: userInfo.email });
if (!user) {
user = new User();
user.email = userInfo.email;
user.avatar = '';
user.name = userInfo.name ?? 'Unknown';
if (userInfo.picture) {
const response = await fetch(userInfo.picture);
const { path } = await this.disk.write('images/profiles/uploaded', response.body)
user.avatar = path;
}
await user.save();
}
ctx.session.setUser(user);
ctx.user = user;
return new HttpResponseRedirect('/');
}
}
Ouvrez api.controller.ts
et remplacez le préfixe du chemin du SocialAuthController
par /auth
.
subControllers = [
controller('/stories', StoriesController),
controller('/auth', AuthController),
controller('/profile', ProfileController),
controller('/auth', SocialAuthController)
];
Allez sur http://localhost:3001/login et cliquez sur le bouton Connect with Google. Vous êtes redirigé vers la page de connexion de Google. Une fois que vous avez validé la connexion, vous êtes redirigé vers la page d'accueil. Si vous avez une photo de profil Google, vous la verrez sur votre page de profil.
Pour que cela fonctionne, vous devez vous assurer que vous utilisez le port
3001
pour tester la connexion sociale. Cela suppose que vous avez créé la build de production dans l'étape précédente de ce tutoriel. Vous ne pouvez pas utiliser le serveur de développement React ici car les redirections ne fonctionneront pas avec les deux ports3000
et3001
.
Félicitations ! Vous avez atteint la fin de ce tutoriel. Vous pouvez trouver le code source complet ici.