Backend
- @adonisjs/ally installé + provider Google configuré (config/ally.ts)
scopes: userinfo.email + userinfo.profile (non-sensibles, validation
auto par Google)
- Migration : ajoute google_id (nullable unique) sur users + rend password
nullable (un user créé via Google n'a pas de mdp en base, il pourra
l'activer plus tard via "mot de passe oublié")
- AuthGoogleController.redirect : entrée OAuth (le bouton SPA pointe ici)
- AuthGoogleController.callback : matche par google_id puis email,
crée org+plans+user si nouveau, pose le refresh cookie httpOnly,
redirige le browser vers le SPA /auth/google/complete?next=...
(next = / pour user complet, /onboarding/entreprise pour nouveau)
- Routes : GET /api/v1/auth/google/{redirect,callback}
- Env : GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_CALLBACK_URL
Frontend
- Composant GoogleButton réutilisable (full-page redirect, pas fetch —
OAuth nécessite navigation pour les cookies cross-origin Google)
- AuthDivider "ou" entre SSO et formulaire email/password
- Boutons ajoutés sur /login et /signup
- Route /auth/google/complete : appelle POST /api/v1/auth/refresh (le
cookie posé par la callback est auto-envoyé), stocke access token +
user dans authStore, navigue vers `next`. Échec → /login + toast.
- Toast d'erreur sur /login si on revient avec ?google=denied|error|...
K3s
- ConfigMap rubis-api-config : ajout GOOGLE_CALLBACK_URL prod
- Secret rubis-app-secrets : ajout GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET
(posés via kubectl, pas dans le manifest)
Doc
- .claude/deploy-memory.md mis à jour avec la procédure Google Cloud
Console (créer OAuth client, redirect URIs, écran de consentement)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
import env from '#start/env'
|
|
import { defineConfig, services } from '@adonisjs/ally'
|
|
|
|
/**
|
|
* Configuration des providers OAuth (Ally).
|
|
*
|
|
* V1 : Google uniquement (cf. CLAUDE.md → Auth). Les autres viendront
|
|
* plus tard si pertinent (Microsoft pour les TPE qui utilisent O365 ?).
|
|
*
|
|
* Le callback URL pointe vers l'API en interne (/api/v1/auth/google/callback).
|
|
* En prod, le reverse proxy nginx (rubis-web) achemine /api/* vers ce
|
|
* service, donc la même URL fonctionne pour le browser et pour Google.
|
|
*/
|
|
const allyConfig = defineConfig({
|
|
google: services.google({
|
|
clientId: env.get('GOOGLE_CLIENT_ID', ''),
|
|
clientSecret: env.get('GOOGLE_CLIENT_SECRET', ''),
|
|
callbackUrl: env.get(
|
|
'GOOGLE_CALLBACK_URL',
|
|
'http://localhost:3333/api/v1/auth/google/callback'
|
|
),
|
|
// Scopes minimaux : on a juste besoin de l'email + nom + photo (avatar
|
|
// optionnel V2). Pas de Drive/Calendar : on ne touche pas aux données
|
|
// Google de l'utilisateur, on s'en sert juste comme provider d'identité.
|
|
scopes: ['userinfo.email', 'userinfo.profile'],
|
|
prompt: 'select_account',
|
|
}),
|
|
})
|
|
|
|
export default allyConfig
|
|
|
|
declare module '@adonisjs/ally/types' {
|
|
interface SocialProviders extends InferSocialProviders<typeof allyConfig> {}
|
|
}
|
|
|
|
import type { InferSocialProviders } from '@adonisjs/ally/types'
|