Class AuthorizationServerConfigurer
Makes the server an OAuth2 authorization server and OpenID Connect provider.
@Bean
SecurityFilterChain web(HttpSecurity http) {
http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.formLogin(Customizer.withDefaults())
.authorizationServer(Customizer.withDefaults());
return http.build();
}
@Bean
RegisteredClientRepository clients() {
return new InMemoryRegisteredClientRepository(RegisteredClient.withId("app")
.clientId("acme-app")
.clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.redirectUri("com.acme.app:/oauth2redirect")
.scope("openid").scope("profile").build());
}
Endpoints
| Path | |
|---|---|
GET /oauth2/authorize |
the authorization endpoint, for the signed-in user |
POST /oauth2/token |
the token endpoint |
GET /oauth2/jwks |
the public halves of the signing keys |
POST /oauth2/revoke |
revocation (RFC 7009) |
POST /oauth2/device_authorization |
starts a device grant (RFC 8628) |
/oauth2/device_verification |
the page where the signed-in user types the device's code, and the same steps as JSON for a request that asks for it |
GET /userinfo |
the user's claims, for an access token granted openid |
GET /.well-known/openid-configuration, /.well-known/oauth-authorization-server |
the metadata |
The paths can be changed, and the issuer must be given outside a
development profile; see AuthorizationServerSettings.
Signing in
The authorization endpoint and the device verification page are for a
signed-in user, and how a user signs in is whatever else the chain
declares: formLogin, oauth2Login, a second factor. A browser that
arrives signed out is sent to sign in and comes back to the request it
made. A client that is not a browser -- its Accept does not name
text/html -- is answered 401 with login_required instead.
Grants
authorization_code, with PKCE: required of a public client, and S256 only. A code works once, for five minutes; presenting one again later revokes what its use was issued. (Presented twice within ten seconds -- a retry, or two processes handed one request -- one is answered and the other refused, and nothing is revoked.) The redirect address must be one the client registered, exactly -- seeRegisteredClient-- and a request whose client or address is wrong is answered with a 400 and never a redirect.refresh_token: opaque, stored as a hash, replaced on every use; using one that was replaced revokes the grant, with the same ten seconds' allowance for a client that refreshes twice at once. A public client is issued one too -- the rotation is what protects it there.client_credentials, for a client with a secret.urn:ietf:params:oauth:grant-type:device_code: the device shows a code of eight letters, the user types it at the verification page, is asked -- by name -- whether to let that client in, and approves; the answer counts only from the question this server put to that session. The device's polling is answeredauthorization_pending,slow_down,access_deniedorexpired_tokenuntil it is.
A client is never granted a scope it was not registered with, and there is no consent page: registering a client with a scope is the consent.
Tokens and keys
An access token is a JWT of type at+jwt (RFC 9068). Its aud is the
resource server it is for: what the request named with the resource
parameter (RFC 8707) -- at the authorization endpoint, the device
authorization endpoint or the token endpoint, where it may only narrow what
the grant was made for -- or else the server's default audience, which is
the issuer unless
AuthorizationServerSettings.Builder.defaultAudience or
cn1.security.authorizationserver.audience says otherwise. A client
registered with resources may ask for those only; invalid_target answers
anything else. /userinfo answers a token that is for this server -- the
default audience, or the address of /userinfo named as a resource -- and
not one made only for other resource servers. The client the token was
issued to is its client_id
claim. An ID token is for the client, and its aud is the client id: it
carries
nonce, auth_time, azp and at_hash, and both are signed RS256 -- or
ES256 when the signing key is a P-256 one. The keys are the application's
JwkSource bean, or the files named by
cn1.security.authorizationserver.jwk.keys; see AuthorizationServerKeys,
which is also how an application signs tokens of its own with them.
Access tokens are verified by their signature alone, anywhere: revoking a
grant stops its refresh token and its answers at /userinfo, and an
access token already issued stays good until it expires. Keep them short.
What is kept, and where
The clients are the application's RegisteredClientRepository bean. The
grants are its OAuth2AuthorizationService bean; without one they are kept
in this process, which a line at start-up says, and are lost when it stops
and unknown to any other process. Client secrets are compared through the
application's PasswordEncoder bean, or the one given to
clientSecretEncoder(PasswordEncoder). With neither, a server whose clients are all known
when it starts -- an
InMemoryRegisteredClientRepository
-- does not start if one of them has a secret. One whose clients are in a
table starts, says once that it cannot check secrets, and refuses a client
that presents one with invalid_client.
Not here
A consent page, dynamic client registration, token introspection, opaque
access tokens, private_key_jwt and mutual TLS client authentication,
pushed authorization requests, DPoP, encrypted tokens, the implicit and
password grants, and back-channel or RP-initiated logout.
-
Field Summary
Fields -
Method Summary
Modifier and TypeMethodDescriptionauthorizationService(OAuth2AuthorizationService authorizationService) Where grants are kept, in place of the application's bean.clientSecretEncoder(PasswordEncoder passwordEncoder) What client secrets were encoded with, in place of the application'sPasswordEncoderbean.The clock every lifetime is measured on; for tests.voidconfigure(HttpSecurity http) Adds this part's filters; nothing by default.deviceVerificationRateLimiter(RateLimiter rateLimiter) What bounds how many device codes one user may try at the verification page, in place of what the application'sRateLimiterbean would count and of the count kept in this process.voidinit(HttpSecurity http) Shares what other parts need to know; nothing by default.The signing keys, the first of them signing, in place of the application's bean and the configuration.jwtEncoder(JwtEncoder jwtEncoder) What signs, in place of the application's bean.registeredClientRepository(RegisteredClientRepository registeredClientRepository) The clients, in place of the application's bean.settings(AuthorizationServerSettings settings) The issuer and the paths; seeAuthorizationServerSettings.tokenCustomizer(OAuth2TokenCustomizer tokenCustomizer) Changes the claims of every token before it is signed.userInfoMapper(OidcUserInfoMapper userInfoMapper) What the server says of a user; seeOidcUserInfoMapper.Methods inherited from class SecurityConfigurer
disable, getBuilder
-
Field Details
-
DEVICE_VERIFICATION_ATTEMPTS
The setting that holds how many device codes one user may try at the verification page in one window; 10 unless set.- See Also:
-
DEVICE_VERIFICATION_WINDOW
The setting that holds the length of that window in seconds; 300 unless set.- See Also:
-
-
Method Details
-
settings
The issuer and the paths; seeAuthorizationServerSettings. -
registeredClientRepository
public AuthorizationServerConfigurer registeredClientRepository(RegisteredClientRepository registeredClientRepository) The clients, in place of the application's bean. -
authorizationService
public AuthorizationServerConfigurer authorizationService(OAuth2AuthorizationService authorizationService) Where grants are kept, in place of the application's bean. -
jwkSource
The signing keys, the first of them signing, in place of the application's bean and the configuration. -
jwtEncoder
What signs, in place of the application's bean. It must sign with the keys ofjwkSource(JwkSource). -
clientSecretEncoder
What client secrets were encoded with, in place of the application'sPasswordEncoderbean. -
tokenCustomizer
Changes the claims of every token before it is signed. -
userInfoMapper
What the server says of a user; seeOidcUserInfoMapper. -
deviceVerificationRateLimiter
What bounds how many device codes one user may try at the verification page, in place of what the application's
RateLimiterbean would count and of the count kept in this process.Ten tries in five minutes are allowed unless
cn1.security.authorizationserver.device.verificationAttemptsandcn1.security.authorizationserver.device.verificationWindowSecondssay otherwise. With no limiter they are counted in this process. With oneRateLimiterbean they are counted wherever it counts -- aJdbcRateLimitermakes that every process -- in a limiter the bean derives, with that limit; seeRateLimiter.derive(String, int, long). A limiter given here, or a bean that derives none, counts by its own limit, and setting the two keys as well is then refused when the chain is built, since they would decide nothing.Of several
RateLimiterbeans the one marked@Primaryis used. With none marked, or more than one, the chain is refused when it is built and the message names the beans; mark one, or pass the one meant here. -
clock
The clock every lifetime is measured on; for tests. -
init
Description copied from class:SecurityConfigurerShares what other parts need to know; nothing by default.- Overrides:
initin classSecurityConfigurer
-
configure
Description copied from class:SecurityConfigurerAdds this part's filters; nothing by default.- Overrides:
configurein classSecurityConfigurer
-