I run a ReactJS front end application and Django REST back end/API both on the same webhost. The application works perfectly fine on localhost, however when you run it from somewhere else it can't seem to connect to the API.
Console of client's browser:
Django REST running on the server:
Am I supposed to connect to it using the external IP of the server instead of localhost? Localhost should work right, since both the frontend and Django API are hosted on the same server?
before fetch the django rest_api, make sure you setup django-cors-headers in your backend settings.py. for more information take a look at this link.
pip install django-cors-headers
settings.py :
INSTALLED_APPS = [
...
'corsheaders',
...
]
MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware',
'corsheaders.middleware.CorsPostCsrfMiddleware',
...
]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = [
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
]
In case someone is looking for an answer, I've learned a few things since posting:
The Django API has to be accessed by the IP, not localhost.
Since my website is on HTTPS, Django has to be accessed by HTTPS as well or it won't work.
Since Django runserver doesn't support HTTPS you need to host it with a webserver (you should do this anyway in production), I used Apache for this.
Thanks to xxnora for giving me tips and steering me in the right direction.
Related
I made Django Backend. and Next.js Frontend. There is cookie which has _ga, csrftoken when I tested on local server 127.0.0.1.
BUT, there is no cookie at all on my production (which has different domain backend and frontend).
I guessed that everything happened because I used different domain when production. Here is some django settings.py I have
ALLOWED_HOSTS = [
"127.0.0.1",
"localhost",
"BACKENDURL",
"FRONTENDURL",
"*.FRONTENDURL",
]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
CSRF_TRUSTED_ORIGINS = [
"http://127.0.0.1:3000",
"http://localhost:3000",
"https://*.frontendURL",
"https://FRONTENDURL",
]
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
For the future visitors...
I figured out what I was wrong.
In Development Settings,
I use same domain
[127.0.0.1:3000] as frontend (Next.JS)
[127.0.0.1:8000] as backend (Django)
But, In Production Settings,
I use different domain
[frontend.com] as frontend
[backend.com] as backend
Which leads "cross-site" error on request/response.
I also found that there is no cookie in my production
due to I use different domain in production
Different domain cannot use same cookie => No Cookie on the frontend.
Thus, I have to set the domain same on backend and frontend in 'hosting service site'
www -> frontendurl
backend -> backendurl
=> Then I can get the csrftoken and sessionid when login.
Also, I made my settings.py in django project including...
SESSION_COOKIE_DOMAIN = ".mydomain"
CSRF_COOKIE_DOMAIN = ".mydomain"
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_ALL_ORIGINS = True
I recognize that CORS_ALLOW_ALL_ORIGINS leads some danger...
I set it just to confirm that everything is fine.
Later on, In production, change it into
CORS_ALLOWED_ORIGINS = [...]
Hope my answer helped someone.
Happy Hacking my friends. Good Luck!
Current Setup: I've got a Django application behind gunicorn running on Cloud Run. Since the region it is deployed in does not support Custom Domains, I have a firebase hosting setup with the following code:
{
"hosting": {
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [{
"source": "/**",
"run": {
"serviceId": "website",
"region": "ap-south1"
}
}]
}
}
The relevant settings in settings.py:
CSRF_TRUSTED_ORIGINS = ['.<domain>.com']
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
The problem: However, the login form on /admin does not work if I access the site using my domain name https://doman.com/admin even though it works fine if I use the Cloud Run endpoint https://endpoint-uw.a.run.app.
Faulty behaviour: When accessing it from my domain, the login page shows up, I enter my credentials and log in, it adds the relevant cookies to my browser but then it redirects me back to the login page.
Could it be that since the URL is being rewritten by firebase django is expecting a cookie from uw.a.run.app? I tried adding the setting SESSION_COOKIE_DOMAIN = '.<domain>.com' but that did not fix it either, it just made the Cloud Run endpoint stop working as well.
Any advice on how to fix this or how to diagnose what is going wrong would be much appreciated, thanks!
The relevant settings in settings.py:
SESSION_COOKIE_NAME = "__session"
as firebase send cookie in the name "__session"
I made an Angular application able use an online api to get a json and do stuff.
But, although the json is the same, if I try to change only the url of the json by setting a local url of a server written in django, angular would seem not to connect anymore ...
My question is, why if with an online cloud server works, with a local one wouldn't?
I tried making this server "on cloud" opening the router's port, also setting up a ddns, and using postman or a browser it seems to work, but when i try to connect with angular it still doesn't get the data...
I am sure 100% that the server answer, with the right json data, because django prints on console that he received a HTTP GET request :
http://i.imgur.com/TIQnIcR.png
I remind you that the HTTP angular request worked with another api, but i will still show up some code :
export class ProdottoService {
private prodotti: Array<ProdottoModel>;
constructor(private httpClient: HttpClient) {
this.prodotti = new Array<ProdottoModel>();
var url:string = "https://gist.githubusercontent.com/saniyusuf/406b843afdfb9c6a86e25753fe2761f4/raw/523c324c7fcc36efab8224f9ebb7556c09b69a14/Film.JSON";
var local_url:string = "http://127.0.0.1:8000/films/?format=json";
httpClient.get(local_url)
.subscribe((films : Array<Object> ) => {
films.forEach((film => {
this.prodotti.push(new ProdottoModel(film));
}));
}
);
}
getProdotti(): Array<ProdottoModel> {
return this.prodotti;
}
}
Result using external api :
http://i.imgur.com/MT7xD9c.png
Thanks in advace for any help :3
-- EDIT -- IS A CORS ISSUE
In django settings.py file :
CORS_ORIGIN_WHITELIST = (
'localhost:8000',
'127.0.0.1:4200'
)
INSTALLED_APPS = (
...
'corsheaders',
...
)
MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
But i don't know if there's a way to set-up CORS settings in Angular
Based on feedback, this is a CORS issue. Your Django server is getting the requests and responding because localhost is an implicitly trusted domain in Django's dev environment, but it isn't configured properly to set the cross origin header, so the browser is not allowing your app to see the response because the server hasn't authorized the domain explicitly.
The problem here is that you've set CORS white list like this:
CORS_ORIGIN_WHITELIST = ( 'localhost:8000', '127.0.0.1:4200' )
it needs to be like this:
CORS_ORIGIN_WHITELIST = ( 'localhost:4200' )
angular runs on localhost, not 127.0.0.1, even though that's what localhost is an alias for, your browser still differentiates them for CORS. Also, you do not need to whitelist the domain your serving off of, that's not crossing any origin as it's the same origin.
In your screenshot, it looks like the response is type "document..." something. The simplest fix, with only the code here, is to convert the string to JSON.
JSON.parse(films)
This is the wrong answer, because it's being set to that because of the CORS issue in the other answers.
I have a django api (djangorestframekwork, django2.1, python 3.6) that I run locally - http://127.0.0.1:8000/api/cards/b361d7e2-6873-4890-8f87-702d9c89c5ad. This api seems to work well. I can hit it via the web api or use curl/requests to add to or view the database.
Now, I want to be able to have my React project hit this api. I can have my react project hit a different api and it returns the data, but when I replace that URI with my own URI it breaks.
App.js - there is one line commented out. Switch that out with the other to switch between the public and private api.
import React from 'react'
import keyforge from '../api/keyforge'
import localhost from '../api/localhost'
import SearchBar from './SearchBar'
class App extends React.Component {
onSearchSubmit = async (term) => {
const response = await localhost.get("api/cards/" + term)
//const response = await keyforge.get("api/decks/" + term)
console.log(response)
}
render () {
return (<div className='ui container'>
<SearchBar onSubmit={this.onSearchSubmit} />
</div>)
}
}
export default App
keyforge.js - this one works!
import axios from 'axios'
const proxyurl = 'https://cors-anywhere.herokuapp.com/'
const url = 'https://www.keyforgegame.com/'
export default axios.create({
// baseURL: 'https://www.keyforgegame.com/api/decks/'
baseURL: proxyurl + url
})
localhost.js - this one does not work
import axios from 'axios'
const proxyurl = 'https://cors-anywhere.herokuapp.com/'
const url = 'http://127.0.0.1:8000/'
export default axios.create({
baseURL: proxyurl + url
})
Error message:
GET https://cors-anywhere.herokuapp.com/http://127.0.0.1:8000/api/cards/b361d7e2-6873-4890-8f87-702d9c89c5ad 404 (Not Found)
Uncaught (in promise) Error: Request failed with status code 404
at createError (createError.js:17)
at settle (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:78)
On my computer - http://127.0.0.1:8000/api/cards/b361d7e2-6873-4890-8f87-702d9c89c5ad takes me to the Django api page for that specifc element. If I get rid of the cors-anywhere url I get this error -
Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/cards/b361d7e2-6873-4890-8f87-702d9c89c5ad' from origin 'http://127.0.0.1:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have this cors-anywhere url prepended to it to solve the No Access-Control-Allow-Origin error that you see when I hit this to the public api. Since I get the same error when I hit my own private api, I am using the same solution (e.g. the cors-anywhere url prepeneded to my url.
Thoughts?
Probably because you didn't enabled CORS on your django rest project. There is a tool called django-cors-headers, Install it via pip install django-cors-headers, add it's midlleware and enable it in your settings.py file.
pip install django-cors-headers
then add it to installed apps:
INSTALLED_APPS = (
...
'corsheaders',
...
)
add it's middleware:
MIDDLEWARE_CLASSES = (
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
)
and finally add this variable in the end of your settings.py file:
CORS_ORIGIN_ALLOW_ALL = True
Find out more about it here: django-cors-headers on github
Your keyforge.js file works because you're hitting an already hosted website which has CORS enabled at it's backend as well. You need to add CORS at your Django backend as well. From what you've said, it seems that you've only added it at the front end. Probably something like could help you.
How can I enable CORS on Django REST Framework
This is my first post, and I have a problem I could not make it work django OMAB socialauth of three things I just need to google, facebook, and twitter, google works well with open id, but not much twitter and I put in my
settings. py:
TWITTER_CONSUMER_KEY = '00' this is no real
TWITTER_CONSUMER_SECRET = '00' this is no real
FACEBOOK_APP_ID = '' ihave no key
FACEBOOK_API_SECRET = ''
LINKEDIN_CONSUMER_KEY = ''
LINKEDIN_CONSUMER_SECRET = ''
ORKUT_CONSUMER_KEY = ''
ORKUT_CONSUMER_SECRET = ''ihave no key
GOOGLE_OAUTH2_CLIENT_ID = ''
GOOGLE_OAUTH2_CLIENT_SECRET = ''
SOCIAL_AUTH_CREATE_USERS = True
SOCIAL_AUTH_FORCE_RANDOM_USERNAME = False
SOCIAL_AUTH_DEFAULT_USERNAME = 'socialauth_user'
SOCIAL_AUTH_COMPLETE_URL_NAME = 'socialauth_complete'
LOGIN_ERROR_URL = '/login/error/'
#SOCIAL_AUTH_USER_MODEL = 'app.CustomUser'
SOCIAL_AUTH_ERROR_KEY = 'socialauth_error'
GITHUB_APP_ID = ''
GITHUB_API_SECRET = ''
FOURSQUARE_CONSUMER_KEY = ''
FOURSQUARE_CONSUMER_SECRET = ''
LOGIN_URL = '/login-form/'
LOGIN_REDIRECT_URL = '/'
LOGIN_ERROR_URL = '/login-error/'
I am using the example that comes in the zip of OMAB socialauth django , but not working.
When I created my twitter app, I wrote my domain www.sisvei.com , I am testing locally socialauth django ie 127.0.0.1:8000, then sign in with twitter sends me to this url:
http://127.0.0.1:8000/login/error/ and a message saying is the Incorrect authentication service
this happens with facebook and google oauth and oauth2
I'm new to django and I this much work comprising this part of django socialath hopefully help me, thank you very much.
You need to be more specific on "why it doesn't work". Where are you getting the errors?
When debugging a third-party oauth/openid app in Django, generally it boils down to:
configuration & keys - did you make sure to obtain all of the necessary API keys for the services you will be using, and to add them to your configuration?
urls - did you remember to add the necessary urlpatterns to your base urls.py file?
authentication setup on the server - often, you'll need to have a file available or respond with a specific header when the authentication service hits your server. Have you checked to make sure that is set up?
databases - have you run syncdb after installing the app? Are all the tables set up?
templates - if the third party app requires you to set up templates, do you have them set up?
custom views - are you using custom views? If so, try using the built-in views that came with the third party app first, to see if they work
After those are confirmed, you're going to want to be able to see what requests are taking place. Use the debugger included in Chrome/Safari, or get the web developer add-on for Firefox, and look at the network requests as they happen. Do you see HTTP responses other than 200 (say, 404, 500, 403, etc?) those mean that the services aren't responding correctly.
From your error, it looks like you have not correctly set up your callback URL on Twitter. It should be sending you to www.sisvei.com, not 127.0.0.1. Alternatively, check the URL when you get to the Twitter login page -- is the callback URL in the URL, and is it pointing to 127.0.0.1? Then Django is sending it the wrong callback URL.
Finally this:
I wrote my domain www.sisvei.com python does not support this
Is unclear. As far as I know, Python doesn't care what the domain is.
WAIT A MINUTE ...
Are you using runserver? Are you getting the following error?
Error: "www.sisvei.com" is not a valid port number or address:port pair.
If so, there is an easy fix! Just run it like so:
python manage.py runserver www.sisvei.com:80
That should resolve your error if that's what's happening. You're probably running it as
python manage.py runserver 127.0.0.1
127.0.0.1 is a reserved IP address that points back to localhost, your own computer. As a result, it is not possible to use it for authentication or any other purpose outside of programs running on your own machine. See this article for more info.
I'm not sure, but I might be having similar problems, oscar. For me, SocialAuth was generating an AuthenticationURL for facebook, foursquare and hotmail, but not for google, twitter or any of the other address it supports. I think it may be something wrong with the API, so I posted an issue on the social-auth google group...you may want to check there to see if anyone updates!!
https://code.google.com/p/socialauth/issues/detail?id=282&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Summary%20Modified