Forbidden 403 frontend react with django python backend

32 Views Asked by At

I need help with this error

This is a message from the backend:

Forbidden (Origin checking failed - http://localhost:3000 does not match any trusted origins.): /user/login/
[04/Mar/2024 18:17:23] "POST /user/login/ HTTP/1.1" 403 2568

This is mi react config for axios:

import axios from 'axios';


export const setCSRFToken = async () => {
    try {
        const response = await instance.get('/user/getCSRFToken/');
        const csrfToken = response.data.CSRFToken;
        instance.defaults.headers.common['X-CSRFToken'] = csrfToken;
        console.log(csrfToken)
        console.log('Headers actualizados:', instance.defaults.headers);
        axios.defaults.withCredentials = true;
    } catch (error) {
        console.error('Error al obtener el token CSRF:', error);
    }
};

export const instance = axios.create({
  baseURL: 'http://127.0.0.1:8000',
  timeout: 5000, // tiempo de espera de 5 segundos
  headers: {
    'Content-Type': 'application/json',
  },
});


// Llama a la función setCSRFToken para configurar el token CSRF al crear la instancia de Axios
setCSRFToken();

This my settings.py:

from pathlib import Path

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'products.apps.ProductsConfig',
    'user.apps.UserConfig',
    'partners.apps.PartnersConfig',
    'corsheaders',
    'django_cleanup.apps.CleanupConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'Registro.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Registro.wsgi.application'

# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'registro',
        'USER': 'root',
        'PASSWORD': 'Password*',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

AUTH_USER_MODEL = 'user.User'

# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Configuracion de CORS
CORS_ALLOWED_ORIGINS = (
    'http://localhost:3000',
)

# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

And this is my login:

import React, { useState } from 'react';
import { Link, redirect }   from 'react-router-dom';
import { Footer } from '../components/footer.js';
import { ButtonHideShow } from '../components/button-hide-show.js';
import '../stylesheets/login-register.css';
import { FaGoogle } from "react-icons/fa";
import { FaFacebook } from "react-icons/fa";
import { instance } from '../components/axios-config.js';
import axios from 'axios';


export const Login = () => {
    const [user, setUser] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState('');
    const [showPassword, setShowPassword] = useState(false);
    const [loggedIn, setLoggedIn] = useState(false);

    //Configuracion para importar los datos de inicio de sesión
    const handleLogin = async (e) => {
        e.preventDefault();

        try {
            const response = await instance.post('/user/login/', { user, password });
            console.log(response.data);
            setLoggedIn(true)
        } catch (error) {
            console.error('Error al iniciar sesión', error);
            setError('Usuario o contraseña incorrectos');
        }
    };

    if(loggedIn) {
        return redirect('/');
    };

    //Función para alternar la visibilidad de la contraseña
    const togglePasswordVisibility = () => {
        setShowPassword(!showPassword);
    };
    

    return (
        <div className='login-form'>
            <form className='container-login'>
                <h2>Inicio de Sesión</h2>
                <h3>Ingresa tus datos de inicio de sesión</h3>
                <input type='text' 
                placeholder='Escribe tu usuario' 
                className='user-dates' 
                value={user} 
                onChange={(e) => setUser(e.target.value)} 
                required />
                <div className='input-password'>
                    <input type={showPassword ? 'text' : 'password'}
                    placeholder='Escribe tu contraseña' 
                    className='user-dates' 
                    id='input-password'
                    value={password}
                    onChange={(e) => setPassword(e.target.value)}
                    required />
                    <ButtonHideShow handleClick={togglePasswordVisibility} showPassword={showPassword}/>
                </div>
                <div className='container-access'>
                    <div className='remember-me'>
                        <input type='checkbox' className='check-login'></input>
                        <p className='login-paragraph'>Recuérdame</p>
                    </div>
                    <Link to='/' style={{textDecoration:'none'}} className='login-paragraph'>¿Olvidaste tu contraseña?</Link>
                </div>
                <p style={{ color: 'red' }}>{error}</p>
                <button type='button' onClick={handleLogin} className='btn-sign-in'>Iniciar Sesión</button>
                <p className='login-paragraph-2'>O inicia sesión con:</p>
                <div className='container-btn-login-with'>
                    <button className='btn-login-with'><FaGoogle />Google</button>
                    <button className='btn-login-with'><FaFacebook />Facebook</button>
                </div>
                <p className='create-account'>¿Aun no tienes una cuenta? <Link to='/register' style={{textDecoration:'none'}} className='register-now'>Regístrate ahora</Link></p>
            </form>
            <Footer />
        </div>
    );
};

I already tried to implement a get request to a view with csrf_exempt, extract the token and use it when sending http requests, configure CORS_ALLOWED_ORIGINS to allow sending requests from 'http://localhost:3000' and I don't know any other solution

1

There are 1 best solutions below

1
Spike Vinalyan On

Idk why is the exact root of your problem, but is obviously a CORS problem, what is a realheadache to config to develop a frontend served by another server in port 3000. I set this in my dev.py (which extends the base settings .py) to avoid this. Do not use this in prod, in prod is better to build the front and serve it like a static .js and in this way you do not have problems with CORS, because de front is served by the same server like the back.

# Para que Django nos deje acceder desde el Dev Server de React, es necesario añadir:
CORS_ALLOWED_ORIGINS = (
    'http://localhost:3000', 'http://127.0.0.1:3000',
)
CSRF_TRUSTED_ORIGINS = ['http://localhost:3000', 'http://127.0.0.1:3000', ]
INSTALLED_APPS += ('corsheaders',)
MIDDLEWARE += ['corsheaders.middleware.CorsMiddleware',]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True