1

I have developed some API functions in Django REST framework, and now I want to develop some client forms / API calls to match. OK, the REST API is available at locally after entering the command:

python3 manage.py runserver

I put together some HTML and JavaScript / jquery.rest, so the client can call a (authorization) end point with the following function linked to an onclick event:

function auth()
{
  var client = new $.RestClient('http://127.0.0.1:8000/auth/');
  client.add('token');

  var client_id = 'xxx...etc';
  var client_secret = 'yyy...etc';
  var username = $('.inputUsername').val();
  var password = $('.inputPassword').val();

  request = client.token.create({
    client_id: client_id,
    client_secret: client_secret,
    grant_type: 'password',
    username: username,
    password: password
  });

  request.done(function (data, textStatus, xhrObject){
    alert('I have data: ' + data);
  });
  return false;
}

Firstly, perhaps naively, I opened the HTML file in a browser, to test out this client function, but Django refused the request with the error:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/auth/token/. (Reason: CORS header 'Access-Control-Allow-Origin' missing).

Then I thought that if I served up the page locally using Apache (with the Django server still in development mode) then the origins would at least be the same, but that gave the same error. I'm guessing that this is because of the different ports. I'm aware that it is possible to set Django so that other origins are allowed, however I'm confused as to how this would work if the client was a web based phone app for example. Wouldn't it be best if the pages were stored locally on the phone (perhaps encrypted), rather than at a different domain or would that be insecure? What is the common solution to this problem?

(Update) I installed the middleware with:

pip install django-cors-headers

...and edited settings.py:

INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
)

CORS_ORIGIN_WHITELIST = (
    'localhost',
)

Nothing appears in the console now, but Django REST framework still refuses the request:

[07/Mar/2016 23:07:00] "POST /auth/token/ HTTP/1.1" 401 27
gornvix
  • 3,154
  • 6
  • 35
  • 74
  • Possible duplicate of [How can I enable CORS on my Django REST Framework](http://stackoverflow.com/questions/35760943/how-can-i-enable-cors-on-my-django-rest-framework) – rnevius Mar 03 '16 at 16:53
  • I'm also asking about storing the client HTML files locally. – gornvix Mar 08 '16 at 14:57
  • Have you tried `CORS_ORIGIN_ALLOW_ALL = True`? Does the browsable api work? – ilse2005 Mar 08 '16 at 15:22
  • I tried the CORS_ORIGIN_ALLOW_ALL setting, still Django refuses the request. The browsable API has long been broken, I forget what package broke it. I can however go to the simplest end point in the API no problem: http://localhost:8000/ping – gornvix Mar 08 '16 at 16:11
  • Also I can access any part of the API with the curl command. – gornvix Mar 08 '16 at 16:18
  • 1
    Ah, I made a mistake I was using the wrong username / password. Now I get a bad request response: [08/Mar/2016 16:59:36] "POST /auth/token/ HTTP/1.1" 400 91. So I guess the CORS middleware is now working and my problem now lies in the setting up of the request. – gornvix Mar 08 '16 at 17:07

1 Answers1

2

I think the usual way is that your backend (api) will run on a separate server than your frontend and you make CORSCORS requests. Therfore you have to set the CORS-Header correctly. This is quite simple using django-cors-headers.

#settings.py
INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
)

CORS_ORIGIN_ALLOW_ALL = True  # allows all 
# or use whitelist:
CORS_ORIGIN_WHITELIST = (
    'google.com',
    'hostname.example.com'
)

If you develop for a website only, you could run frontend and backend on the same server. but if you develop a mobile app you can't install and run django on the phone.

ilse2005
  • 11,189
  • 5
  • 51
  • 75
  • I tried this but I still the request is refused by Django REST framework. See the update section on my post! – gornvix Mar 08 '16 at 14:30