I have implemented Django backend for Google OAuth2 signin/signup process for user authorization.
The mechanism is triggered from React UI.
The user can successfully signup using Django backend and I can see the associated users are created in Django Admin.
However, when I try to use the same user information through React UI, "me" API call cannot access to the Django user that has signed in. But direct Django call through browser and curl command works fine.
The following command works fine with backend call :
curl -X GET --header "Cookie: csrftoken=M1kFFNataWZcbckfdrqUEiXuRRsSRwYKKCH4XvENUyWnLE9xnSMHe7DiaUcDBRU6; sessionid=p156z2d5gy9cwamojxvmxbopg84p99v6" http://localhost:8000/registration/me/
Below is Django settings for Cors and CSRF :
CORS_ORIGIN_ALLOW_ALL = True
ALLOWED_HOSTS = ['*']
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
]
CORS_ALLOW_ALL_ORIGINS=True
CORS_ALLOW_CREDENTIALS = False
CORS_ORIGIN_WHITELIST = [
'http://localhost:3000'
]
CSRF_COOKIE_NAME = "csrftoken"
CSRF_COOKIE_HTTPONLY = False
CORS_EXPOSE_HEADERS = ["Content-Type", "X-CSRFToken"]
CORS_ALLOW_CREDENTIALS = True
CSRF_COOKIE_AGE = None
CSRF_COOKIE_DOMAIN = 'localhost'
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SECURE = True
CSRF_USE_SESSIONS = True
Below is rest framework settings :
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
'DEFAULT_PERMISSIONS_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
The API call from Django for "me" :
@api_view(['GET'])
def current_user(request):
from rest_framework.permissions import IsAuthenticated
permission_classes = [IsAuthenticated]
user = request.user
if user.is_authenticated:
return Response({
'username' : user.username,
'email' : user.email,
'firstname' : user.first_name,
'lastname' : user.last_name,
'picture' : user.picture,
'email_verified' : user.email_verified,
'locale' : user.locale,
'token' : user.token
})
return Response({'user' : 'anonymous'})
Below is the Axios call :
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
console.log("COOKIE : " + document.cookie);
var cookieValue = document.cookie
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken').split("=")[1];
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";
axios({
method: 'get',
url: 'http://localhost:8000/registration/me/',
data: {
csrfmiddlewaretoken: csrftoken,
'Authentication' : "Token " + csrftoken,
},
headers: {
"Content-Type": "X-CSRFToken",
'X-CSRFTOKEN' : "M1kFFNataWZcbckfdrqUEiXuRRsSRwYKKCH4XvENUyWnLE9xnSMHe7DiaUcDBRU6",
},
withCredentials: false,
xsrfHeaderName: 'X-CSRFToken',
xsrfCookieName: 'csrftoken',
}).then(res => {
resultState.state = 'success';
resultState.data = res.data;
console.log("registration/me success : " + JSON.stringify(resultState.data));
}).catch((err) => {
resultState.state = 'error';
resultState.data['message'] = err.message;
console.log("registration/me error : " + JSON.stringify(resultState.data));
})
The react response for the Django call is as below :
API_SETTINGS.JWT_AUTH_COOKIE : Cookie
API_SETTINGS.JWT_AUTH_COOKIE : 0:05:00
API_SETTINGS TOKEN : eyJ0eXAiOiJK...
API_SETTINGS.JWT_AUTH_COOKIE : Cookie
API_SETTINGS : <rest_framework.settings.APISettings object at 0x10e7f9300>
jwt_login : <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="http://localhost:3000">
RESPONSE : <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="http://localhost:3000">
[24/Jun/2022 21:02:27] "GET /api/v1/oauth/google/?code=4/0AX4XfWgL1FkFt3-21eIbY3MEi3WGqwkEBYcU4KXE5Rdw7LwwAG5__XgqVD4r0F6ApYpJVQ&scope=email%20profile%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile%20openid&authuser=3&hd=supereye.co.uk&prompt=none HTTP/1.1" 302 0
[24/Jun/2022 21:02:46] "GET /registration/me/ HTTP/1.1" 200 7613
[24/Jun/2022 21:02:47] "GET /static/rest_framework/css/bootstrap.min.css.map HTTP/1.1" 404 1746
[24/Jun/2022 21:07:56] "GET /registration/me/ HTTP/1.1" 200 20
[24/Jun/2022 21:07:56] "GET /registration/me/ HTTP/1.1" 200 20
registration/me success : {"user":"anonymous"}
React output for "me" call in Developer Console is below :
I can provide any further information regarding the setup. Any suggestions would be appreciated.
Actually, everything that is required was in place, only setting the parameter "withCredentials : true" was sufficient. The page already knew the cookie / associated user, but axios was not using the cookie information automatically.
Adding parameter as below was sufficient :
axios({
method: 'get',
url: 'http://localhost:8000/registration/me/',
withCredentials: true,
}).then(res => {
resultState.state = 'success';
resultState.data = res.data;
}).catch((err) => {
resultState.state = 'error';
resultState.data['message'] = err.message;
})