My React app is just a simple login Page and my intention is how do I able to tackle the Spring Security Authentication via React Login,
My React app is running at localhost:5713
My Spring app is running at localhost:5001
my react code:
export default function Login(){
let [username,setUsername]=useState('')
let [password,setPassword]=useState('')
let formSubmit=async(e)=>{
e.preventDefault();
console.log(username,password)
const login=await fetch("http://localhost:5001/login",{
method: 'POST',
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify({username,password})
})
console.log(login)
const data=login.json();
console.log(data)
}
// useEffect(()=>{
// },[])
return(
<>
<form onSubmit={formSubmit}>
<label htmlFor="username">Name</label>
<input id="username" name="username" type="text" value={username} onChange={e=>setUsername(e.target.value)} />
<label htmlFor="password">Password</label>
<input id="password" name="password" value={password} onChange={e=>setPassword(e.target.value)} type="password" />
{/* <button type="submit">Login</button> */}
<Button>Submit</Button> <!-- my custom button Component -->
</form>
</>
)
}
and here is how my Spring Boot Security looks like:
@EnableWebSecurity
public class SecurityConfigTest implements WebMvcConfigurer {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.securityMatcher("/**")
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/user/add", "/csrf", "/login").permitAll()
.anyRequest().authenticated()
)
.formLogin(formLogin -> formLogin
.loginPage("http://localhost:5173/login") // My react app Login Form
.defaultSuccessURL("/testing") //its defined in my Springboot controller
)
return http.build();
}
@Bean
UserDetailsService userDetailsService(PasswordEncoder pa) {
UserDetails user=User.withUsername("admin")
.password(pa.encode("pass"))
.roles("ADMIN")
.build();
System.out.println("at userDetailsService");
UserDetails user1=User.withUsername("user")
.password(pa.encode("user"))
.roles("USER")
.build();
System.out.println(user.getUsername());
System.out.println(user.getPassword());
return new InMemoryUserDetailsManager(user,user1);
}
}
I was using the @CrossOrigin(origins = "http://localhost:5173") into my spring boot app at my Controller Class level.
My Controller:
@Controller
@CrossOrigin(origins = "http://localhost:5173")
class ConnTest{
UserRepo userRepo;
@Autowired
TestingSerivce test;
// one way to read the app.props values
@Value("${spring.jpa.database}")
String dbname;
ConnTest(UserRepo userRepo,TestingSerivce test){
this.userRepo=userRepo;
this.test=test;
}
@ResponseBody
@GetMapping("/")
String test(HttpServletRequest req) {
return "Hello Welcome to my Demo";
}
@ResponseBody
@PostMapping("/user/add")
int addUser(@RequestBody User user) {
userRepo.save(user);
System.out.println(user);
return 1;
}
@ResponseBody
@GetMapping("/out")
String logoutHere(HttpServletRequest req) throws ServletException {
System.out.println(req.getRemoteUser()+"\nSession : "+req.getSession());
req.logout();
HttpSession session = req.getSession(false);
if(session!=null) session.invalidate();
System.out.println(req.getRemoteUser()+"\nSession : "+req.getSession());
return "Logging out...";
}
@ResponseBody
@GetMapping("/csrf")
CsrfToken httpServReq(HttpServletRequest req) {
// return securityConfig.csrfToken(req);
System.out.println("tesing");
return (CsrfToken) req.getAttribute("_csrf");
}
@ResponseBody
@GetMapping("/test/x")
String testx(@RequestParam(required = false) String msg) {
String header="{'ab':'xyx'}";
byte []b=header.getBytes();
String encoded=Base64.getEncoder().encodeToString(b);
System.out.println(encoded);
if (msg == null) {
return "Null Msg";
}
return "this is my Testingx -> " + msg;
}
@ResponseBody
@PostMapping("/login")
UserDetails userLogin(@RequestBody UserDetail user) {
System.out.println(user.getUsername()+" -- "+user.getPassword());
return user;
}
}
Issue:
I'm getting my React login form successfully whenever I try to access any secure route defined in Spring Controller (don't no its good to use it like it) but whenever I provide the credentials and hit Submit button I'm getting the Cors Error even I mentioned it at Controller Class level.
Also Unable to redirect to secureRoutes
When I try the same with unsecured URLs Cors is working total fine without any issues. So I believe issue is only when working with secure routes.
Is there any mistake done by me when using Spring Security Authentication?
Access to fetch at 'http://localhost:5001/login' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Login.jsx:14
POST http://localhost:5001/login net::ERR_FAILED
formSubmit @ Login.jsx:14
callCallback2 @ react-dom.development.js:4164
invokeGuardedCallbackDev @ react-dom.development.js:4213
invokeGuardedCallback @ react-dom.development.js:4277
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:4291
executeDispatch @ react-dom.development.js:9041
processDispatchQueueItemsInOrder @ react-dom.development.js:9073
processDispatchQueue @ react-dom.development.js:9086
dispatchEventsForPlugins @ react-dom.development.js:9097
(anonymous) @ react-dom.development.js:9288
batchedUpdates$1 @ react-dom.development.js:26179
batchedUpdates @ react-dom.development.js:3991
dispatchEventForPluginEventSystem @ react-dom.development.js:9287
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ react-dom.development.js:6465
dispatchEvent @ react-dom.development.js:6457
dispatchDiscreteEvent @ react-dom.development.js:6430
Show 15 more frames
Show less
Login.jsx:14
Uncaught (in promise) TypeError: Failed to fetch
at formSubmit (Login.jsx:14:27)
at HTMLUnknownElement.callCallback2
You have to enable CORS policy
in your Springboot application. You can do it by using:-
@CrossOrigin
public class ConnTest {
}
Refer this answer for more context: - origin has been blocked by CORS policy Spring boot and React