
Comment ajouter plusieurs fournisseurs d'authentification à votre site Optimizely CMS 12
Si vous développez un site Optimizely CMS 12 qui doit prendre en charge différents types d'utilisateurs, vous aurez probablement besoin de plusieurs options de connexion. Votre équipe marketing pourrait utiliser des comptes Microsoft, les partenaires externes pourraient préférer la connexion Google, et les clients pourraient vouloir créer des comptes locaux avec seulement un courriel et un mot de passe.
Configurer plusieurs fournisseurs d'authentification dans Optimizely CMS 12 n'est pas compliqué, mais faire fonctionner tous les éléments ensemble nécessite une configuration minutieuse. Ce guide vous explique comment ajouter l'authentification Entra ID (anciennement Azure AD), Google, Facebook et l'identité locale à votre site; tout en gardant la connexion administrateur CMS intégrée entièrement fonctionnelle.
Prérequis
Avant de commencer à configurer les fournisseurs d'authentification, assurez-vous d'avoir :
- Un site Optimizely CMS 12 fonctionnant sur .NET 6 ou plus récent
- Un accès administrateur à votre locataire Entra ID (si vous utilisez l'authentification Microsoft)
- Des comptes développeur pour Google Cloud Console et/ou le portail développeur Facebook
- Une compréhension de base du middleware d'authentification ASP.NET Core
- L'accès pour mettre à jour les fichiers de configuration de votre site et déployer les changements
Nous avons appris qu'avoir des comptes de test prêts pour chaque fournisseur fait gagner beaucoup de temps de débogage plus tard. Créez des utilisateurs de test dédiés dans chaque système avant de commencer l'implémentation.
Implémentation étape par étape
Étape 1 : Installer les paquets NuGet requis
Commencez par ajouter les paquets d'authentification dont votre site a besoin. Ouvrez votre terminal dans le répertoire du projet et exécutez :
dotnet add package EPiServer.CMS.UI.AspNetIdentity dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect dotnet add package Microsoft.IdentityModel.Protocols.OpenIdConnect dotnet add package Microsoft.AspNetCore.Authentication.Google dotnet add package Microsoft.AspNetCore.Authentication.Facebook
Ces paquets fournissent la base pour la gestion de l'identité locale et l'intégration OAuth2/OpenID Connect avec des fournisseurs externes.
Étape 2 : Configurer l'identité locale pour les utilisateurs CMS
L'identité locale gère les connexions traditionnelles courriel/mot de passe à /util/login. Ajoutez cette configuration à votre Startup.cs ou Program.cs :
services.AddCmsAspNetIdentity<SiteUser>(options => {
options.ConnectionStringOptions = new ConnectionStringOptions {
Name = "EPiServerDB",
ConnectionString = Configuration.GetConnectionString("EPiServerDB")
};
});Cela permet à vos comptes administrateur CMS existants de continuer à fonctionner exactement comme avant. La classe SiteUser devrait hériter de IdentityUser et inclure toutes les propriétés personnalisées dont vous avez besoin pour vos utilisateurs.
Étape 3 : Configurer l'authentification Entra ID
Entra ID (le service d'identité infonuagique de Microsoft) sert généralement de méthode d'authentification principale pour les utilisateurs d'entreprise. Voici la configuration complète :
services.AddAuthentication()
.AddCookie("azure-cookie", options => {
options.Events = new CookieAuthenticationEvents {
OnSignedIn = async ctx => {
if (ctx.Principal?.Identity is ClaimsIdentity id) {
var sync = ctx.HttpContext.RequestServices
.GetRequiredService<ISynchronizingUserService>();
await sync.SynchronizeAsync(id);
}
}
};
})
.AddOpenIdConnect("azure", options => {
options.SignInScheme = "azure-cookie";
options.ResponseType = OpenIdConnectResponseType.Code;
options.UsePkce = true;
options.ClientId = Configuration["Authentication:AzureClientID"];
options.ClientSecret = Configuration["Authentication:AzureClientSecret"];
options.Authority = Configuration["Authentication:AzureAuthority"];
options.CallbackPath = new PathString("/signin-oidc");
// Configurer les portées
options.Scope.Clear();
options.Scope.Add(OpenIdConnectScope.OpenIdProfile);
options.Scope.Add(OpenIdConnectScope.OfflineAccess);
options.Scope.Add(OpenIdConnectScope.Email);
// Mapper les revendications correctement
options.MapInboundClaims = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
// Définir les paramètres de validation de jeton
options.TokenValidationParameters = new TokenValidationParameters {
RoleClaimType = "roles",
NameClaimType = "preferred_username",
ValidateIssuer = false
};
// Synchroniser l'utilisateur lors d'une authentification réussie
options.Events = new OpenIdConnectEvents {
OnTokenValidated = ctx => {
if (ctx.Principal?.Identity is ClaimsIdentity id) {
id.AddClaim(new Claim("auth_provider", "entra"));
}
ServiceLocator.Current.GetInstance<ISynchronizingUserService>()
.SynchronizeAsync(ctx.Principal?.Identity as ClaimsIdentity);
return Task.CompletedTask;
}
};
});Portez attention à l'appel ISynchronizingUserService. Cela garantit que les utilisateurs externes obtiennent les bonnes permissions CMS selon leurs revendications.
Étape 4 : Ajouter l'authentification Google
La configuration de l'authentification Google est plus simple qu'Entra ID :
services.AddAuthentication()
.AddGoogle("google", options => {
options.SignInScheme = "azure-cookie"; // Partager le même témoin
options.ClientId = Configuration["Authentication:Google:ClientId"];
options.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
// Mapper les revendications Google aux types de revendications standards
options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
options.Events = new OAuthEvents {
OnCreatingTicket = ctx => {
if (ctx.Principal?.Identity is ClaimsIdentity id) {
id.AddClaim(new Claim("auth_provider", "google"));
// Synchroniser l'utilisateur avec le CMS
var sync = ctx.HttpContext.RequestServices
.GetRequiredService<ISynchronizingUserService>();
sync.SynchronizeAsync(id);
}
return Task.CompletedTask;
}
};
});Remarquez comment nous utilisons le même azure-cookie pour le schéma de connexion. Cela permet aux utilisateurs de rester connectés peu importe le fournisseur qu'ils ont utilisé.
Étape 5 : Configurer l'authentification Facebook
Facebook suit un modèle similaire mais nécessite une configuration spécifique de portée et de champs :
services.AddAuthentication()
.AddFacebook("facebook", options => {
options.SignInScheme = "azure-cookie";
options.AppId = Configuration["Authentication:Facebook:AppId"];
options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
// Facebook nécessite une configuration explicite de la portée
options.Scope.Clear();
options.Scope.Add("email");
options.Scope.Add("public_profile");
// Spécifier quels champs récupérer
options.Fields.Add("email");
options.Fields.Add("first_name");
options.Fields.Add("last_name");
options.Fields.Add("name");
// Mapper les champs Facebook aux revendications
options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "first_name");
options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "last_name");
options.Events = new OAuthEvents {
OnCreatingTicket = ctx => {
if (ctx.Principal?.Identity is ClaimsIdentity id) {
id.AddClaim(new Claim("auth_provider", "facebook"));
var sync = ctx.HttpContext.RequestServices
.GetRequiredService<ISynchronizingUserService>();
sync.SynchronizeAsync(id);
}
return Task.CompletedTask;
}
};
});Étape 6 : Implémenter le routage d'authentification intelligent
Avec plusieurs fournisseurs configurés, vous avez besoin de schémas de politique pour acheminer correctement les demandes d'authentification :
services.AddAuthentication()
.AddPolicyScheme("smart-auth", "Smart Auth", options => {
options.ForwardDefaultSelector = ctx => {
var cookies = ctx.Request.Cookies;
// Vérifier quel témoin existe pour déterminer la session active
if (cookies.ContainsKey(".AspNetCore.azure-cookie"))
return "azure-cookie";
if (cookies.ContainsKey(".AspNetCore.Identity.Application"))
return IdentityConstants.ApplicationScheme;
// Solution de repli par défaut
return "azure-cookie";
};
})
.AddPolicyScheme("smart-challenge", "Smart Challenge", options => {
options.ForwardDefaultSelector = ctx => {
var path = (ctx.Request.Path.Value ?? string.Empty).ToLowerInvariant();
// Router selon le chemin de la requête
if (path.StartsWith("/login/google")) return "google";
if (path.StartsWith("/login/facebook")) return "facebook";
if (path.StartsWith("/login")) return "azure";
if (path.StartsWith("/util/login")) return IdentityConstants.ApplicationScheme;
return "azure"; // Par défaut vers Entra ID
};
});
// Définir les schémas par défaut
services.PostConfigure<AuthenticationOptions>(o => {
o.DefaultScheme = "smart-auth";
o.DefaultAuthenticateScheme = "smart-auth";
o.DefaultChallengeScheme = "smart-challenge";
o.DefaultSignInScheme = "azure-cookie";
});Cette configuration achemine intelligemment les demandes d'authentification selon le chemin URL et les témoins existants.
Étape 7 : Créer le contrôleur de connexion
Construisez un contrôleur pour gérer les différentes routes de connexion :
[Route("login")]
public class LoginController : Controller
{
private readonly SignInManager<SiteUser> _signInManager;
public LoginController(SignInManager<SiteUser> signInManager)
{
_signInManager = signInManager;
}
[HttpGet("")]
public IActionResult Microsoft([FromQuery] string returnUrl = "/")
{
return Challenge(
new AuthenticationProperties { RedirectUri = returnUrl },
"azure"
);
}
[HttpGet("google")]
public IActionResult Google([FromQuery] string returnUrl = "/")
{
return Challenge(
new AuthenticationProperties { RedirectUri = returnUrl },
"google"
);
}
[HttpGet("facebook")]
public IActionResult Facebook([FromQuery] string returnUrl = "/")
{
return Challenge(
new AuthenticationProperties { RedirectUri = returnUrl },
"facebook"
);
}
[HttpPost("logout")]
public async Task<IActionResult> Logout()
{
// Vérifier quel fournisseur a été utilisé
var authProvider = User.FindFirst("auth_provider")?.Value;
if (string.IsNullOrEmpty(authProvider))
{
// Déconnexion de l'identité locale
await _signInManager.SignOutAsync();
}
else
{
// Déconnexion du fournisseur externe
await HttpContext.SignOutAsync("azure-cookie");
HttpContext.Response.Cookies.Delete(".AspNetCore.azure-cookie");
}
return Redirect("/");
}
}Étape 8 : Mettre à jour les paramètres de configuration
Ajoutez tous les paramètres nécessaires à votre appsettings.json :
{
"ConnectionStrings": {
"EPiServerDB": "Server=.;Database=YourCmsDb;Trusted_Connection=True;TrustServerCertificate=True"
},
"Authentication": {
"AzureClientID": "VOTRE-ID-CLIENT-ENTRA",
"AzureClientSecret": "VOTRE-SECRET-CLIENT-ENTRA",
"AzureAuthority": "https://login.microsoftonline.com/VOTRE-ID-LOCATAIRE/v2.0",
"CallbackPath": "/signin-oidc",
"Google": {
"ClientId": "VOTRE-ID-CLIENT-GOOGLE",
"ClientSecret": "VOTRE-SECRET-CLIENT-GOOGLE"
},
"Facebook": {
"AppId": "VOTRE-ID-APP-FACEBOOK",
"AppSecret": "VOTRE-SECRET-APP-FACEBOOK"
}
}
}N'oubliez pas de stocker les secrets de production dans Azure Key Vault ou dans des variables d'environnement, pas dans votre code source.
Étape 9 : Configurer les URI de redirection des fournisseurs
Chaque fournisseur doit avoir l'URI de redirection correcte configurée dans leur portail respectif :
Entra ID (portail Azure) :
- Naviguez vers Inscriptions d'applications → Votre application → Authentification
- Ajoutez l'URI de redirection : https://votre-domaine.com/signin-oidc
Console Google Cloud :
- Allez dans APIs et services → Identifiants → Votre client OAuth 2.0
- Ajoutez l'URI de redirection autorisée : https://votre-domaine.com/signin-google
Console développeur Facebook :
- Ouvrez votre application → Facebook Login → Paramètres
- Ajoutez l'URI de redirection OAuth valide : https://votre-domaine.com/signin-facebook
Erreurs courantes à éviter
Notre expérience montre que ces problèmes causent des difficultés à la plupart des développeurs lors de l'implémentation de l'authentification multi-fournisseurs :
1. URI de redirection non concordantes
L'URI de redirection dans votre code doit correspondre exactement à ce qui est configuré dans le portail du fournisseur. Même une différence de barre oblique causera l'échec de l'authentification. Vérifiez attentivement :
- HTTP vs HTTPS
- WWW vs sans WWW
- Barres obliques finales
- Sensibilité à la casse (certains fournisseurs en tiennent compte)
2. Oublier la synchronisation des utilisateurs
Sans appeler ISynchronizingUserService.SynchronizeAsync(), les utilisateurs externes n'apparaîtront pas dans le CMS avec les bonnes permissions. Synchronisez toujours les utilisateurs pendant l'événement d'authentification.
3. Conflits de témoins
Utiliser différents schémas de témoins pour chaque fournisseur crée des cauchemars de gestion de session. Partagez un seul schéma de témoin pour tous les fournisseurs externes, mais gardez l'identité locale séparée.
4. Mappage de revendications manquant
Chaque fournisseur retourne les revendications différemment. Si vous ne les mappez pas correctement, vous vous retrouverez avec des utilisateurs sans nom ou adresse courriel dans votre système.
5. Gestion d'erreurs inadéquate
L'authentification peut échouer pour plusieurs raisons : secrets expirés, problèmes de réseau, ou pannes du fournisseur. Implémentez des pages d'erreur et une journalisation appropriées pour aider à diagnostiquer rapidement les problèmes.
Tests et vérification
Après avoir implémenté l'authentification, testez minutieusement chaque fournisseur :
Liste de vérification des tests
1. Test de l'identité locale
- Naviguez vers /util/login
- Connectez-vous avec un compte administrateur CMS
- Vérifiez l'accès à l'interface d'administration CMS
- Vérifiez que le navigateur rapide fonctionne correctement
2. Test Entra ID
- Naviguez vers /login
- Complétez le processus de connexion Microsoft
- Vérifiez que l'utilisateur apparaît dans la gestion des utilisateurs CMS
- Vérifiez que les rôles attribués sont corrects
3. Test Google
- Naviguez vers /login/google
- Complétez l'authentification Google
- Vérifiez que les revendications sont mappées (nom, courriel)
- Testez avec un compte Gmail et Google Workspace
4. Test Facebook
- Naviguez vers /login/facebook
- Authentifiez-vous avec Facebook
- Vérifiez que les revendications de courriel et de nom sont présentes
- Testez avec différents paramètres de confidentialité
5. Test inter-fournisseurs
- Connectez-vous avec un fournisseur
- Déconnectez-vous
- Connectez-vous avec un fournisseur différent
- Vérifiez qu'aucun conflit de session ne se produit
6. Test des permissions
- Créez du contenu de test
- Définissez des permissions spécifiques
- Vérifiez que chaque fournisseur respecte correctement les permissions
Débogage des problèmes d'authentification
Lorsque l'authentification échoue, vérifiez d'abord ces zones :
// Ajoutez une journalisation détaillée à vos événements d'authentification
options.Events = new OpenIdConnectEvents {
OnAuthenticationFailed = context => {
var logger = context.HttpContext.RequestServices
.GetRequiredService<ILogger<Startup>>();
logger.LogError(context.Exception,
"L'authentification a échoué pour {Provider}",
context.Scheme.Name);
context.HandleResponse();
context.Response.Redirect("/error/auth-failed");
return Task.CompletedTask;
}
};Surveillez ces sources de journalisation :
- Journaux du middleware d'authentification ASP.NET Core
- Réponses d'erreur spécifiques au fournisseur
- Onglet réseau du navigateur pour les chaînes de redirection
- Journaux du service de synchronisation CMS
Conclusion
Configurer plusieurs fournisseurs d'authentification dans Optimizely CMS 12 offre de la flexibilité à vos utilisateurs tout en maintenant la sécurité. En suivant ce guide, vous avez configuré Entra ID, Google, Facebook et l'identité locale pour fonctionner ensemble harmonieusement. La clé est de comprendre comment les chaînes de middleware d'authentification ASP.NET Core fonctionnent et d'assurer une synchronisation appropriée des utilisateurs avec le CMS.
Les équipes avec lesquelles nous travaillons rapportent qu'offrir plusieurs options de connexion réduit considérablement les billets de support concernant les réinitialisations de mot de passe et l'accès aux comptes. Les utilisateurs apprécient de pouvoir choisir leur méthode d'authentification préférée, surtout quand elle s'aligne avec les outils qu'ils utilisent déjà quotidiennement.
Si vous prévoyez implémenter l'authentification multi-fournisseurs dans Optimizely CMS 12 et avez besoin d'aide pour des exigences personnalisées comme l'authentification unique sur plusieurs sites ou des scénarios avancés de mappage de rôles, nous pouvons vous guider dans les décisions d'architecture et les détails d'implémentation spécifiques à votre configuration.
