skip to content

Spring Authorization Server

Spring Authorization Server issues tokens itself: registered clients, the discovery document, and the authorize and token endpoints. Interviewers ask when you would run your own rather than buy Auth0 or Keycloak, and the honest answer is rarely.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is Spring Authorization Server, and what role do RegisteredClient and RegisteredClientRepository play in it?

level: juniorimportance: must knowfreq 60%

answer

  1. Separate project, not Security core
  2. Issues access + id tokens
  3. RegisteredClient = one allowed app
  4. InMemory vs Jdbc repository
  5. findByClientId on each request

basics

~20 s

Spring Authorization Server is a standalone project that turns your app into an OAuth2/OIDC provider — it issues tokens. A RegisteredClient is one app allowed to request tokens; RegisteredClientRepository stores and looks up those clients.

solid answer

~40 s

Spring Authorization Server (a separate project from Spring Security, not part of the core framework) provides a compliant OAuth2 Authorization Server and OpenID Connect 1.0 Provider. It exposes endpoints like /oauth2/authorize, /oauth2/token and /oauth2/jwks and issues access tokens and OIDC id tokens. A RegisteredClient models a client application permitted to obtain tokens: its clientId/clientSecret, allowed authorization grant types (e.g. authorization_code, client_credentials), redirect URIs, and scopes. RegisteredClientRepository is the abstraction that saves and finds those clients — InMemoryRegisteredClientRepository for demos/tests, JdbcRegisteredClientRepository for persistence. On each token request the server loads the RegisteredClient by clientId to validate the request and decide what it may be issued.

code

java · 16 lines
java
RegisteredClient client = RegisteredClient.withId(UUID.randomUUID().toString())
    .clientId("web-app")
    .clientSecret("{bcrypt}$2a$10$...")
    .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
    .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
    .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
    .redirectUri("https://app.example.com/login/oauth2/code/web-app")
    .scope(OidcScopes.OPENID)
    .scope("read")
    .clientSettings(ClientSettings.builder().requireProofKey(true).build())
    .build();

@Bean
RegisteredClientRepository registeredClientRepository() {
    return new InMemoryRegisteredClientRepository(client);
}

go deeper

for a junior

Know it issues tokens and that RegisteredClient = an app allowed to get tokens.

for a middle

Explain RegisteredClient fields (grant types, scopes, redirect URIs) and InMemory vs Jdbc repositories.

for a senior

Discuss client authentication methods, PKCE for public clients, and custom RegisteredClientRepository implementations.

for a principal

Weigh self-hosting an IdP vs delegating to Keycloak/Okta; persistence, multi-instance, and client-lifecycle management.

