reactjs – Cross Origin 403 – No Acces-Controll-Allow-Origin – Failed to fetch

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);
        }
    }

}

Leave a Comment