我有2个ASP。. NET MVC应用程序,我使用OpenID中间件UseOpenIdConnectAuthentication做单点登录到两者。配置说明如下。SSO非常有效。我从应用程序1登录,然后检查我是否也登录到连接到idserver的应用程序2,我可以看到自己登录了。两个客户端应用程序现在都有相同的id_token和token。
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "oidc",
SignInAsAuthenticationType = "Cookie",
Authority = "<my-idserver-url>",
ClientId = "client1",
RedirectUri = "https://localhost:44360",
PostLogoutRedirectUri = "https://localhost:44360",
ResponseType = "id_token token",
//scopes from config file
Scope = ConfigurationManager.AppSettings.Get("Scope"),
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = n =>
{
var claims = n.AuthenticationTicket.Identity.Claims;
var accepted_claims = new[]{"name", "tenant", "email", "sub"};
var new_claims = claims.Where(x => accepted_claims.Contains(x.Type)).ToList();
new_claims.Add(new Claim("id_token", n.ProtocolMessage.IdToken));
new_claims.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));
var ci = new ClaimsIdentity(new_claims, n.AuthenticationTicket.Identity.AuthenticationType, "email", "role");
n.AuthenticationTicket = new AuthenticationTicket(ci, n.AuthenticationTicket.Properties);
return Task.FromResult(0);
}
在应用程序中单击注销时,当在客户端调用RedirectToIdentityProvider方法时,我将id_token设置为idtokenint,如下所示:
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.LogoutRequest)
{
var user = n.OwinContext.Authentication.User;
if (user != null && user.Identity.IsAuthenticated)
{
var id_token_claim = user.Claims.FirstOrDefault(x => x.Type == "id_token");
if (id_token_claim != null)
{
n.ProtocolMessage.IdTokenHint = id_token_claim.Value;
}
}
}
return Task.FromResult(0);
}
问题区>单次注销:
成功场景:当我从应用程序1注销时,它将重定向到idserver并注销我,然后重定向回应用程序1。在调试时,我可以看到DefaultViewService的注销方法中的注销消息在这种情况下不是空的。
失败场景:问题是,当我尝试从应用程序2而不是应用程序1注销时(请记住,我是从应用程序1登录的),它确实将我带到idserver上的注销页面,并且我可以注销。但是它不会重定向回应用程序2,而是停留在idserver注销页面上。在调试中,我可以看到DefaultViewService的logout方法中的签出消息在这种情况下是空的。
可能是因为id_token最初是发给应用程序的吗?
我错过了什么?我是否需要处理这种场景,并以某种方式获取用户使用的身份服务器中的客户机,以便实际注销(应用程序2)?然后可能发出一个新的SignoutMessage并为该客户端放入注销后重定向Url ?
或者我完全搞错了,这应该自动工作?
更新:一个错误是在不同端口的IISExpress localhost上尝试这个,两个客户端(localhost,不同端口)以某种方式获得相同的id_token和访问令牌,这不应该发生。
迁移到托管不同站点的IIS解决了这个问题,现在应用程序可以获得自己的独立id_token和访问令牌。
我仍在研究单注销,探索iFrame方法。
我已经为此挣扎了好几天了。谷歌给我指出了你的问题:)
这是我所做的,为我工作(不确定这是否是正确的方法):
为每个客户端配置在PostLogoutRedirectUris中添加了两个客户端uri:
PostLogoutRedirectUris = new List<string>()
{
"http://localhost:28560/",
"http://localhost:57311/"
}