Har*_*aka 6 c# asp.net-core-mvc asp.net-core identityserver4
我有一个使用 IdentityServer4 Hybrid Auth Flow 的 ASP.Net Core 应用程序项目。设置如下,
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
}).AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = IdentityServerUrl;
options.RequireHttpsMetadata = false;
options.ClientId = ClientId;
options.ClientSecret = ClientSecret;
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("offline_access");
options.Scope.Add("ApiAuthorizedBasedOnIdentity");
options.GetClaimsFromUserInfoEndpoint = true;
options.TokenValidationParameters.NameClaimType = JwtClaimTypes.Name;
options.TokenValidationParameters.RoleClaimType = JwtClaimTypes.Role;
});
//Setup Tenant Role based authorization
services.AddSingleton<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
services.AddProxy();
}
Run Code Online (Sandbox Code Playgroud)
我能够进行身份验证并且 SaveTokens=true 成功地将访问令牌保存在 ASP.Net 身份验证 cookie 中。现在,我需要在我的 ASP.Net Core 客户端项目的控制器操作(不是通过中间件)中向这个相同的身份验证 cookie 添加自定义声明。以 HomeController 的 Index 动作为例。
我还需要将此声明保留在身份验证 cookie 中,以便它可以跨请求和控制器操作保留。
我做了一些挖掘并注意到我可以用 ASP.Net Identity 做到这一点
if (User.Identity.IsAuthenticated)
{
var claimsIdentity = ((ClaimsIdentity)User.Identity);
if (!claimsIdentity.HasClaim(c => c.Type == "your-claim"))
{
((ClaimsIdentity)User.Identity).AddClaim(new Claim("your-claim", "your-value"));
var appUser = await userManager.GetUserAsync(User).ConfigureAwait(false);
await signInManager.RefreshSignInAsync(appUser).ConfigureAwait(false);
}
}
Run Code Online (Sandbox Code Playgroud)
身份验证由 IdentityServer 使用在该项目中设置的 ASP.Net Identity 完成。但是,要在客户端项目中使用 SignInManager、UserManager 等,我需要将 ASP.Net Identity 引入其中。还在客户端项目中设置 ASP.Net 身份和存储,只是用额外的声明更新身份验证 cookie 似乎有点矫枉过正。有没有其他方法可以做到这一点?
Kir*_*kin 11
您当然不需要在您的客户端项目中包含 ASP.NET Core Identity,但您可以使用它来获得灵感,了解如何实现您正在寻找的东西。让我们先看看 的实现RefreshSignInAsync:
public virtual async Task RefreshSignInAsync(TUser user)
{
var auth = await Context.AuthenticateAsync(IdentityConstants.ApplicationScheme);
var authenticationMethod = auth?.Principal?.FindFirstValue(ClaimTypes.AuthenticationMethod);
await SignInAsync(user, auth?.Properties, authenticationMethod);
}
Run Code Online (Sandbox Code Playgroud)
从上面可以看出,这也会调用 into SignInAsync,它看起来像这样:
public virtual async Task SignInAsync(TUser user, AuthenticationProperties authenticationProperties, string authenticationMethod = null)
{
var userPrincipal = await CreateUserPrincipalAsync(user);
// Review: should we guard against CreateUserPrincipal returning null?
if (authenticationMethod != null)
{
userPrincipal.Identities.First().AddClaim(new Claim(ClaimTypes.AuthenticationMethod, authenticationMethod));
}
await Context.SignInAsync(IdentityConstants.ApplicationScheme,
userPrincipal,
authenticationProperties ?? new AuthenticationProperties());
}
Run Code Online (Sandbox Code Playgroud)
我们最感兴趣的两个调用是:
Context.AuthenticateAsync,它创建一个AuthenticateResult同时包含ClaimsPrincipal和AuthenticationProperties从cookie中读取的。Context.SignInAsync,最终用 aClaimsPrincipal和相关联的AuthenticationProperties.ASP.NET Core Identity 创建一个全新的ClaimsPrincipal,通常从数据库中获取,以便“刷新”它。您不需要这样做,因为您只是想使用现有 ClaimsPrincipal的附加声明。这是满足您要求的完整解决方案:
var authenticateResult = await HttpContext.AuthenticateAsync();
if (authenticateResult.Succeeded)
{
var claimsIdentity = (ClaimsIdentity)authenticateResult.Principal.Identity;
if (!claimsIdentity.HasClaim(c => c.Type == "your-claim"))
{
claimsIdentity.AddClaim(new Claim("your-claim", "your-value"));
await HttpContext.SignInAsync(authenticateResult.Principal, authenticateResult.Properties);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,要求HttpContext.AuthenticateAsync将使用你已经在你的配置设置默认方案("Cookies")以访问这两个ClaimsPrincipal和AuthenticationProperties。之后,只需添加新声明并执行对 的调用HttpContext.SignInAsync,这也将使用默认方案 ( "Cookies")。