Problem Overview:
I have a web application built with a Java Spring Boot backend and a custom frontend using JavaScript. The frontend communicates with the backend through a Spring Cloud Gateway. The application involves user registration and login functionality.
When I try to GET or to POST user from my frontend I get status 403 (forbidden), but in contrast in Postman I get status 200 OK. I have tried now for a week to solve the issue without any luck.
Also, when I remove the Gateway API and send information directly to the microservice from the frontend I do not encounter any error. That is why I believe the issue lays somewhere in the Gateway API, hope this helps to pin point the problem that I did not find!
Error/ Status message from my frontend
UserLogin.js:9
GET http://localhost:5000/usersRegistration/get/test@mail.com/Test$12345 403 (Forbidden)
(anonymous) @ UserLogin.js:9
UserLogin.js:14
UserLogin.js:26 Error: Error: Login failed. Invalid credentials.
at UserLogin.js:18:23
Gateway API
package webapplication.gatewayapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://localhost:63343")
@SpringBootApplication
public class GatewayApiApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApiApplication.class, args);
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("usersRegistration", r -> r.path("/usersRegistration/**")
.uri("http://localhost:5001"))
.build();
}
}
Gateway application.yaml
server:
port: 5000
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOriginPatterns: "*"
allowedMethods:
- GET
- POST
allowedHeaders: "*"
allowCredentials: true
maxAge: 3600
routes:
- id: LoginSignUpUsers
uri: http://localhost:5001
predicates:
- Method=GET,POST
- Path=/usersRegistration/**
filters:
- RewritePath=/usersRegistration/(?<segment>.*),/$\{segment}
metadata:
cors:
allowedOrigins: http://localhost:63343
allowedMethods: GET,POST
Microservice where users login and sign up
package webapplication.login_signup.RestApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("usersRegistration")
@CrossOrigin(origins = "http://localhost:5000")
@Validated
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public List<UserModel> getAllUsers() {
return userService.getAllUsers();
}
@GetMapping("/get/{email}/{password}")
public ResponseEntity<UserModel> getUser(@Valid @PathVariable String email, @Valid @PathVariable String password) {
UserModel user = userService.getUserByEmailAndPassword(email, password);
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.notFound().build();
}
}
@PostMapping("/post")
public ResponseEntity<UserModel> createUser(@Valid @RequestBody UserModel userModel, BindingResult bindingResult) {
UserModel createdUser = userService.createUser(userModel);
if (bindingResult.hasErrors()) {
return ResponseEntity.badRequest().body(createdUser);
}
if (createdUser == null) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}
}
Microservice Spring Security
package webapplication.login_signup.Security;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/usersRegistration/**").permitAll()
.anyRequest().authenticated()
.and()
.cors()
.and()
.csrf().disable();
}
}
Frontend Javascript method get inf
document.getElementById("loginForm").addEventListener("submit", function (event) {
event.preventDefault();
const formData = new FormData(event.target);
const email = formData.get('email');
const password = formData.get('password');
fetch(`http://localhost:5000/usersRegistration/get/${email}/${password}`, {
method: 'GET',
})
.then(response => {
console.log(response.statusText + " and " + response.status);
if (response.ok) {
return response.json();
} else {
throw new Error('Login failed. Invalid credentials.');
}
})
.then(data => {
console.log('Login successful!', data);
window.location.href = '..FrontendWebApplication/FrontEnd/nextPage.html';
})
.catch(error => {
console.error('Error:', error);
const errorMessage = document.getElementById('error-message');
errorMessage.textContent = 'Invalid email or password!';
});
});
To view and test the whole code can be found in this GitHub repo: https://github.com/LyubomirD/WebApplication_Microservices
Thanks in advance to all of you!