Spring Boot and OAuth2: a field guide for every surface
Secure a Spring Boot app with OAuth2 across every surface: HTTP APIs, the gateway, and the message broker, all on one Keycloak and the same scopes.
Securing a Spring Boot app with OAuth2 means putting one identity architecture across every surface the app exposes, instead of bolting a separate login onto each one. Keycloak issues the tokens. Spring Security validates them. The HTTP endpoints, the gateway in front of them, and even the message broker all trust the same JWTs and authorize by the same scopes.
The series works through the app one surface at a time, and each article ships a companion demo you can run with one command. Start anywhere: they share an architecture, not a plot. More surfaces join as I write them.
In this guide
- Token exchange with Spring Cloud GatewayA hands-on walkthrough of RFC 8693 token exchange using Spring Cloud Gateway, Keycloak, and three frontend frameworks. Architecture, implementation, observability, and the things the docs don't tell you.24 min read
- OAuth2-secured RabbitMQ over AMQP 0.9.1Secure your Spring Boot app's messaging with OAuth2, not guest/guest. RabbitMQ joins your HTTP APIs' Spring Security setup as a resource server.19 min read
- OAuth2-secured RabbitMQ over AMQP 1.0Secure Spring Boot 4 messaging over RabbitMQ AMQP 1.0 with OAuth2 and the native spring-rabbitmq-client: same Keycloak scopes, simpler in-place token refresh.12 min read
- MCP server OAuth2 in Spring: the DCR proxy patternA Spring Authorization Server that adds Dynamic Client Registration in front of an IdP that can't, keeping a Spring AI MCP server connectable to AI clients23 min read
Client ID Metadata Documents in Spring: CIMD instead of DCRClient ID Metadata Documents replace Dynamic Client Registration for MCP clients. How CIMD works in Spring, and what happened when Claude Code connected.24 min read
Key ideas
- One identity provider, every surface, and scopes are the through-line: the enforcement point moves, the model stays the same. There is no reason the broker needs its own
guest/guestaccount when Keycloak is already sitting right there. - The HTTP edge uses token exchange. At the gateway, RFC 8693 swaps a user's token for one scoped to the specific downstream service it calls, so their identity flows through without over-sharing claims.
- Messaging makes the broker a resource server. RabbitMQ authorizes publish and consume from the same JWT's scopes, down to the routing key, identically over AMQP 0.9.1 and AMQP 1.0. The boundary lives in the token, not the transport.
- AI clients need a registration broker. When an MCP client expects Dynamic Client Registration and the enterprise IdP can't offer it, a small Spring Authorization Server adds DCR, federates the login upstream, and mints role-derived scopes onto ES256 tokens.
- Or no registration at all. A Client ID Metadata Document makes the
client_ida URL the authorization server fetches, so nothing lands in a client table. It costs an SSRF guard and a runtime dependency on the client vendor's host.
Frequently asked questions
How do you secure a Spring Boot application with OAuth2?
Make one provider the authorization server, usually Keycloak, and put Spring Security's OAuth2 support on every surface the app exposes. HTTP endpoints validate JWTs as resource servers, the gateway exchanges a user's token for one scoped to each downstream service, and the message broker validates the same JWTs too. One identity provider, one set of scopes, enforced everywhere.
Can OAuth2 secure more than HTTP APIs in Spring?
Yes. The same OAuth2 architecture that guards HTTP endpoints also secures messaging. RabbitMQ can act as an OAuth2 resource server, validating the same Keycloak JWTs and authorizing publish and consume operations from the token's scopes. The token rides as the AMQP connection password instead of a Bearer header.
What is the difference between token exchange and client_credentials in Spring OAuth2?
Token exchange (RFC 8693) keeps a user's identity flowing through the gateway by swapping their token for one scoped to a specific downstream service. The client_credentials grant has no user: each service authenticates as its own OAuth2 client for service-to-service calls, which is what secures the messaging path. Token exchange fits a surface where a user is present, like the HTTP edge; client_credentials fits service-to-service traffic, like messaging.
More guides
- Building ralphctl: an agent harness, release by releaseThe build log of one agent harness: how ralphctl went from a v0.0.4 sprint CLI to a cross-provider loop I trust to run coding agents overnight.5 articles 70 min read
- Spring Boot and Postgres: where the limits actually areOne Spring Boot app, one Postgres: where a request really queues, what the connection pool gates, and how much search the database can do on its own.2 articles 46 min read
- AI agent harnesses: a field guideWhat an AI agent harness is, how the generator-evaluator loop and check gates decide when a change is done, and why the harness is the part you trust.3 articles 35 min read