Skip to main content
Stack Overflow
  1. About
  2. For Teams

You are not logged in. Your edit will be placed in a queue until it is peer reviewed.

We welcome edits that make the post easier to understand and more valuable for readers. Because community members review edits, please try to make the post substantially better than how you found it, for example, by fixing grammar or adding additional resources and hyperlinks.

Required fields*

Spring Boot OAuth2 with Casdoor behind AWS Lambda + HTTP API v2: state parameter encoding issue

I’m developing a Spring Boot application deployed behind an AWS API Gateway (HTTP API v2) with Lambda (handler based on SpringBootLambdaContainerHandler and HttpApiV2ProxyRequest).

I’m using OAuth2 with Casdoor, but I’m running into an issue with the state parameter:

  • Casdoor redirects back with a state generated by Spring Security.
  • API Gateway seems to pass the state URL-encoded (=%3D).
  • When Spring Security tries to match the returned state with the stored one, I get: authorization_request_not_found.

It works correctly locally. I also tested generating a state without special characters, and in that case the login flow worked behind Lambda/API Gateway.

Logs

DEBUG o.s.security.web.FilterChainProxy - Securing GET /oauth2/authorization/casdoor?
DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to https://casdoor.example.com/login/oauth/authorize?...&state=abd7CZ2NFOsuFT2ivWcun89d8t7Ndnhn4o08AyrXb6A%3D&redirect_uri=https://api.example.com/login/oauth2/code/casdoor
INFO LambdaContainerHandler - IP xxx.xxx.xxx.xxx -- "GET /oauth2/authorization/casdoor" 302
DEBUG o.s.security.web.FilterChainProxy - Securing GET /login?
INFO LambdaContainerHandler - IP xxx.xxx.xxx.xxx -- "GET /login" 302
DEBUG o.s.security.web.FilterChainProxy - Securing GET /login/oauth2/code/casdoor?code=xxxxx&state=abd7CZ2NFOsuFT2ivWcun89d8t7Ndnhn4o08AyrXb6A=
ERROR SecurityConfig - OAuth2 login FAILURE
org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found]

My Lambda handler

public class LambdaHandler implements RequestStreamHandler {
 private static final SpringBootLambdaContainerHandler<HttpApiV2ProxyRequest, AwsProxyResponse>
 handler;
 static {
 try {
 handler = SpringBootLambdaContainerHandler.getHttpApiV2ProxyHandler(PojaApplication.class);
 } catch (ContainerInitializationException e) {
 throw new RuntimeException("Initialization of Spring Boot Application failed", e);
 }
 }
 @Override
 public void handleRequest(InputStream input, OutputStream output, Context context)
 throws IOException {
 handler.proxyStream(input, output, context);
 }
}

My Spring Security configuration

package com.example.demo.endpoint.rest.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
 private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);
 private final String casdoorClientId;
 private final String casdoorLogoutUrl;
 public SecurityConfig(
 @Value("${spring.security.oauth2.client.registration.casdoor.clientid}")
 String casdoorClientId,
 @Value("${casdoor.logout.url}") String casdoorLogoutUrl) {
 this.casdoorClientId = casdoorClientId;
 this.casdoorLogoutUrl = casdoorLogoutUrl;
 }
 @Bean
 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
 http.csrf(Customizer.withDefaults())
 .authorizeHttpRequests(
 authz ->
 authz
 .requestMatchers("/casdoor-logout")
 .permitAll()
 .requestMatchers("/")
 .permitAll()
 .anyRequest()
 .authenticated())
 .oauth2Login(
 oauth2 ->
 oauth2
 .successHandler(
 (request, response, authentication) -> {
 log.info("OAuth2 login SUCCESS");
 log.info("User: {}", authentication.getName());
 log.info("Authorities: {}", authentication.getAuthorities());
 response.sendRedirect("/welcome");
 })
 .failureHandler(
 (request, response, exception) -> {
 log.error("OAuth2 login FAILURE");
 log.error("Message: {}", exception.getMessage());
 new SimpleUrlAuthenticationFailureHandler("/oauth2/authorization/casdoor")
 .onAuthenticationFailure(request, response, exception);
 log.info("Forced redirect to /oauth2/authorization/casdoor executed");
 }));
 return http.build();
 }
}

What I tried and expected

I ran the OAuth2 login flow locally, and it worked perfectly: Spring Security generated a state, Casdoor redirected back, and the state was correctly matched.

Behind AWS Lambda + HTTP API v2, using the default generated state (with characters like =), the login fails. Generating a state without special characters works correctly.

I expected Spring Security to automatically handle the state parameter and match it correctly behind Lambda + API Gateway.

What actually happens: the state arrives in the Lambda request, but Spring Security cannot match it with the stored state.

Question:

Could anyone please advise how to automatically handle the encoding/decoding of the state parameter so that Spring Security OAuth2 receives it correctly behind Lambda + HTTP API v2, and the Casdoor authentication works without having to generate the state manually?

Thank you in advance for your help!

Answer*

Draft saved
Draft discarded
Cancel
1
  • Then update your question, and as this post provides two working solutions, apply the one the author recommends, and once you get things working, accept the answer. Commented Oct 21, 2025 at 6:41

AltStyle によって変換されたページ (->オリジナル) /