user9808476
user9808476

Reputation:

django-cors-headers does not allow a request from an allowed origin

The problem that I am facing is that I cannot fetch an existing user from my NextJS frontend. The backend framework that I use is Django (along with the django-cors-headers package). django-cors-headers does not allow a certain HTTP request, while it should.

My next.config.js contains a rewrite, so that I can access my backend.

async redirects() {
    return [
      {
        source: '/api/:path*',
        destination: 'http://localhost:8000/:path*/',
        permanent: true,
      },
    ]
  },

And my django-cors-headers settings look like this:

# CORS

CSRF_TRUSTED_ORIGINS = [
    'http://localhost:3000',
]

CORS_ALLOWED_ORIGINS = [
    'http://localhost:3000',
    'http://localhost:8000',
    'http://127.0.0.1:3000',
    'http://127.0.0.1:8000',
]

CORS_ALLOW_ALL_ORIGINS = True

The request that fails attempts to fetch a user with an ID of 1. This user exists and therefore, this request should succeed.

fetch(`/api/users/${String(userId)}/`, {
    mode: 'cors',
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
    },
  })

However, the only thing that I get back from the request is an error message about CORS.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/users/1.
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
Status code: 301.

It looks like my django-cors-headers setup is wrong. But I am allowed to obtain my JWT tokens. The following request succeeds.

fetch('/api/token', {
    method: 'POST',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      email: mail,
      password,
    }),
  })

Upvotes: 3

Views: 14579

Answers (4)

NadiaNaji
NadiaNaji

Reputation: 31

I have the same problem. I tried to call Django API in react app and this error bugged me for a few days, but I found the solution.

  1. first check all proposed solutions on the web such as: installing corsheaders in Django and adding it in the install app and MIDDLEWARE in setting.py. so next step: Open the network tab in any browser, we have to check two important headers. during the request.
  2. Access-Control-Request-Headers in the request header.
  3. Access-Control-Allow-Headers in the response header.
  4. as you can see in the picture,Access-Control-Request-Headers in the request header is content-type, but Access-Control-Allow-Headers in the response is http://localhost:3000, content-type. So this is the problem.

enter image description here

  1. to resolve the problem go to settings.py in the backend check CORS_ALLOW_HEADERS and delete everything except for 'content-type',. so check again. my bug disappeared.

Upvotes: 3

user9808476
user9808476

Reputation:

I tried pretty much everything EXCEPT for double checking the load order of my middleware... I fixed my issue by going from the following load order

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

... to

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

I knew that it had to be something simple, but now I just feel like a grand idiot...

Upvotes: 8

Toan Quoc Ho
Toan Quoc Ho

Reputation: 3378

With CORS, we have a couple of things that need to be considered. You could find more in here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers, go to Access-Control links.

Your config above, you've set up:

  • CORS_ALLOWED_ORIGINS: http://localhost:8000, ...
  • CORS_ALLOW_METHODS: "DELETE", "GET", "OPTIONS", "PATCH", "POST", "PUT" (default)
  • CORS_ALLOW_CREDENTIALS: False (default)
  • CORS_ALLOW_HEADERS = [ "accept", "accept-encoding", "authorization", "content-type", "dnt", "origin", "user-agent", "x-csrftoken", "x-requested-with", ] (default)

So if your app using credentials, then change CORS_ALLOW_CREDENTIALS to True. If it's still not working, check your request headers, make sure that there are no special headers in there and if you do have special headers on your request, it's better be inside of CORS_ALLOW_HEADERS.

Upvotes: 2

Yilmaz
Yilmaz

Reputation: 49291

This is the settings for django cors headers. in settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # add this 
    'corsheaders',        
]

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

 # set this
 CORS_ALLOW_ALL_ORIGINS=True

Status code: 301 indicates that requested resource is invalid, so the request should be redirected to a proper url. Most likely you are sending request to an invalid endpoint

Upvotes: 0

Related Questions