Search code examples
javasingle-sign-onkeycloakkerberosspnego

Skip kerberos sso authentication in keycloak


In certain cases we need to skip automatic login through Kerberos. According to the documentation this should be done through the parameter ?prompt=login:

prompt - Keycloak supports these settings:

  • login - SSO will be ignored and the Keycloak login page will be always shown, even if the user is already authenticated

This works in most cases (we also use a NTLM waffle implementation) but with Kerberos the user is always signed in automatically.

Any hint or idea why?
Are there alternative ways to force forwarding to the login page?

EDIT: The reason I need to skip the Kerberos authentication is because I need to login with an admin-account where I have to enter username+password.

EDIT2: We are using Keycloak.x version 14.0.0, also applies to version 15.0.2.


Solution

  • I just created a feature-request with a possible solution on the code side.
    skip kerberos SSO authentication to use login-form

    Might be able to override the default SpnegoAuthenticator with a custom one containing the login parameter handling.
    I patched and tested it in a kerberos environment and it worked.

    @Override
    public void authenticate(AuthenticationFlowContext context) {
    // +++ BEGIN CHANGE +++
        AuthenticationSessionModel session = context.getAuthenticationSession();
        Map<String, String> clientNotes = session.getClientNotes();
    
        if ("login".equals(clientNotes.get("prompt"))) {
            logger.info("skip SPNEGO authenticator because of client requests login prompt: " + clientNotes); //$NON-NLS-1$
            context.attempted();
            return;
        }
    // +++ END CHANGE +++
    
        HttpRequest request = context.getHttpRequest();
        String authHeader = request.getHttpHeaders().getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        if (authHeader == null) {
            Response challenge = challengeNegotiation(context, null);
            context.forceChallenge(challenge);
            return;
        }