403 Forbidden on login via browser when Spring Boot app runs from JAR, but works in IDE and API clients
03:22 11 May 2025

I'm facing an issue with my Spring Boot application. When I run the app directly from my IDE, everything works fine — I can log in from my Angular frontend (via POST /login) without any problems.

However, after I've packaged the app into a JAR file using mvn clean install and run it with java -jar my-app.jar, I get the following behavior:

  • Logging in via Postman or Insomnia still works (POST request to /login returns token as expected).

  • Logging in via the Angular frontend (in the browser) fails with a 403 Forbidden error.

Backend logs show:

HttpRequestMethodNotSupportedException: Request method 'GET' is not supported

What I've checked:

  • CORS configuration in SecurityConfiguration allows http://localhost:4200 and includes POST method.
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable)
                .cors(cors -> cors.configurationSource(request -> {
                    var corsConfiguration = new CorsConfiguration();
                    corsConfiguration.setAllowedOriginPatterns(List.of("http://localhost:4200"));
                    corsConfiguration.setAllowedMethods(List.of("GET","PATCH", "POST", "PUT", "DELETE", "OPTIONS"));
                    corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
                    
                    corsConfiguration.setAllowCredentials(true);
                    return corsConfiguration;
                }))
                .authorizeHttpRequests(request -> request
                        .requestMatchers("/","/login","/join").permitAll()
                        .requestMatchers("/users").hasRole("ADMIN")
                        .requestMatchers("/uploads/**").permitAll()
                        .anyRequest().authenticated())
                .sessionManagement(manager -> manager.sessionCreationPolicy(STATELESS))
                .authenticationProvider(authenticationProvider())
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
  • Angular is sending a POST request to /login.
login(loginRequest: LoginRequest): Observable {
    this.dataService.log(true);
    return this.http.post(`${environment.baseURL}/login`, loginRequest
)
    .pipe(
      tap((response: AuthResponse) => {
        if (response.token) {
          localStorage.setItem('jwtToken', response.token);
        }
      }),
      catchError(error => {
        console.error('Login error:', error);
        return throwError(() => new Error(error.error?.message || 'Login failed. Please try again.'));
      })
    );
  }
  • Angular interceptor:
export const headerInterceptor: HttpInterceptorFn = (req: HttpRequest,
  next: HttpHandlerFn
): Observable> => {
  const Authorization = localStorage.getItem('jwtToken') ? `Bearer ${localStorage.getItem('jwtToken')}` : '';
  if(!req.url.includes('login') && !req.url.includes('join'))
    return next(req.clone({ setHeaders: { Authorization } }));
  else 
  return next(req);
};
  • environment.prod.ts:
export const environment = {
    production: true,
    baseURL: "http://localhost:8080",
    eventsURL: "http://localhost:8080/events",
    homeURL: "http://localhost:8080/home",
    citiesURL: "http://localhost:8080/cities",
    commentsURL: "http://localhost:8080/comments",
    usersURL: "http://localhost:8080/users"
};
  • and in angular.json:
"fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ]
  • in application.yml:
profiles:
  active: prod
  • start .jar with
java -jar my-app.jar --spring.profiles.active=prod
  • Works perfectly in IDE.

  • Fails only after running from the JAR.

No apparent difference in logs or stack traces that explain why only browser requests fail.

Question:

What could cause Spring Boot to behave differently (especially for browser-based login requests) when running from a JAR versus running from the IDE?

java angular spring spring-boot jwt