Skip to content

Framework Adapters

Every framework integration follows the same two-role model:

  • Frontend / OIDC client: any library that implements the Authorization Code + PKCE flow (keycloak-js for browsers, AppAuth for mobile, MSAL for Microsoft stacks, etc.).
  • Backend / resource server: any library that validates Bearer JWTs against the realm’s JWKS endpoint.

The key insight is that the backend does not need a Keycloak-specific library. It only needs a library that can validate a JWT against a JWKS URL — which is a standard feature of every mature OAuth2/OIDC ecosystem.

Spring Boot (Spring Security OAuth2 Resource Server)

Section titled “Spring Boot (Spring Security OAuth2 Resource Server)”

Add the Spring Security OAuth2 Resource Server dependency to your pom.xml:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

Then point Spring at your realm’s issuer URI. Spring automatically fetches the JWKS, verifies incoming JWTs, and populates SecurityContextHolder with the decoded claims:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://localhost:8080/realms/my-app

Spring Security derives the JWKS URL automatically from the issuer URI by appending /protocol/openid-connect/certs (via the OIDC discovery document). No Keycloak-specific code is needed.

A minimal security configuration to protect all endpoints:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
return http.build();
}
}

express-oauth2-jwt-bearer is Auth0’s MIT-licensed middleware that wraps jose for Express. Install it:

Terminal window
npm install express-oauth2-jwt-bearer
import { auth } from 'express-oauth2-jwt-bearer';
import express from 'express';
const checkJwt = auth({
audience: 'my-app-backend',
issuerBaseURL: 'http://localhost:8080/realms/my-app',
});
const app = express();
app.get('/profile', checkJwt, (req, res) => {
res.json({ sub: req.auth?.payload.sub });
});

Keycloak used to ship per-framework adapters: keycloak-connect for Node, a Keycloak Spring Boot adapter, and others. Most of them were removed in Keycloak 25 (the Jetty adapter went a release earlier, in 24), so on a current server they are simply not an option. Use your framework’s standard OIDC/OAuth2 support instead:

FrameworkRecommended library
Browser SPAkeycloak-js (official, still maintained)
Spring Boot backendSpring Security OAuth2 Resource Server
Node/Express backendjose or express-oauth2-jwt-bearer
Any other backendAny JWT library that supports JWKS
OptionBenefitCost
Use an official Keycloak adapter (e.g. older keycloak-js, keycloak-connect)Fast setup, with an API tailored specifically to Keycloak’s own use casesTightly coupled to Keycloak — the backend adapters such as keycloak-connect are deprecated, and switching identity provider later is hard
Implement standard OIDC resource-server middleware yourself (jose, express-oauth2-jwt-bearer, Spring Security’s oauth2ResourceServer)Portable across any identity provider that supports OIDC/JWKS, and maintained by a broader communityYou need to understand the OIDC spec yourself (issuer, audience, JWKS) instead of relying on a vendor-specific abstraction
  • Trusting client-side auth state instead of verifying at the backend — checking that the frontend has a token, or that the UI shows “logged in,” is not authentication the backend can rely on. Every protected endpoint must go through middleware that actually verifies the JWT, not just trust a header the frontend claims proves the user is logged in.
  • Still using a deprecated Keycloak adapter — keycloak-connect and the older Keycloak Spring Boot adapter no longer receive new features. New projects should move to their framework’s standard OAuth2/OIDC resource server support instead.
  • Mixing authentication and authorization responsibility into one middleware — checking that a token is valid (authentication) and checking whether the user may access a resource (authorization) should be separate layers. Combining them into one place makes testing and debugging much harder when roles/policy change.

Real-world example

Spring Security’s oauth2ResourceServer — a production-grade example of using standard middleware instead of a Keycloak-specific adapter; setting just the issuer-uri makes it work with any OIDC-compliant identity provider, not only Keycloak.

express-oauth2-jwt-bearer (from Auth0) — built by Auth0, but it can verify Keycloak-issued JWTs just as well, because it follows the OIDC/JWKS standard — a good reminder that solid resource-server middleware shouldn’t be tied to any one vendor.

What does the Spring Security issuer-uri property tell Spring Boot?
How does Spring Security discover the JWKS URL from the issuer-uri?
Why are the old per-framework Keycloak adapters (keycloak-connect, etc.) not recommended?
Which keycloak-js feature is still the recommended choice for browser SPAs?