I am having some problems on the authentication part for my Django app, using a CustomUser. The logic is the following: I need to send credentials (email/password) to an external API, from which I retrieve the access token which will be used on the later requests. During the process, I also create (or update, if it's already there) a CustomUser inside my local db, with the same credentials as in the external database. Then I try to authenticate the user in my app with the same credentials.
Below the relevant parts of code:
models.py:
class CustomUser(AbstractUser):
email = models.EmailField("Email", max_length=255, unique=True, null=True)
custom_user_id = models.IntegerField("Custom user id", unique=True, null=True)
name = models.CharField("Name", max_length=255, null=True)
initials = models.CharField("Initials", max_length=255, null=True)
views.py
from django.contrib.auth import login as auth_login
@api_view(['POST'])
@never_cache
def user_login(request):
''' User login '''
if request.method == 'POST':
url = "THE EXTERNAL API"
payload = {
'email':request.data['email'],
'password':request.data['password']
}
headers = {
'Origin': 'REDACTED',
'Content-Type': 'text/plain'
}
email = request.data['email']
username = email
password = request.data['password']
payload = '{"email":"' + email + ',"password":"' + password + '}'
r = requests.post(url, data = payload, headers=headers)
if r.status_code == 200:
data = r.json()
# Get user // create one if it doesn't exist yet
user, created = CustomUser.objects.update_or_create(
custom_user_id = data['data']['uid'],
defaults = {
'username': username,
'initials': data['data']['initials'],
'email': data['data']['email'],
'name': data['data']['name']
})
#trying to login user
auth_login(request, user)
request.session['access_token'] = data['data']['access_token']
First all, this code works perfectly fine when I run the app in local - in fact I can see that request.user correctly stores the logged user inside any other views, and the @login_required decorator works as expected.
The problems arise when I run the same app on my deployed version (aws ec2 with nginx). In this case, 'request.user' contains the correct user only inside this login view. But if I print request.user in any other view, it actually returns AnonymousUser, as if the auth_login function has actually failed.
As a result, the @login_required decorathor no longer works properly (because request.user does not contain the authenticated user). Strangely, its counterpart for class-based view (LoginRequiredMixin) works perfectly fine instead (not sure if they look at different things?), however I have a mix of function-based and class-based views in my app and I can't convert everything into class-based view (also I'd like to solve the issue at the root).
Another strange thing is, despite the fact that request.user contains AnonymousUser, request.session contains the right credentials of the user (for example I'm able to retrieve the ID of the logged user with request.session['_auth_user_id']
If the authentication has failed, then why request.session correctly contains the information about the logged user?
I also tried the following, based on the answer on a similar question on SO:
from django.contrib.auth import authenticate
user = authenticate(username=username, password=password)
However it didn't solve anything.