Keycloak logout: How to obtain id_token with C# when forms authentication is used?

608 Views Asked by At

I need to update an application that uses Keycloak with forms authentication compatible with Keycloak 19. Previously, Keycloak 17 was used. After logout, the browser was redirected to the application login page using the redirect_uri parameter.

As Keycloak 19 no longer supports the redirect_uri parameter, I need to use the id_token_hint and post_logout_redirect_uri parameters to achieve similar behavior as with Keycloak 17. So far, I have added the parameter post_logout_redirect_uri to my logout URL, which looks like this: https://realm/protocol/openid-connect/logout?post_logout_redirect_uri=https://my-application/UserLogin.aspx. However, this brings up an error "Missing parameters: id_token_hint".

I need help obtaining the value for the id_token_hint parameter that should be added to the logout URL. My code is written in C#.

Currently, the code in UserLogin.aspx looks like this:

public partial class CustomLogin : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // Check if sign out required
        if (SignOut)
        {
            ExecuteSignOut(Request, Response);
        }
        else
        {
            ExecuteSignIn(Request, Response);
        }
    }
    
    public static void ExecuteSignOut(HttpRequest request, HttpResponse response)
    {
        var redirectUri = request.Url.AbsoluteUri;
        
        var signOutUri = $"{Realm}/protocol/openid-connect/logout?" +
                        $"post_logout_redirect_uri={HttpUtility.UrlEncode(redirectUri)}";
                        
        response.Redirect(signOutUri, false);
        HttpContext.Current.ApplicationInstance.CompleteRequest();
    }
}

So, finally, the logout URL should look like this: https://realm/protocol/openid-connect/logout?id_token_hint=value_of_id_token&post_logout_redirect_uri=https://my-application/UserLogin.aspx.

1

There are 1 best solutions below

0
Markku Rintala On

To answer my question, I did it like this:

//First, read code from request.
var code = request.QueryString["code"];
// Redirect URI was saved when user opened the sign in of the application. User was redirected to Keycloack.
var redirectUri = request.Cookies["RedirectUriCookieName"].value;

var tokens = JwtHelper.GetOAuth2TokensByCode(code, redirectUri);
var idtoken = tokens["id_token"].Value<string>();

where GetOAuth2TokensByCode is something like

public static JObject GetOAuth2TokensByCode(string code, string redirectUri)
{
    var targetUrl = "https://_Keycloack_URL_/auth" + "/protocol/openid-connect/token";

    try
    {
        using (var client = new WebClient())
        {
            client.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");

            var parameters = new System.Collections.Specialized.NameValueCollection
            {
                { "grant_type", "authorization_code" },
                { "client_id", OAuth2ClientId },
                { "client_secret", OAuth2ClientSecret },
                { "code", code },
                { "redirect_uri", redirectUri }
            };

            var response = client.UploadValues(targetUrl, "POST", parameters);
            var result = Encoding.UTF8.GetString(response);

            return JObject.Parse(result);
        }
    }
    catch (WebException e)
    {
    
    }
}