J'utilise un serveur d'authentification OpenId Connect, en particulier Identity Server 4 (version 1.5.2) sur .NET Core 1.1. Je l’utilise avec ASP.NET Framework MVC 5 et les applications Web ASP.NET Core 1.1 MVC. La configuration suivante provient d'une application Web .NET Core 1.1:
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
app.UseDeveloperExceptionPage();
app.UseStatusCodePages();
app.UseRewriter(new RewriteOptions().AddRedirectToHttps());
app.UseStaticFiles();
#region Configure Authentication
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies",
AutomaticAuthenticate = true,
AccessDeniedPath = "/AccessDenied"
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "https://localhost:44316",
ClientId = "test-mule",
ClientSecret = "secret",
ResponseType = "code id_token",
SaveTokens = true,
GetClaimsFromUserInfoEndpoint = true,
PostLogoutRedirectUri = "https://localhost:44324",
RequireHttpsMetadata = true,
Scope = { "openid", "profile", "name", "email", "org", "role" },
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
}
});
#endregion Configure Authentication
app.UseMvc();
}
Une fois connecté, je peux répertorier les revendications associées à l'utilisateur authentifié:
var claims = User.Claims.OrderBy(c => c.Type).ToList();
Sur l'application ASP.NET 1.1, cela fournit la liste des revendications suivante:
amr pwd
aud test-mule
auth_time 1504529067
c_hash nouhsuXtd5iKT7B33zxkxg
email tom@
exp 1504532668
family_name Cobley
given_name Tom
iat 1504529068
idp local
iss https://localhost:44316
name tom
nbf 1504529068
nonce 6364012...
org IBX
role SysAdmin
role TeleMarketing
role AccountManager
role DataManager
role Member
sid 2091...
sub 1b19...440fa
Ce qui est ce que je veux/attend.
J'essaie maintenant de répliquer ce problème dans ma première application ASP.NET Core 2.0 avec la configuration Startup
suivante:
public Startup()
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("Cookies")
.AddCookie("Cookies", options =>
{
options.LoginPath = "/SignIn";
options.AccessDeniedPath = "/AccessDenied";
})
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "https://localhost:44316";
options.ClientId = "test-mule";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.SignedOutRedirectUri = "https://localhost:44367";
options.RequireHttpsMetadata = true;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("name");
options.Scope.Add("email");
options.Scope.Add("org");
options.Scope.Add("role");
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
// Add framework services.
services.AddMvc();
}
Pour référence l'action du contrôleur /Signin
ressemble à ceci:
[Route("/SignIn")]
public IActionResult SignIn(string returnUrl = null)
{
if (!Url.IsLocalUrl(returnUrl)) returnUrl = "/";
var props = new AuthenticationProperties
{
RedirectUri = returnUrl
};
return Challenge(props, "oidc");
}
Dans cet environnement, après une connexion réussie, si je liste les revendications de l'utilisateur, je ne vois qu'un sous-ensemble de ce qui est disponible dans Core 1.1:
email tom@...
family_name Cobley
given_name Tom
idp local
name tom.cobley
sid 2091...
sub 1b19...440fa
J'ai exécuté des journaux de trace à la fois sur le client et sur le serveur, mais je ne peux rien voir/identifier. Je suppose également que ce n'est pas un problème d'Identity Server puisqu'il s'agit de 'juste' un service Open Id Connect qui devrait être cohérent avec tout client?
Quelqu'un peut-il m'indiquer dans la bonne direction où je me trompe?
Merci.
Suite à la suggestion de MVCutter, j'ai ajouté un gestionnaire d'événements `OnUserInformationReceived car j'avais remarqué que toutes mes revendications personnalisées n'étaient pas correctement mappées à l'identité de l'utilisateur. Je ne sais pas pourquoi c'est nécessaire ou s'il y a un meilleur endroit pour le faire, mais cela semble me donner ce que je veux pour le moment.
private Task OnUserInformationReceivedHandler(
UserInformationReceivedContext context)
{
if (!(context.Principal.Identity is ClaimsIdentity claimsId))
{
throw new Exception();
}
// Get a list of all claims attached to the UserInformationRecieved context
var ctxClaims = context.User.Children().ToList();
foreach (var ctxClaim in ctxClaims)
{
var claimType = ctxClaim.Path;
var token = ctxClaim.FirstOrDefault();
if (token == null)
{
continue;
}
var claims = new List<Claim>();
if (token.Children().Any())
{
claims.AddRange(
token.Children()
.Select(c => new Claim(claimType, c.Value<string>())));
}
else
{
claims.Add(new Claim(claimType, token.Value<string>()));
}
foreach (var claim in claims)
{
if (!claimsId.Claims.Any(
c => c.Type == claim.Type &&
c.Value == claim.Value))
{
claimsId.AddClaim(claim);
}
}
}
return Task.CompletedTask;
}
S'il vous plaît voir ci-dessous, j'ai rencontré le même problème que vous. Je suis sûr qu'il nous manque un problème de configuration mais, pour le moment, j'ai analysé les valeurs renvoyées par UserInfoEndpoint dans le gestionnaire d'événements OnUserInformationReceived.
public override void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(o =>
{
o.ClientId = "sss";
o.ClientSecret = "sss";
o.RequireHttpsMetadata = false;
o.Authority = "http://localhost:60000/";
o.MetadataAddress = "http://localhost:60000/IdSrv/.well-known/openid-configuration";
o.ResponseType = OpenIdConnectResponseType.IdTokenToken;
o.CallbackPath = new PathString("/CGI/Home/Index");
o.SignedOutCallbackPath = new PathString("/CGI/Account/LoggedOut");
o.Scope.Add("openid");
o.Scope.Add("roles");
o.SaveTokens = true;
o.GetClaimsFromUserInfoEndpoint = true;
o.Events = new OpenIdConnectEvents()
{
OnUserInformationReceived = (context) =>
{
ClaimsIdentity claimsId = context.Principal.Identity as ClaimsIdentity;
var roles = context.User.Children().FirstOrDefault(j => j.Path == JwtClaimTypes.Role).Values().ToList();
claimsId.AddClaims(roles.Select(r => new Claim(JwtClaimTypes.Role, r.Value<String>())));
return Task.FromResult(0);
}
};
o.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role,
};
});
}
Modifier:
J'ai trouvé qu'il existe une méthode d'extension pour la propriété ClaimsAction appelée MapUniqueJsonKey, elle semble fonctionner pour les clés à valeur unique personnalisées, mais les bombes sur les types de tableaux comme les rôles ... se rapprocher
o.ClaimActions.MapUniqueJsonKey("UserType", "UserType");
ASP.NET Core 2 a introduit une propriété ClaimActions dans OpenIdConnectionOptions. La collection par défaut de ClaimActions supprimera les revendications que vous recherchez. Vous pouvez récupérer les revendications en désactivant ClaimActions sur votre objet options:
options.ClaimActions.Clear();
Voir aussi: https://leastprivilege.com/2017/11/15/missing-claims-in-the-asp-net-core-2-openid-connect-handler/