Guide
Spring Boot and OAuth2: a field guide for every surface
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.
This guide ties the series together, each article built on a companion demo you can run with one command. It works through the app one surface at a time: the HTTP edge, where a user's identity has to reach the services behind a gateway, and the messaging path, where services talk to each other through a broker with no user in the loop. More surfaces can join the same architecture, and the list below tracks them as I write them. Same Keycloak, same Spring Security, whichever surface you are securing.
Key ideas
- One identity provider, every surface. A Spring app's HTTP endpoints, its gateway, and its
broker can all live in the same OAuth2 architecture. 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 the user's identity flows through without over-sharing claims.
- Messaging makes the broker a resource server. RabbitMQ validates the same Keycloak JWTs and authorizes publish and consume from the token's scopes, down to the routing key. The only real change is that the token travels as the AMQP connection credential. The model is identical over both AMQP 0.9.1 (Spring AMQP's classic client) and AMQP 1.0 (RabbitMQ 4's native protocol), which is the clearest proof that the security boundary lives in the token, not the transport.
- Scopes are the through-line. Whether a request hits an HTTP endpoint or a service publishes a message, the same scope claim decides what is allowed. The enforcement point moves; the model stays the same.
- AI clients need a registration broker. When an autonomous MCP client expects Dynamic Client Registration but the enterprise IdP can't offer it, a small Spring Authorization Server sits in front: it adds DCR, federates the human login upstream, and mints role-derived scopes onto its own ES256 tokens. The scopes still come from the upstream roles, never from what the client asks for.
In this guide
- Token exchange with Spring Cloud Gateway: A 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.
- OAuth2-secured RabbitMQ over AMQP 0.9.1: Secure your Spring Boot app's messaging with OAuth2, not guest/guest. RabbitMQ joins your HTTP APIs' Spring Security setup as a resource server.
- OAuth2-secured RabbitMQ over AMQP 1.0: Secure 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.
- MCP server OAuth2 in Spring: the DCR proxy pattern: A 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 clients
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.