**What it is.** Spring Authorization Server is a dedicated Spring project (artifact `org.springframework.security:spring-security-oauth2-authorization-server`) that lets you host your own **OAuth2 Authorization Server** and **OpenID Connect (OIDC) 1.0 Provider**. It is *not* bundled in Spring Security core — you add it as a separate dependency. Its job is to **authenticate clients/users and issue tokens** that resource servers (APIs) then trust. **Vocabulary (assume nothing).** - *OAuth2*: a delegated-authorization protocol. A *client* application gets an **access token** to call protected APIs on a user's behalf. - *OIDC*: an identity layer on top of OAuth2 that additionally issues an **id token** (a JWT describing *who* the user is) and a discovery/userinfo mechanism. - *Client*: an application (e.g. a SPA, mobile app, or backend service) that requests tokens — distinct from the end user. - *Grant type*: the flow used to get a token (authorization_code, client_credentials, refresh_token, etc.). **RegisteredClient.** An immutable value object describing exactly one client that is allowed to talk to the server. Built via `RegisteredClient.withId(...)`. Key fields: - `clientId` / `clientSecret` — the client's credentials (secret typically encoded with a `PasswordEncoder`). - `clientAuthenticationMethod(s)` — how the client proves itself, e.g. `CLIENT_SECRET_BASIC`, `NONE` for public clients using PKCE. - `authorizationGrantType(s)` — `AUTHORIZATION_CODE`, `CLIENT_CREDENTIALS`, `REFRESH_TOKEN`, etc. - `redirectUri(s)` — allowed callback URLs (validated exactly on the authorization_code flow). - `scope(s)` — permissions the client may ask for; `OidcScopes.OPENID` is required to get an id token. - `clientSettings` / `tokenSettings` — e.g. require PKCE, require consent, token TTLs, token format. **RegisteredClientRepository.** The strategy interface the server uses to persist and retrieve clients. Two methods matter: `save(RegisteredClient)` and `findByClientId(String)` / `findById(String)`. Built-in implementations: - `InMemoryRegisteredClientRepository` — a fixed in-memory list; great for tests and demos, lost on restart. - `JdbcRegisteredClientRepository` — persists to a relational database using the schema shipped with the project; the production choice. You can also implement it yourself (e.g. to load clients from your own tables or a config service). **How it fits at runtime.** When a token request arrives, the server extracts the `clientId`, calls `findByClientId`, and uses the returned `RegisteredClient` to validate the request (is this grant allowed? is the redirect URI registered? are the scopes permitted?) and to shape the issued tokens. **Gotchas.** - The server is a separate deployable/config; don't confuse it with `spring-security-oauth2-client` (which makes your app a *client*) or `spring-security-oauth2-resource-server` (which makes your app validate tokens). - `InMemoryRegisteredClientRepository` state is lost on restart and not shared across instances — never use it in production. - A missing `openid` scope means no id token is issued even though it's an OIDC-configured server. **When to use.** Choose Spring Authorization Server when you need to *own* your identity/token issuance (internal IdP, first-party SSO) instead of delegating to Okta/Auth0/Keycloak.

  • Which repository implementation would you use in production and why?
    JdbcRegisteredClientRepository, so clients survive restarts and are shared across all server instances via the database; InMemory is only for tests/demos.
  • How does the server know which app is calling?
    The client authenticates (e.g. clientId+secret via CLIENT_SECRET_BASIC, or PKCE for public clients); the server looks up the RegisteredClient by clientId to validate the request.

saying these in an interview costs you the question

  • Thinking Spring Authorization Server is part of Spring Security core rather than a separate project
  • Confusing it with oauth2-client (consumer) or resource-server (validator)
  • Believing InMemoryRegisteredClientRepository is fine for production

context

open as a page

How does Spring Authorization Server issue access tokens versus OIDC id tokens, and how do they differ?

level: middleimportance: must knowfreq 50%

basics

~20 s

The access token authorizes API calls (it says what the client may do); the id token is proof of the user's identity for the client (it says who logged in). The id token is only issued when the client requests the openid scope.

open as a page

What is the OIDC /.well-known discovery endpoint, and which core endpoints does Spring Authorization Server expose by default?

level: middleimportance: should knowfreq 45%

basics

~10 s

The discovery endpoint /.well-known/openid-configuration returns JSON metadata (issuer plus URLs of the authorize, token, jwks, and userinfo endpoints) so clients can auto-configure. Spring Authorization Server also exposes /oauth2/authorize, /oauth2/token, and /oauth2/jwks.

open as a page

How do you customize the claims in issued tokens and configure JWT signing in Spring Authorization Server?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Register an OAuth2TokenCustomizer<JwtEncodingContext> bean to add or change claims per token type. Provide a JWKSource<SecurityContext> bean holding your signing key(s); the server signs JWTs with the private key and publishes the public key at /oauth2/jwks.

open as a page

You are running Spring Authorization Server as a multi-instance production IdP. What are the key architectural concerns and how do you address them?

level: principalimportance: should knowfreq 25%

basics

~20 s

Persist clients and authorizations in a shared database (Jdbc*Repository, not in-memory), load stable signing keys from a secret store with a rotation plan, set an explicit issuer that matches the public URL behind your proxy, and enforce PKCE/consent and short token TTLs.

open as a page