The plan
What we are building, what OAuth and OpenID Connect each answer, and what this series deliberately leaves out.
You will build
nothing yet: a map of the server, the protocols, and the fourteen parts
You will understand
the difference between OAuth and OpenID Connect, where OAuth 2.1 stands, and why the finished project is a template rather than an identity product
Most OAuth tutorials stop after they can print an access token.
That is useful for learning the protocol, but it is far from what an authorization server needs once real users, clients, keys, databases, revocation, account security, deployment, and operations enter the picture.
In this series we build the server incrementally, starting with an empty Spring Boot project and ending with a production-oriented template that supports:
- Authorization Code flow;
- PKCE;
- OpenID Connect;
- JWT access tokens and ID tokens;
- refresh tokens with rotation;
- PostgreSQL-backed OAuth clients, authorizations, and consent;
- database-backed users and roles;
- OAuth scope management;
- administrative client and user APIs;
- password management and login lockout;
- persistent RSA signing keys;
- UserInfo;
- token revocation and introspection;
- audit logging;
- health/readiness probes;
- Docker and CI.
The finished project is deliberately a template, not an attempt to replace a complete identity product such as Keycloak, Auth0, Okta, or an enterprise IAM platform.
What are we actually building?
flowchart LR
U[Resource Owner / User]
C[OAuth Client]
AS[Our Spring Authorization Server]
RS[Resource Server / API]
DB[(PostgreSQL)]
K[RSA Signing Keys]
U --> C
C -->|Authorization request + PKCE| AS
AS -->|Authorization code| C
C -->|Code + verifier| AS
AS -->|Access + Refresh + ID token| C
C -->|Bearer access token| RS
AS --> DB
AS --> K
The authorization server is responsible for authentication, authorization grants, client configuration, token issuance, and—because we enable OpenID Connect—identity assertions.
A resource server is a different role. It consumes access tokens and protects APIs. We will make the authorization server itself act as a resource server only for its own sensitive management APIs.
OAuth versus OpenID Connect
One distinction matters throughout the series:
| Protocol | Main question |
|---|---|
| OAuth | “What is this client allowed to access?” |
| OpenID Connect | “Who is the authenticated user?” |
OAuth access tokens are for delegated access. OpenID Connect adds an identity layer and introduces concepts such as the openid scope, ID Token, UserInfo endpoint, and standard identity claims.
OAuth 2.1 note
As of September 2026, OAuth 2.1 remains an active IETF Internet-Draft rather than a published RFC. Spring Security describes its authorization-server support as OAuth 2.1-oriented, while the implementation also relies on stable related specifications such as PKCE, JWT, token revocation, token introspection, and OpenID Connect.
We will therefore build around modern practices—Authorization Code + PKCE, short-lived access tokens, refresh-token rotation, exact redirect URIs, and no implicit flow—without pretending the OAuth 2.1 draft is a finalized RFC.
Series roadmap
Part 1 — The OAuth/OIDC mental model
Before code, we establish the actors, tokens, grants, scopes, PKCE, JWT, OIDC, and trust boundaries.
Part 2 — Bootstrap Spring Authorization Server
We create the Spring Boot project, define security filter chains, enable OIDC, register a development client, and expose discovery/JWKS endpoints.
Part 3 — Authorization Code + PKCE + JWT + refresh tokens
We perform the first complete browser-based authorization flow and inspect the resulting tokens.
Part 4 — PostgreSQL + Flyway persistence
We remove the in-memory OAuth repositories and persist clients, authorizations, refresh tokens, and consent.
Part 5 — Database users and roles
We replace the in-memory user with JPA entities and a database-backed UserDetailsService.
Part 6 — Registration, error handling, and safe development seed data
We add a registration API, validation, centralized API errors, and profile-isolated development fixtures.
Part 7 — Admin OAuth client management and scope registry
We build protected management APIs for OAuth clients and custom scopes.
Part 8 — Testcontainers and persistent RSA signing keys
We make the test suite use a real PostgreSQL container and stop regenerating production signing keys on every restart.
Part 9 — User administration and account security
We add user administration, password change/reset, failed-login tracking, temporary locks, and manual locks.
Part 10 — OpenID Connect identity claims and UserInfo
We add scope-aware identity claims to ID Tokens and verify /userinfo.
Part 11 — Revocation and introspection
We test RFC 7009/RFC 7662 behavior and immediately reject revoked JWTs on sensitive management APIs.
Part 12 — Runtime hardening
We externalize issuer/CORS, add health/readiness endpoints, and persist security audit events.
Part 13 — Docker, CI, and v1.0
We package the application, keep signing keys outside the image, run integration tests in GitHub Actions, and create a clean v1 release.
The code
The finished project is on GitHub: mesubash/spring-boot-oauth2-authorization-server, released as
v1.0.0.
Every part ends with a The code section listing the exact commits it corresponds to, so you can check out the project as that part leaves it and compare it with your own:
git clone https://github.com/mesubash/spring-boot-oauth2-authorization-server.git
cd spring-boot-oauth2-authorization-server
git checkout <commit from the part>
The history is linear, so stepping forward one commit at a time is a good way to see each change in isolation.
What this series intentionally does not build
A complete identity product would require many more concerns. We leave these for later extensions:
- MFA/passkeys;
- email verification;
- forgot-password email workflows;
- social/federated identity providers;
- dynamic client registration;
- advanced consent UI;
- organization/multi-tenant identity;
- hardware/KMS-backed signing-key rotation;
- distributed rate limiting;
- fraud/risk engines;
- dedicated administrative frontend.
That boundary is intentional. The goal is a strong authorization-server foundation whose architecture is small enough to understand.
Primary references
- Spring Security Authorization Server: https://docs.spring.io/spring-security/reference/servlet/oauth2/authorization-server/
- OAuth 2.1 Internet-Draft: https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/
- OAuth 2.0 Security BCP — RFC 9700: https://www.rfc-editor.org/rfc/rfc9700
- PKCE — RFC 7636: https://www.rfc-editor.org/rfc/rfc7636
- OpenID Connect Core 1.0: https://openid.net/specs/openid-connect-core-1_0.html
- JWT — RFC 7519: https://www.rfc-editor.org/rfc/rfc7519
In the next part, we build the mental model we will use for every implementation decision that follows.