У меня есть два mvc клиентских приложения mvc_client1
и mvc_client2
. Когда я вошел в систему mvc_client1
и щелкнул меню, чтобы запустить mvc_client2
, автоматически аутентифицируйте и откройте авторизованную страницу согласно IdentityServer4
документации.
Но, если я инициирую выход из системы с любого из клиентов, только выйдите из системы клиент который я запросил выход. Я уже прочитал документацию и внедрил Back-Channel-Logout
. Несмотря на то, что единый выход не работает, как задокументировано.
Я заметил кое-что, что Identity-сервер предоставляет / отсылает разные значения cook ie для каждого клиента при авторизации. Будет ли это причиной единого выхода? (см. Прикрепленное изображение) Если да, как решить эту проблему?
Или, это из-за недавнего обновления SameSite
во всех современных браузерах?
Клиент1:
Клиент2:
РЕДАКТИРОВАТЬ:
Запуск проекта IdentityServer:
public void ConfigureServices(IServiceCollection services)
{
//...
//...
services.AddIdentityServer()
.AddInMemoryIdentityResources(IdentityConfiguration.GetIdentityResources())
.AddInMemoryClients(IdentityConfiguration.GetClients())
.AddDeveloperSigningCredential()
.AddProfileService<CustomProfileService>()
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();
}
Запуск клиентского проекта:
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");
}
Конфигурация моего клиента:
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" }
}
}
};