Keycloak social login rest API redirected you too many times

I try to secure my spring boot app server, I use keycloak for it. I want to create social login use google auth. This is my keycloak config:

package com.example.keycloaklearning.config;

import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

@KeycloakConfiguration
class KeyCloakConfig extends KeycloakWebSecurityConfigurerAdapter {

    // Disable default role prefix ROLE_
    @Autowired
    public void configureGlobal(
            AuthenticationManagerBuilder auth) throws Exception {

        KeycloakAuthenticationProvider keycloakAuthenticationProvider
                = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
                new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    // Use Spring Boot property files instead of default keycloak.json
    @Bean
    public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

    // Register authentication strategy for public or confidential applications
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(
                new SessionRegistryImpl());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                .antMatchers("/test/unprotected-data").permitAll()
                .antMatchers("/test/generator").permitAll()
                .anyRequest().authenticated();
    }
}

And my controller:

package com.example.keycloaklearning.controllers;

import lombok.extern.java.Log;
import org.keycloak.common.util.Base64Url;
import org.keycloak.common.util.KeycloakUriBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

@RequestMapping(value = "/test")
@RestController
@Log
public class TestUserController {


    private String authServerUrl = "http://localhost:8080/auth";
    private String realm = "keycloak-lerning-realm";
    private String clientId = "keycloak-lerning-server";


    @GetMapping(path = "/generator")
    public String brokerGenerator(HttpServletRequest httpServletRequest) throws ServletException {
        String provider = "google";
        String nonce = UUID.randomUUID().toString();
        MessageDigest md = null;

        try {
            md = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }

        String input = nonce + clientId + provider;
        byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
        String hash = Base64Url.encode(check);
        httpServletRequest.getSession().setAttribute("hash", hash);

        String redirectUri = "http://localhost:8081/test/redirect";

        return KeycloakUriBuilder.fromUri(authServerUrl)
                .path("/realms/keycloak-lerning-realm/protocol/openid-connect/auth") // Url changed
                .queryParam("response_type", "code") // Autherization Code Flow
                .queryParam("scope", "openid") // Add additional scopes if needed
                .queryParam("kc_idp_hint", "google") // This should match IDP name registered in Keycloak
                .queryParam("nonce", nonce)
                .queryParam("hash", hash)
                .queryParam("client_id", clientId)
                .queryParam("redirect_uri", redirectUri).build(realm, provider).toString();
    }

    @GetMapping(value = "/unprotected-data")
    public String getName() {
        return "Hello, this api is not protected.";
    }

    @GetMapping(value = "/protected-data")
    public String getEmail() {
        return "Hello, this api is protected.";
    }

    @GetMapping(value = "/redirect")
    public String getRedirectMessage() {
        return "Redirect message.";
    }
}
  1. I go to test/unprotected-data This unserure and this work fine.
  2. Then I go test/unprotected-data This page is secured and I get keycloak login page, I don’t want to use it and I go to http://localhost:8081/test/generator
  3. When I go to /test/generator I get url, something like this: auth/realms/keycloak-lerning-realm/protocol/openid-connect/auth?response_type=code&scope=openid&kc_idp_hint=google&nonce=1d339be6-72b8-487f-8d18-a3b84a1663de&hash=4VZz9Xtk-VqRprnjW8sJCf95EH2dGYIsgkSGYxNtlxU&client_id=keycloak-lerning-server&redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Ftest%2Fredirect
  4. When I go by this address I input my google data(email and password), and I get error: This page isn’t workinglocalhost redirected you too many times. Try clearing your cookies. ERR_TOO_MANY_REDIRECTS

In my Network tab I see many requests like this: General:

Request URL: 8081/sso/login?session_state=fc107364-ae64-4ab6-923d-d3e8abec6b0b&code=b0fb2c6f-93a0-45ee-bead-500202ef46b8.fc107364-ae64-4ab6-923d-d3e8abec6b0b.4b1cdc54-90bb-4c12-97d7-e04a72d98a49 Request Method: GET Status Code: 302 Remote Address: [::1]:8081 Referrer Policy: strict-origin-when-cross-origin

Response Headers:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate Connection: keep-alive Content-Length: 0 Date: Sun, 24 Oct 2021 10:43:56 GMT Expires: 0 Keep-Alive: timeout=60 Location: http://localhost:8081/sso/login?session_state=fc107364-ae64-4ab6-923d-d3e8abec6b0b&code=b0fb2c6f-93a0-45ee-bead-500202ef46b8.fc107364-ae64-4ab6-923d-d3e8abec6b0b.4b1cdc54-90bb-4c12-97d7-e04a72d98a49 Pragma: no-cache Set-Cookie: OAuth_Token_Request_State=; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block

Request headers:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng, / ;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate, br Accept-Language: ru Connection: keep-alive Cookie: JSESSIONID=C6A7D049775893649E853257B1B8645F; OAuth_Token_Request_State=704778b2-b484-4102-beda-f95e18ddc759 Host: localhost:8081 sec-ch-ua: “Chromium”;v=“94”, “Google Chrome”;v=“94”, “;Not A Brand”;v=“99” sec-ch-ua-mobile: ?0 sec-ch-ua-platform: “Linux” Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: cross-site Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36

Queiry string parametrs:

session_state: fc107364-ae64-4ab6-923d-d3e8abec6b0b code: b0fb2c6f-93a0-45ee-bead-500202ef46b8.fc107364-ae64-4ab6-923d-d3e8abec6b0b.4b1cdc54-90bb-4c12-97d7-e04a72d98a49

I try to clean my cookies and open new incognite tab, this isn’t work.