How to Install Keycloak and Seamlessly Integrate It with Spring Boot and Spring Cloud

This guide walks through downloading, installing, and initializing Keycloak, creating realms, clients, users and roles, then shows step‑by‑step integration with Spring Boot microservices, token propagation via Feign and Zuul, logout handling, email setup, third‑party login, and essential Keycloak terminology.

Programmer DD
Programmer DD
Programmer DD
How to Install Keycloak and Seamlessly Integrate It with Spring Boot and Spring Cloud

Installation & Initialization

Download the Keycloak Standalone server distribution from http://www.keycloak.org/downloads.html , unzip it, navigate to KEYCLOAK_PATH/bin and run ./standalone.sh (or ./standalone.sh & for background). After startup, open http://localhost:8080/ to create the initial admin account (e.g., admin/admin).

Administration Console

Log in with the admin credentials to access the console, which provides many menus for managing realms, clients, users, roles, and other settings.

Integration with Spring Boot

Keycloak provides adapters for various frameworks; we use the OpenID Connect Spring Boot adapter. Create a realm, a client (public access type), configure redirect URLs, and define roles ( user-role, test-role). Assign roles to users.

Spring Boot Microservice Example

Assume a microservice ms-content-sample running at http://localhost:8081 with an endpoint /articles protected by the role user-role. Add Keycloak dependencies via BOM and starter, then configure application.yml with the realm, client, and security constraints.

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.keycloak.bom</groupId>
      <artifactId>keycloak-adapter-bom</artifactId>
      <version>3.4.0.Final</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
<dependency>
  <groupId>org.keycloak</groupId>
  <artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
keycloak:
  public-client: true
  auth-server-url: http://localhost:8080/auth
  realm: realm
  resource: ms-content-sample
  securityConstraints:
    - authRoles:
        - user-role
      securityCollections:
        - name: user-role-mappings
          patterns:
            - /articles

Run the service; accessing /articles as user1 (with user-role) succeeds, while user2 (with test-role) is denied.

Accessing Identity in Controllers

@GetMapping("/articles")
public HashMap<Object, Object> search(Principal principal) {
    if (principal instanceof KeycloakPrincipal) {
        AccessToken token = ((KeycloakPrincipal) principal).getKeycloakSecurityContext().getToken();
        String username = token.getPreferredUsername();
        Set<String> roles = token.getRealmAccess().getRoles();
        log.info("Current user: {}, roles: {}", username, roles);
    }
    return null;
}

Logout

@RestController
public class LogoutController {
    @GetMapping("/logout")
    public String logout(HttpServletRequest request) throws ServletException {
        request.logout();
        return "Logout successful";
    }
}

Integration with Spring Cloud

For distributed applications, propagate the Keycloak token between services using Feign interceptors or Zuul filters.

Feign Token Propagation

public class KeycloakRequestInterceptor implements RequestInterceptor {
    private static final String AUTHORIZATION_HEADER = "Authorization";
    @Override
    public void apply(RequestTemplate template) {
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Principal principal = attrs.getRequest().getUserPrincipal();
        if (principal instanceof KeycloakPrincipal) {
            KeycloakSecurityContext ctx = ((KeycloakPrincipal) principal).getKeycloakSecurityContext();
            if (ctx instanceof RefreshableKeycloakSecurityContext) {
                ((RefreshableKeycloakSecurityContext) ctx).refreshExpiredToken(true);
                template.header(AUTHORIZATION_HEADER, "Bearer " + ctx.getTokenString());
            }
        }
    }
}

Zuul Token Propagation

@Component
public class KeycloakRouteZuulFilter extends ZuulFilter {
    private static final String AUTHORIZATION_HEADER = "Authorization";
    @Override
    public String filterType() { return FilterConstants.ROUTE_TYPE; }
    @Override
    public int filterOrder() { return 1; }
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        Principal p = ctx.getRequest().getUserPrincipal();
        return p != null && p instanceof KeycloakPrincipal;
    }
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        if (ctx.getRequest().getHeader(AUTHORIZATION_HEADER) == null) {
            addKeycloakTokenToHeader(ctx);
        }
        return null;
    }
    private void addKeycloakTokenToHeader(RequestContext ctx) {
        Principal p = ctx.getRequest().getUserPrincipal();
        KeycloakSecurityContext sec = ((KeycloakPrincipal) p).getKeycloakSecurityContext();
        if (sec instanceof RefreshableKeycloakSecurityContext) {
            ctx.addZuulRequestHeader(AUTHORIZATION_HEADER,
                "Bearer " + ((RefreshableKeycloakSecurityContext) sec).getTokenString());
        }
    }
}

Configure non‑Zuul clients as bearer-only so they rely on token forwarding from the gateway.

Login Configuration and Third‑Party Identity Providers

Enable user registration, “Remember Me”, and add external identity providers such as GitHub by creating a GitHub OAuth application, obtaining the client ID and secret, and filling them in the Keycloak admin console.

Keycloak Terminology

Definitions of Resource Server, Resource, Scope, Permission, Policy, Policy Provider, and Permission Ticket are provided to understand the underlying authorization model.

Spring BootSpring CloudOAuth2AuthorizationKeycloak
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.