问题
I have two mvc client application mvc_client1
and mvc_client2
. When I logged into mvc_client1
and click the menu to launch mvc_client2
automatically authenticate and open authorized page as per IdentityServer4
documentation.
But, if I trigger logout from any of the client only logout the client which I requested the logout. I have already read documentation and implemented Back-Channel-Logout
. Even though single sign-out not working as documented.
I noticed something that, Identity server provide/send-back different cookie value for each client when authorize. Will it causes an single sign-out? (Please refer attached image) If yes, how to resolve this?
Or, Is this because of recent SameSite
update in all modern browsers?
Client1:
Client2:
EDIT :
IdentityServer Project's Startup:
public void ConfigureServices(IServiceCollection services)
{
//...
//...
services.AddIdentityServer()
.AddInMemoryIdentityResources(IdentityConfiguration.GetIdentityResources())
.AddInMemoryClients(IdentityConfiguration.GetClients())
.AddDeveloperSigningCredential()
.AddProfileService<CustomProfileService>()
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();
}
Client Project's Startup:
public void Configuration(IAppBuilder app)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = new Dictionary<string, string>();
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
CookieSecure = CookieSecureOption.SameAsRequest,
CookieHttpOnly = true,
ExpireTimeSpan = TimeSpan.FromMinutes(180),
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = "https://localhost:44306/",
ClientId = "mvc_client1",
ClientSecret = "secret",
Scope = "openid profile",
ResponseType = "code id_token",
RedirectUri = "https://localhost:44307/",
SignInAsAuthenticationType = "Cookies",
UseTokenLifetime = false,
RequireHttpsMetadata = true,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = n =>
{
var id = n.AuthenticationTicket.Identity;
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
n.AuthenticationTicket = new AuthenticationTicket(
id,
n.AuthenticationTicket.Properties);
return Task.FromResult(0);
},
RedirectToIdentityProvider = n =>
{
if (IsAjaxRequest(n.Request))
{
n.Response.StatusCode = 401;
n.Response.Headers.Remove("Set-Cookie");
n.State = NotificationResultState.HandledResponse;
}
switch (n.ProtocolMessage.RequestType)
{
case Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Authentication:
{
n.OwinContext.Authentication.SignOut("Cookies");
break;
}
case Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Logout:
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
n.ProtocolMessage.ClientId = ConfigurationManager.AppSettings["ClientID"];
}
break;
}
}
return Task.FromResult(0);
}
}
});
}
private bool IsAjaxRequest(IOwinRequest request)
{
IReadableStringCollection query = request.Query;
if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest"))
{
return true;
}
IHeaderDictionary headers = request.Headers;
return (headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest");
}
My Client Configuration:
public static IEnumerable<IdentityResource> GetIdentityResources() =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
public static IEnumerable<Client> GetClients() =>
new List<Client> {
new Client {
ClientName = "MVC Client 1",
ClientId = "mvc_client1",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = new List<string>
{
"https://localhost:44307/"
},
PostLogoutRedirectUris = new List<string>
{
"https://localhost:44307/"
},
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
},
AlwaysIncludeUserClaimsInIdToken = true,
RequireConsent = false,
BackChannelLogoutSessionRequired = true,
BackChannelLogoutUri = "https://localhost:44307/Home/SignoutOidc",
Properties = new Dictionary<string, string>()
{
{"ForgetPasswordUri", "https://localhost:44307/account/forgotpassword" },
{"SubscribeUri", ""https://localhost:44307/account/register" }
}
}
};
来源:https://stackoverflow.com/questions/61400654/why-identityserver4-provide-send-back-different-cookie-for-each-clients