For my Spring Boot 2.4 application, I've configured OAuth2 Login (OpenID Connect) that uses the OAuth 2.0 Authorization Code Grant flow internally.
The OAuth 2.0 specification for this flow defines the state parameter as recommended, mostly for CSRF-protection issues. A sample request looks like the following:
https://authorization-server.com/oauth/authorize
?client_id=a17c21ed
&response_type=code
&state=5ca75bd30
&redirect_uri=https%3A%2F%2Fexample-app.com%2Fauth
&scope=photos
As the application should run with multiple instances (at least two), I'm running into issues as this state parameter is randomly generated with different values for each Spring Boot instance. So the callback has to arrive at the same instance the request was initiated, as otherwise, the validation of this state field fails.
The relevant Spring Security code part I found is the following (resolve method of DefaultOAuth2AuthorizationRequestResolver)
builder.clientId(clientRegistration.getClientId())
.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri())
.redirectUri(redirectUriStr)
.scopes(clientRegistration.getScopes())
.state(this.stateGenerator.generateKey()) // this line generates it
.attributes(attributes);
If I enable sticky sessions on the load balancer, everything works as expected. But then I wouldn't describe the application setup as fully stateless.
Is there are way to persist the used state parameter e.g. in a database to share it among several Spring Boot instances to verify the callback at every instance? Or do I have to manually provide a custom StringKeyGenerator and somehow tweak the state validation?