I am new to Spring Boot and I am developing a simple API with few endpoints. Now I am implementing an Authorization Server (Oauth2AuthorizationServer) and Resource server with my endpoints. I have noticed that when AuthServer issues once a JWT token with provided credentials (I am using credential flow), Resource Server is able to verify the JWT even when the AuthServer is stopped. How that magic happens? I was thinking in the beginning that AuthServer must authorize every request made to the resource server. I can’t figure it out how Resource server is able to decode the JWT even the auth server is down. Please, can somebody explain it to me how exactly things work.
When I try to make the first request to Resource server and AuthServer is stopped, there is an error – that there is no @Bean with decoder().
Advertisement
Answer
Spring Security supports protecting endpoints by using two forms of OAuth 2.0 Bearer Tokens:
- JWT
- Opaque Tokens
The behavior you experienced means that you configured JWT Authentication, by specifying the Authorization Server with an issuer URI, for example:
spring: security: oauth2: resourceserver: jwt: issuer-uri: https://idp.example.com/issuer
According to Spring documentation:
Resource Server will use this property to further self-configure, discover the authorization server’s public keys, and subsequently validate incoming JWTs.
It configures itself through the following steps:
- Query the Provider Configuration or Authorization Server Metadata endpoint for the
jwks_url
property- Query the
jwks_url
endpoint for supported algorithms- Configure the validation strategy to query
jwks_url
for valid public keys of the algorithms found- Configure the validation strategy to validate each JWTs
iss
claim againstidp.example.com
.
An important note from the docs which answers one of your questions is:
If the authorization server is down when Resource Server queries it (given appropriate timeouts), then startup will fail.
During the runtime, any request containing an Authorization: Bearer
header is processed as follows:
Validate its signature against a public key obtained from the
jwks_url
endpoint during startup and matched against the JWTValidate the JWT’s
exp
andnbf
timestamps and the JWT’siss
claim, andMap each scope to an authority with the prefix
SCOPE_
.
There is no communication between Resource Server and Authorization Server during this process, so it doesn’t have to be up after startup.
The behavior you expected, in the beginning, is actually related to Opaque Token Authentication. Where Authorization Server is specified with different properties, according to Spring documentation:
spring: security: oauth2: resourceserver: opaque-token: introspection-uri: https://idp.example.com/introspect client-id: client client-secret: secret
This startup process is quite a bit simpler than for JWTs since no endpoints need to be discovered and no additional validation rules get added.
At the runtime, it is also processing any request containing an Authorization: Bearer
header:
Query the provided introspection endpoint using the provided credentials and the token
Inspect the response for an
{ 'active': true }
attributeMap each scope to an authority with the prefix
SCOPE_
This means that the token is valid only if the Authorization Server responds that it is.