When a user logs out under certain circumstances I want to show them a message on the logged out page. To enable this I want to be able to send an optional parameter from the client to the Identity Server / Authority site on logout.
While I have the standard logout flow working I have hit a brick wall in handling this scenario as information seems thin on the ground and the suggested solutions are not working.
From what I have read the 'state' parameter is the correct way to pass this information but this not coming through currently. AcrValues are only used to send information the other way.
My naive implementation below simply adds a state query string item to the end session endpoint. However, when I check the query string my client uses to go to the identity server instance it is missing.
Redirect(discoveryResponse.EndSessionEndpoint+"&state=foo")
Any help gladly received!
Current flow for MVC client:
Please note; some code has been removed for brevity.
Logout initiated from client controller with state=foo:
public class LogoutController : Controller
{
public ActionResult Index()
{
Request.GetOwinContext().Authentication.SignOut();
var discoveryClient = new DiscoveryClient(clientConfig.Authority) { Policy = {RequireHttps = false} };
var discoveryResponse = discoveryClient.GetAsync().Result;
var tokenClaim = ((ClaimsIdentity)User.Identity).FindFirst("id_token");
return Redirect(discoveryResponse.EndSessionEndpoint+ "?id_token_hint="+ tokenClaim + "&state=foo");
}
}
RedirectToIdentityProvider is called for request:
IdTokenHint and PostLogoutRedirectUri are set and passed correctly.
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType != OpenIdConnectRequestType.LogoutRequest)
return Task.FromResult(0);
var idTokenHint = n.OwinContext.Authentication.User.FindFirst(OpenIdConnectClaimType.IdToken);
if (idTokenHint == null) return Task.FromResult(0);
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
n.OwinContext.Response.Cookies.Append("IdentityServerPostLogoutReturnUri",
n.ProtocolMessage.PostLogoutRedirectUri);
n.ProtocolMessage.PostLogoutRedirectUri =
n.Options.PostLogoutRedirectUri;
return Task.FromResult(0);
}
}
URL Generated (not the lack of 'state' item):
Logout page on the authority site:
This is where I want to be able to access the state parameter.
public class LogoutController : Controller
{
public async Task<ViewResult> Index(string logoutId)
{
if (logoutId == null) throw new Exception("Missing logoutId");
var logoutRequest = await interactionService.GetLogoutContextAsync(logoutId);
var vm = new LoggedOutViewModel(logoutRequest, logoutId);
if (!string.IsNullOrWhiteSpace(httpContextService.GetCookieValue(PostLogoutReturnUriCookieKey)))
{
vm.PostLogoutRedirectUri = httpContextService.GetCookieValue(PostLogoutReturnUriCookieKey);
httpContextService.ClearCookie(PostLogoutReturnUriCookieKey);
}
await httpContextService.SignOutAsync();
return View("Index", vm);
}
}