Stateless Authentication
By default, Spring Security keeps the authentication of the user in the HTTP session. With stateless authentication, the browser keeps it instead, in a signed JSON Web Token (JWT). The server doesn’t need the session to know who the user is. A restart of the server therefore doesn’t log the users out, and several servers recognize the same users without sharing their sessions.
|
Important
|
Only for React Views
Stateless authentication is intended for applications whose views are all React views. Its behavior with Flow views is undefined. Flow views keep their UI state in the HTTP session, so they depend on the session in any case.
|
Dependencies
Stateless authentication needs these dependencies. Spring Boot manages their versions:
Source code
XML
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>Configuration
Apply VaadinStatelessSecurityConfigurer after VaadinSecurityConfigurer, and turn off the sessions of Spring Security:
Source code
Java
@EnableWebSecurity
@Configuration
public class SecurityConfigurer {
@Value("${my.app.auth.secret}")
private String authSecret;
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
// Disable creating and using sessions in Spring Security
http.sessionManagement(sessionManagement -> sessionManagement
.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
// Register your login view to the view access checker mechanism
http.with(VaadinSecurityConfigurer.vaadin(),
configurer -> configurer.loginView("/login"));
// Enable stateless authentication
http.with(new VaadinStatelessSecurityConfigurer<>(),
cfg -> cfg.withSecretKey()
.secretKey(new SecretKeySpec(
Base64.getDecoder().decode(authSecret), 1
JwsAlgorithms.HS256) 2
).and().issuer("com.example.application") 3
);
return http.build();
}
}Java
-
The secret key that signs and verifies the JWT, from the Base64-encoded property
my.app.auth.secret. -
The signature algorithm. The key must be long enough for the algorithm. The algorithm HS256 needs a key of at least 32 bytes.
-
The issuer of the JWT, a string or a URL that identifies the application.
|
Caution
|
Keep the Secret Key Secret
Anyone who has the key can create a JWT that the application accepts. Give each application and each environment a key of its own, and don’t commit it to the source repository. See Storing Sensitive Data. |
VaadinStatelessSecurityConfigurer has these configuration methods:
withSecretKey()-
Configures the secret key. It returns a configurer with the methods
secretKey(), which sets the key,algorithm(), which sets the algorithm, andand(), which returns toVaadinStatelessSecurityConfigurer. When the algorithm isn’t set, it comes from the key. An overload ofwithSecretKey()takes aCustomizerof that configurer instead. issuer()-
Sets the issuer of the JWT.
expiresIn()-
Sets the lifetime of the JWT in seconds. The default is 1800 seconds, which is 30 minutes.
Tokens & Cookies
After the login, the server sends the JWT in two cookies:
jwt.headerAndPayload-
The header and the payload of the JWT. The browser code can read this cookie.
jwt.signature-
The signature of the JWT, in an HTTP-only cookie that the browser code can’t read.
The server renews the JWT and the cookies in its responses, so they expire after the lifetime of the JWT has passed without requests. For example, this sets the lifetime to one hour:
Source code
Java
http.with(new VaadinStatelessSecurityConfigurer<>(), cfg -> cfg
.withSecretKey().secretKey(secretKey).and()
.issuer("com.example.application")
.expiresIn(3600));The payload has the name of the user as its subject, the issuer, and the times when the JWT was issued and when it expires. Its roles claim lists the role authorities of the user, without the role prefix. When the server reads the JWT, it adds the prefix again. The other granted authorities of the user aren’t in the JWT.
The CSRF token is also in a cookie, XSRF-TOKEN, instead of the session.