Guide de connexion - betagouv/omniauth-proconnect GitHub Wiki
Ce manuel vous guidera dans l'installation et l'utilisation de ProConnect (PC) dans votre application avec cette librairie qui fournit une stratégie OmniAuth adaptée.
Le flux OpenID Connect (OIDC) se résume à :
- Redirection : L'utilisateur est redirigé vers le serveur d'authentification (ProConnect)
- Authentification : L'utilisateur s'authentifie et revient avec un code d'autorisation
- Échange : Votre serveur échange ce code contre un token d'accès et les informations utilisateur.
D'autres cinématiques sont possibles mais c'est celle là (3-legged) qui nous intéresse dans le schéma typique d'une application web.
En combinant avec une stratégie OmniAuth
, voici la cinématique de connexion :
- votre utilisateur veut se connecter et choisi le bouton ProConnect
- le bouton ProConnect
POST
surlocalhost:3000/auth/proconnect
- cette URL (
/auth/proconnect
) est intercepté par le middleware OmniAuth qui délègue à la stratégie enregistrée pourproconnect
(et donc :omniauth-proconnect
) - la stratégie génère et redirige vers une URL pour aller sur ProConnect et
aussi où revenir (
302 Location: http://proconnect.fr/machin?redirect_uri=localhost:3000/auth/proconnect/callback
) - l'utilisateur est redirigé vers et s'authentifie sur ProConnect
- ProConnect émet alors une redirection en utilisant la
redirect_uri
du 4) et rajoute un code dans les paramètres (?code=machin
) - l'URL de retour
(
http://localhost:3000/auth/proconnect/callback?code=machin
) est elle aussi interceptée parOmniAuth
et la stratégie ProConnect - la stratégie prend le code (
?code=machin
), et l'échange de serveur (vous) à serveur (ProConnect) pour un jeton et des informations (email, uid, etc) - la stratégie peuple
request.env["omniauth.auth"]
avec ces informations puis rend la main - votre application continue et termine en invoquant l'action configurée pour
/auth/proconnect/callback
, enrichie grâce aux étapes 8 & 9. - à vous de jouer
NOTE : les endpoints d'initiation/redirection sont configurables mais les valeurs par défaut sont parfaitement valables.
sequenceDiagram
participant U as 👤 Utilisateur
participant B as 🌐 Navigateur
participant A as 🖥️ Votre app<br/>(localhost:3000)
participant O as 📦 Stratégie<br/>OmniAuth
participant P as 🏛️ serveur ProProConnect<br/>Server
Note over U,P: Flux d'authentification ProConnect (OpenID Connect)
%% Étape 1: Accès à la page de connexion
U->>+B: Visite le site web
B->>+A: GET /login
A-->>-B: Page de connexion avec bouton ProConnect
B-->>-U: Affiche la page de connexion
%% Étape 2: Choix de ProConnect et redirection
U->>+B: Clique "Se connecter avec ProConnect"
B->>+A: POST /auth/proconnect
Note right of A: Intercepté par la stratégie OmniAuth
A->>+O: Activation de la stratégie ProConnect
O-->>-A: Génère la redirection vers ProConnect
A-->>-B: Redirection vers ProConnect
Note right of A: HTTP 302 Redirect<br/>Location: https://proconnect.gouv.machin/authorize?<br/>redirect_uri=localhost:3000/auth/proconnect<br/>client_id, response_type=code, scope
B->>+P: GET https://proconnect.gouv.machin/authorize?client_id=...&redirect_uri=...
P-->>-B: Page d'authentification ProConnect
B-->>-U: Affiche le formulaire de connexion
%% Étape 3: Authentification et retour avec code
U->>+B: Saisit ses identifiants ProConnect
B->>+P: POST /login (authentification)
P-->>-B: Redirection avec authorization_code
Note right of P: HTTP 302 Redirect<br/>Location: localhost:3000/auth/proconnect?code=abc123
B->>+A: GET /auth/proconnect?code=abc123
%% Étape 4: Interception par OmniAuth et échange de tokens
Note over A,O: La requête est interceptée par OmniAuth
A->>+O: Activation de la stratégie ProConnect
O->>+P: POST /oauth/token
Note right of O: Échange du code contre tokens<br/>{code: "abc123", client_id, client_secret, etc...}
P-->>-O: access_token + id_token + user_info
Note left of P: Réponse JSON avec tokens<br/>et informations utilisateur déchiffrées
%% Étape 5: Traitement des données et réponse finale
O-->>-A: Peuple request.env["omniauth.auth"]
Note right of O: Données utilisateur disponibles:<br/>uid, email, nom, prénom, etc.
A->>A: Traitement de l'authentification<br/>(création/connexion utilisateur)
A-->>-B: Redirection vers tableau de bord
B-->>U: Utilisateur connecté ✅
Accédez à l'espace partenaires de
ProConnect et créez une
application. Stockez vos identifiants (client_id
, client_secret
) quelque
part (Rails.credentials
, variables d'environnement, etc).
Installez les gems requises :
+gem "omniauth"
+gem "omniauth-rails_csrf_protection"
+gem "omniauth-proconnect"
Comme vu au début de ce guide, vous avez besoin de trois routes :
- une route pour présenter les options de connexion (
/login
) - une route d'initiation du flot, celle qui calcule l'URL pour rediriger vers
ProConnect : cette route est automatiquement écoutée par le middleware de la
stratégie, par défaut :
/auth/proconnect
- une route pour accueillir le redirect de ProConnect : cette route est elle
aussi automatiquement interceptée par le middelware de la stratégie, par
défaut
/auth/proconnect/callback
, mais la stratégie rend la main à Rack une fois son travail effectué : votre serveur doit donc mapper une destination à cette route.
# config/routes.rb
+get "sessions/new", as: :login, to: "sessions#new" # login
+get "auth/:provider/callback", to: "sessions#create" # retour de ProConnect
# pas besoin de `post "/auth/proconnect"`, la stratégie la fournit déjà
Nous utilisons ici un placeholder :provider
générique pour tirer profit de
l'architecture d'OmniAuth qui permet de brancher plusieurs fournisseurs
d'identité et de récupérer une information homogène derrière : si dans le futur
vous décidez d'intégrer autre chose (ex: FranceConnect), votre configuration ne
change pas, les stratégies s'occupent de tout et vous recevez la même
information (email
, etc) dans sessions#create
.
Vous avez donc désormais les trois routes nécessaires :
-
/login
; -
/auth/proconnect
(enregistré par la librairie) ; -
/auth/proconnect/callback
(enregistré par la librairie, mais que vous devez réceptionner ensuite).
Pour gérer ces routes :
# app/controllers/sessions_controller
class SessionsController < ApplicationController
def new
render :new
end
def create
@user = User.from_oidc(request.env["omniauth.auth"]) # voir ci-dessous
if @user.save
redirect_to root_path, notice: "Connexion réussie pour #{email}"
else
redirect_to login_path, alert: "Impossible de connecter #{email}"
end
end
end
OmniAuth permettant d'utiliser plusieurs stratégies de manière transparente,
nous créons ici une fonction qui permet d'initialiser ou de trouver un
utilisateur selon des attributs rassemblés par les stratégies (uid
et
info.email
), et aussi d'éviter au controller d'en faire trop :
# app/models/user.rb
class User
class << self
def from_oidc(data)
find_or_initialize_by(uid: data.uid) do |user|
user.email = data.info.email
end
end
end
end
NOTE : l'attribut uid
est l'identifiant unique dans le cadre de votre
fournisseur d'identité (ici : ProConnect), c'est avec ça que vous devez les
distinguer.
Retournez sur l'espace partenaires de
ProConnect et renseignez votre URL de
redirection, dans notre cas : http://localhost:3000/auth/proconnect/callback
.
Le domaine ProConnect est l'URL du serveur vers lequel se tourne votre utilisateur et plus tard l'application. Vous pouvez retrouvez celle qui vous correspond à votre cas d'usage sur la page PROCONNECT_DOMAIN de la documentation ProConnect.
En restant dans l'optique de ce guide, nous sommes en intégration hors-RIE donc
le domaine est fca.integ01.dev-agentconnect.fr
.
/api/v2
pour obtenir le vrai endpoint qui permet l'interaction. La vraie URL
est donc https://fca.integ01.dev-agentconnect.fr/api/v2
.
Il faut désormais enregistrer et configurer la stratégie avec les bonnes
valeurs. Par souci de simplification elles sont directement renseignées ici mais
vous devez bien évidemment les stocker dans votre environnement, dans vos
Rails.credentials
ou quelque part de sûr et confidentiel.
# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider(
:proconnect, # permet à OmniAuth d'inférer la stratégie OmniAuth::Proconnect
{
client_id: "foo",
client_secret: "bar",
proconnect_domain: "https://fca.integ01.dev-agentconnect.fr/api/v2",
redirect_uri: "http://localhost:3000/auth/proconnect/callback",
post_logout_redirect_uri: "", # c.f fin du guide
scope: "" # c.f fin du guide
}
)
end
Dans votre page de login (i.e : app/sessions/new.html.erb
), insérez un bouton
qui déclenche la stratégie ProConnect en effectuant un POST
sur
/auth/proconnect
.
À terme, intégrez-le comme le veut la documentation du bouton
ProConnect
(si vous utilisez déjà dsfr-view-components
le bouton ProConnect est
disponible)
et en attendant :
<div>
<form action="/auth/proconnect" method="post" data-turbo="false">
<button class="proconnect-button fr-btn">
<span class="proconnect-sr-only">S'identifier avec ProConnect</span>
</button>
</form>
</div>
Et c'est bon ! Vous devriez pouvoir effectuer un login test en utilisant les identifiants de test de ProConnect.
- n'oubliez pas de déconnecter vos utilisateurs correctement
- vous pouvez configurer les informations demandées à ProConnect