layout: docs-default
Federated 的登出后重定向
當(dāng)客戶(hù)端程序登出IdentityServer的時(shí)候,一個(gè)"post-logout redirect uri"會(huì)被發(fā)送給用戶(hù),以便在完全退出后重定向回客戶(hù)端。這個(gè)信息維護(hù)在"sign out message"cookie里,通過(guò)唯一的"sign out message id"來(lái)標(biāo)識(shí)。這個(gè)標(biāo)識(shí)通過(guò)查詢(xún)字符串來(lái)傳給”logged out"頁(yè)面,這樣可以訪(fǎng)問(wèn)這個(gè)cookie來(lái)重定向用戶(hù)回客戶(hù)端應(yīng)用。
如果IdentityServer使用一個(gè)上游的身份認(rèn)證,當(dāng)用戶(hù)從IdentityServer 登出的時(shí)候,也會(huì)重定向到第三方認(rèn)證來(lái)退出。如果第三方認(rèn)證提供 "post logout redirect uri" 功能, 那么一旦用戶(hù)被重定向回IdentityServer,這個(gè)"sign in message id" 會(huì)丟掉.
IdentityServer支持在重定向到第三方認(rèn)證前獲取和保存 "sign out message id"。一旦用戶(hù)被重定向回IdentityServer,可以使用這個(gè)"sign out message id" 來(lái)顯示IdentityServer的登出界面,這個(gè)界面有一個(gè)鏈接可以退回到用戶(hù)程序。
這種方式需要托管程序在重定向前拿到"sign out message id"。通過(guò)調(diào)用 IdentityServer OWIN environment extensions的 GetSignOutMessageId
方法。我們的邏輯代碼需要保存這個(gè)標(biāo)識(shí)(比如到cookie)
這個(gè)同樣需要在托管程序中定義個(gè) "post logout redirect" endpoint (這個(gè)endpoint需要在尚有的認(rèn)證服務(wù)注冊(cè)). 當(dāng)?shù)谌秸J(rèn)證登出時(shí),這個(gè)endpoint像一個(gè)回調(diào)函數(shù)一樣。當(dāng)這個(gè)回調(diào)被調(diào)用的時(shí)候,可以顯示一個(gè)IdentityServer的“l(fā)ogged out page"(通過(guò)調(diào)用IdentityServer OWIN environment extensions的RenderLoggedOutViewAsync
).這個(gè)"sign in message id" 會(huì)做為參數(shù)傳過(guò)來(lái)。
詳情可以參考下面的代碼:
public void Configuration(this IAppBuilder app)
{
app.Map("/core", coreApp =>
{
var factory = new IdentityServerServiceFactory();
// ...
coreApp.UseIdentityServer(idsrvOptions);
coreApp.Map("/signoutcallback", cleanup =>
{
cleanup.Run(async ctx =>
{
var state = ctx.Request.Cookies["state"];
await ctx.Environment.RenderLoggedOutViewAsync(state);
});
});
});
}
public static void ConfigureIdentityProviders(IAppBuilder app, string signInAsType)
{
var oidc = new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "oidc",
Caption = "External IdP",
SignInAsAuthenticationType = signInAsType,
// ...
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.LogoutRequest)
{
// ...
var signOutMessageId = n.OwinContext.Environment.GetSignOutMessageId();
if (signOutMessageId != null)
{
n.OwinContext.Response.Cookies.Append("state", signOutMessageId);
}
}
return Task.FromResult(0);
}
}
};
app.UseOpenIdConnectAuthentication(oidc);
}