I can’t get any further. As soon as I try to fill out the form in the React frontend via the “FireFox” browser, the Origin cannot take “localhost:3000” to localhost:8080. I get error 403. Cross origin request is blocked. Despite “Access-Controll-Allow-Origin on *this message comes up.
In Postman Software I can get 200 OK on Post, but as soon as I enter the Origin “localhost:3000” I also get 403
Browser Error
React – api.js
export async function signup(user) {
debugger
const response = await fetch(`${URL}/users/auth/sign-up`, {
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(user)
})
if (!response.ok) {
return Promise.reject(response)
}
return response.json()
}
React – signup.js
import {useRedirectToHome} from "../lib/session";
import {useRouter} from "next/router";
import {useState} from "react";
import {signup} from "../lib/api";
import classes from "../styles/globalClasses.module.css";
import styles from "../styles/login.module.css";
import Link from "next/link";
const defaultModel = {
email: "",
password: ""
}
function validateModel(model) {
const errors = {
email: "",
password: ""
}
let isValid = true;
if (model.email.trim().length === 0 || !model.email.includes("@")) {
errors.email = "E-Mail muss gültig sein!"
isValid = false;
}
if (model.password.trim().length === 0 || model.password.length < 8) {
errors.password = "Das Passwort kann nicht leer sein und muss mindestens 8 Zeichen haben."
isValid = false;
}
return {errors, isValid}
}
export default function SignUpPage({session}) {
useRedirectToHome(session)
const router = useRouter();
const [errors, setErrors] = useState(defaultModel)
const [isLoading, setIsLoading] = useState(false)
const [model, setModel] = useState(defaultModel)
const handleChange = (event) => {
const name = event.target.name;
const value = event.target.value;
setModel({
...model,
[name]: value
})
}
const handleSubmit = async (event) => {
event.preventDefault()
setIsLoading(true)
setErrors(defaultModel)
const result = validateModel(model)
if (!result.isValid) {
setErrors(result.errors)
setIsLoading(false)
return
}
await signup(model)
await router.push(`/users/`)
setIsLoading(false)
}
return (
<div>
<main className={classes.main}>
<h1>Registrieren</h1>
<form onSubmit={handleSubmit}>
<fieldset className={classes.fieldset}>
<label className={classes.label}>E-Mail</label>
<input className={classes.input} placeholder="E-Mail" type="text" name="email"
onChange={handleChange}/>
{errors.email && <p className={classes.errors}>{errors.email}</p>}
</fieldset>
<fieldset className={classes.fieldset}>
<label className={classes.label}>Passwort</label>
<input className={classes.input} placeholder="Passwort" type="password" name="password"
onChange={handleChange}/>
{errors.password && <p className={classes.errors}>{errors.password}</p>}
</fieldset>
<button type="submit" className={classes.grayButton} disabled={isLoading}>
{isLoading ? "Laden..." : "Registrieren"}
</button>
</form>
<div className={styles.signup}>
<p className={styles.p}>Bereits Konto?</p>
<Link href="/login"><p className={classes.a}> Anmelden</p></Link>
</div>
</main>
</div>
)
}
Backend – SecurityConfiguration.java
package ch.bbcag.zubehoermsbackend.configurations;
import ch.bbcag.zubehoermsbackend.security.JWTAuthenticationFilter;
import ch.bbcag.zubehoermsbackend.security.JWTAuthorizationFilter;
import ch.bbcag.zubehoermsbackend.security.UserDetailsServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import static ch.bbcag.zubehoermsbackend.security.SecurityConstants.API_DOCUMENTATION_URLS;
import static ch.bbcag.zubehoermsbackend.security.SecurityConstants.SIGN_UP_URL;
import java.util.List;
@Configuration
@EnableWebSecurity(debug = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserDetailsServiceImpl userDetailsService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public SecurityConfiguration(UserDetailsServiceImpl userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
.antMatchers(HttpMethod.OPTIONS, SIGN_UP_URL).permitAll()
.antMatchers(HttpMethod.GET, API_DOCUMENTATION_URLS).permitAll()
// .anyRequest().permitAll().and() // TODO
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
// this disables session creation on Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("*"));
configuration.setAllowedMethods(List.of("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Backend – UserController.java
package ch.bbcag.zubehoermsbackend.controllers;
import ch.bbcag.zubehoermsbackend.data.dtos.UserSignUpDTO;
import ch.bbcag.zubehoermsbackend.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import javax.validation.Valid;
import java.util.NoSuchElementException;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public ResponseEntity<?> findAll() {
return ResponseEntity.ok(userService.findAll());
}
@GetMapping(path = "{nfcSerialNumber}")
public ResponseEntity<?> findBySerialNumber(@PathVariable String nfcSerialNumber) {
try {
return ResponseEntity.ok(userService.getBySerialNumber(nfcSerialNumber));
}
catch (NoSuchElementException e) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Item could not be found");
}
}
@PostMapping(value = "/auth/sign-up0", consumes = "application/json")
public ResponseEntity<?> signUp(@Valid @RequestBody UserSignUpDTO userSignUpDTO) {
try {
return ResponseEntity.ok(userService.create(userSignUpDTO));
}
catch (DataIntegrityViolationException e) {
throw new ResponseStatusException(HttpStatus.CONFLICT, "User could not be created, email already in use");
}
} @PostMapping(value = "/auth/sign-up", consumes = "application/json")
public ResponseEntity<?> signUp() {
try {
return ResponseEntity.ok("test");
}
catch (DataIntegrityViolationException e) {
throw new ResponseStatusException(HttpStatus.CONFLICT, "User could not be created, email already in use");
}
}
}
Backend – JWTAuthenticationFilter.java
package ch.bbcag.zubehoermsbackend.security;
import ch.bbcag.zubehoermsbackend.data.entities.User;
import com.auth0.jwt.JWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import static ch.bbcag.zubehoermsbackend.security.SecurityConstants.*;
import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException {
try {
User creds = new ObjectMapper()
.readValue(req.getInputStream(), User.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
creds.getEmail(),
creds.getPassword(),
new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain,
Authentication auth) {
String token = JWT.create()
.withSubject(((org.springframework.security.core.userdetails.User) auth.getPrincipal()).getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.sign(HMAC512(SECRET.getBytes()));
res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
try {
res.setContentType("application/json");
res.getOutputStream().print("{"" + AUTH_RESPONSE_ATTRIBUTE_NAME + "":"" + TOKEN_PREFIX + token + ""}");
res.getOutputStream().flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}