【发布时间】:2020-11-12 09:01:12
【问题描述】:
我有使用 OpenIDConnect 身份验证的 ASP.NET Core 应用程序。在OnTokenValidated 事件中,我检查Authenticated 用户是否存在于我的应用程序的数据库中,如果不存在,那么我将抛出UnauthorizedAccessException
请注意,在OnTokenValidated 事件中,如果用户存在于应用程序的数据库中,我将创建新身份,否则我将保留经过身份验证的用户。
public class Startup
{
private readonly ILogger<Startup> _logger;
public IConfiguration Configuration { get; }
private IHostingEnvironment _environment { get; }
public Startup(IConfiguration configuration, IHostingEnvironment env, ILogger<Startup> logger)
{
Configuration = configuration;
_environment = env;
_logger = logger;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = "/Home";
options.AccessDeniedPath = "/Account/Forbidden";
options.Cookie = new CookieBuilder()
{
Name = "myCookie",
HttpOnly = true,
};
options.SlidingExpiration = true;
})
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
//options.ForwardChallenge
options.Authority = configuration["IdentityOptions:Authority"];
options.ClientId = configuration["IdentityOptions:ClientID"];
options.ResponseType = "id_token";
options.CallbackPath = "/Home";
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; //tells cookies scheme to persist user's identity in cookie.
options.SignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;//tells cookies scheme to remove persisted cookie
options.Scope.Add(OpenIdConnectScope.Email);
options.Events = new OpenIdConnectEvents()
{
OnTokenValidated = async context =>
{
var emailClaim = context.Principal.Claims.SingleOrDefault(x => x.Type == ClaimTypes.Email);
// check if user exists in client applications db
CompanyUser cu = null;
using (var serviceProvider = services.BuildServiceProvider())
{
using (var serviceScope = serviceProvider.CreateScope())
{
using (var accountService = serviceScope.ServiceProvider.GetService<IAccountService>())
{
cu = await accountService.Authorize(emailClaim.Value);
}
}
}
if (cu == null)
{
// context.Principal.Identity.IsAuthenticated is true here
throw new UnauthorizedAccessException(string.Format("Could not find user for login '{0}' ", emailClaim.Value));
}
//We will create new identity to store only required claims.
var newIdentity = new ClaimsIdentity(context.Principal.Identity.AuthenticationType);
// keep the id_token for logout
newIdentity.AddClaim(new Claim(IdentityClaimTypes.IdToken, context.ProtocolMessage.IdToken));
// add email claim
newIdentity.AddClaim(emailClaim);
context.Properties.IsPersistent = true;
context.Properties.ExpiresUtc = DateTime.UtcNow.AddHours(3);
// overwrite existing authentication ticket
context.Principal = new ClaimsPrincipal(newIdentity);
},
OnRedirectToIdentityProviderForSignOut = async context =>
{
var idTokenHint = context.HttpContext?.User?.FindFirst("id_token");
if (idTokenHint != null)
context.ProtocolMessage.IdTokenHint = idTokenHint.Value;
await Task.FromResult(0);
},
OnRemoteFailure = async context =>
{
//WHY context.HttpContext.User.Identity.IsAuthenticated is false here??
if (context.Failure is UnauthorizedAccessException)
{
context.Response.Redirect("/Account/AccessDenied");
}
else
{
context.Response.Redirect("/Account/Error");
}
context.HandleResponse();
await Task.FromResult(0);
}
};
});
}
}
问题
1> 在OnRemoteFailure 中,我如何在重定向到 AccessDenied 视图之前自动注销/清除unauthorized 用户? AccessDenied 视图可供匿名用户访问。
我试过了
OnRemoteFailure = async context =>
{
if (context.Failure is UnauthorizedAccessException)
{
await Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.SignOutAsync(context.HttpContext, CookieAuthenticationDefaults.AuthenticationScheme);
await Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.SignOutAsync(context.HttpContext, OpenIdConnectDefaults.AuthenticationScheme);
context.Response.Redirect("/Account/AccessDenied");
}
else
{
context.Response.Redirect("/Account/Error");
}
context.HandleResponse();
await Task.FromResult(0);
}
但是在OnTokenValidated 事件中context.HttpContext.User.Identity.IsAuthenticated 是假的,所以它不起作用。
【问题讨论】:
标签: asp.net-core-mvc asp.net-core-2.0 identityserver4 openid-connect identityserver3