Asp.net core mvc 使用OpenIDConnect时如何注销ClaimsEntity用户
我有一个使用OpenIDConnect身份验证的ASP.NET核心应用程序。在Asp.net core mvc 使用OpenIDConnect时如何注销ClaimsEntity用户,asp.net-core-mvc,asp.net-core-2.0,identityserver4,openid-connect,identityserver3,Asp.net Core Mvc,Asp.net Core 2.0,Identityserver4,Openid Connect,Identityserver3,我有一个使用OpenIDConnect身份验证的ASP.NET核心应用程序。在OnTokenValidated事件中,我检查Authenticated用户是否存在于我的应用程序的数据库中,如果不存在,我将抛出UnauthorizedAccessException 请注意,在OnTokenValidated事件中,如果应用程序的数据库中存在用户,我将创建新身份,否则我将保留已验证用户的身份 public class Startup { private readonly ILogger<
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);
}
};
});
}
但是,在
OnTokenValidated
事件context.HttpContext.User.Identity.IsAuthenticated
中,它为false,因此不起作用。一个常见错误是执行响应。在注销方法调用后重定向,这听起来很明显。但不幸的是,这不起作用。注销方法创建它们自己的重定向响应,当您执行重定向时,您将“覆盖”这些重定向
实现这一点的正确方法是不返回任何内容,并让Signout方法处理重定向:
public async Task DoLogout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
}
要重定向到其他Url,您可以尝试:
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties( )
{
RedirectUri = "alternativeUrl"
});
我尝试了这个,但这会将用户重定向到identity server的注销页面。我希望用户转到拒绝访问页面。我尝试了
public async Task AccessDenied(){wait-HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);wait-HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);return View(“AccessDenied”);}
未工作,因此未被重定向。可能是我问错了问题。我开始了一条新的思路,澄清你的问题总是很好的。但是,为什么不在两个签出方法上设置AuthenticationProperties{redirectUri}?或者尝试更改它们的顺序?如果您无法使其正常工作,您可以作为黑客随时清除本地会话cookie以在本地注销用户。您对我的答案满意还是缺少什么?如果没有,请将我的答案标记为已接受。
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties( )
{
RedirectUri = "alternativeUrl"
});