Home > OS >  First django rest api call returns request.user as AnonymousUser but further calls return proper use
First django rest api call returns request.user as AnonymousUser but further calls return proper use

Time:11-29

right now I have an api view that requires knowing which user is currently logged in. When I try to call it with a logged in user; however, it returns anonymous user. The odd thing is that if I call the api view again, it returns the proper user. I am using django rest framework and JSON Web Tokens with simplejwt. Right now the call in ReactJS looks like this:

const fetchAuthorData = () => {
        axiosInstance.get('authors/')
        .then((res) => {
            setAuthor(res.data)
        }).catch((err) => {
            fetchAuthorData()
        })
        
        fetchAuthorThreads()
        fetchAuthorArticles()
    }

However, I know recursively calling this over and over is very dangerous, because even though I redirect if the user is actually not logged in before this recursive api call, if somehow that fails my server will be overloaded with api calls. Does anyone know how I could make it so that my api actually properly identifies on the first call whether the user is logged in?

Here is my login view:

axiosInstance.post('author-auth/token/', {
                email: formData.email,
                password: formData.password,
            }).then((response) => {
                localStorage.setItem('access_token', response.data.access)
                localStorage.setItem('refresh_token', response.data.refresh)
                axiosInstance.defaults.headers['Authorization'] = 
                    'JWT '   localStorage.getItem('access_token')
                    history.push('/')
            }).catch((err) => {
                alert("Make Sure Login Credentials Are Correct")
            })

Here is the faulty view:

@api_view(['GET'])
def author(request):
    print(request.user)
    if request.user.is_authenticated:
        author = request.user
        serializer = AuthorAccessSerializer(author, many=False)
        return Response(serializer.data)
    else:
        return HttpResponse(status=400)

In this, request.user is an anonymous user even though I am logged in

Here is a similar part of another view that works oddly

@api_view(['GET', 'POST'])
def articles(request):
    if request.method == 'GET':
        category_name = request.query_params['category']
        dash = request.query_params['dash']
        #this part is very similiar and works for some reason
        if dash == "True":
            if request.user.is_authenticated:
                articles = Article.objects.filter(author=request.user)
            else:
                return HttpResponse(status=401)
        # *end part*
        elif category_name:
            try:
                category = Category.objects.get(name__icontains=category_name)
            except:
                return HttpResponse(status=400, content="Category not found")
            articles = Article.objects.filter(category=category)
        else:
            articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        
        return Response(serializer.data)

Here are my axios settings:

export const axiosInstance = axios.create({
    baseURL: baseURL,
    timeout: 5000,
    headers : {
        Authorization: localStorage.getItem('access_token')
            ? 'JWT'   localStorage.getItem('access_token')
            : null,
        'Content-Type' : 'application/json',
        accept : 'application/json'
    }
})

And here are my rest framework and JWT auth settings:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny'
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(hours=5),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
    'ROTATE_REFRESH_TOKENS': False,
    'BLACKLIST_AFTER_ROTATION': True,
    'UPDATE_LAST_LOGIN': False,

    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,
    'AUDIENCE': None,
    'ISSUER': None,
    'JWK_URL': None,
    'LEEWAY': 0,

    'AUTH_HEADER_TYPES': ('Bearer', 'JWT'),
    'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',
    'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',

    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',

    'JTI_CLAIM': 'jti',

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}

ALLOWED_HOSTS=['127.0.0.1', 'http://localhost:5000']
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
    'http://localhost:3000',
) 

Again, if I keep calling the same api call, it works for some reason not changing any authorization headers, tokens, or anything else and request.user works fine with the second view I have above. Can anyone tell me why this is happening?

CodePudding user response:

I think,

                1. localStorage.setItem('access_token', response.data.access)
                2. localStorage.setItem('refresh_token', response.data.refresh)
                3. axiosInstance.defaults.headers['Authorization'] = 
                    'JWT '   localStorage.getItem('access_token')
                    history.push('/')

on login code may cause problem.

These code never run sequentially; every javascript run asynchronously.

It means, your axiosInstance.defaults.headers could be null because, 1, 2 and 3 lines are executed at once. In other words, axiosInstance.defaults.headers become null (as there is no access_token on localStorage) then, Js set access_token from response.data.access.

You'd better use promise with .then() after 1 and 2 line, or fetch Authorization of axiosInstance when make http request.

  • Related