Home > OS >  Axios post request to route 'appName/v1/users/' (Djoser) throws 401 error but Postman does
Axios post request to route 'appName/v1/users/' (Djoser) throws 401 error but Postman does

Time:12-29

I'm new to Django and trying to build basic user authentication with REST API and a Vue.js frontend. To send the request, I am using axios, which is configured first in a seperate composable axios.js:

import axios from 'axios'

axios.defaults.withCredentials = true
axios.defaults.baseURL = 'http://localhost:8000'

and used inside a register.vue component:

const submitRegistration = () => {
    axios.post('api/v1/users/', {username: 'userName', password: 'userPassword'})
        .then(res => {
            console.log(res)
        })
}

To make it simple, I'm sending a data-object with predefined strings, as you can see above. The request gets sent to one of the djoser routes in projectName/urls.py:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include('djoser.urls')),
    path('api/v1/', include('djoser.urls.authtoken')),
]

This however, throws a 401 Unauthorized Error:

code: "ERR_BAD_REQUEST"
config: {transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …}
message: "Request failed with status code 401"
name: "AxiosError"
request: XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: true, upload: XMLHttpRequestUpload, …}
response: {data: {…}, status: 401, statusText: 'Unauthorized', headers: AxiosHeaders, config: {…}, …}
stack: "AxiosError: Request failed with status code 401\n    at settle (http://localhost:3000/node_modules/.vite/deps/axios.js?v=a45c5ec0:1120:12)\n    at XMLHttpRequest.onloadend (http://localhost:3000/node_modules/.vite/deps/axios.js?v=a45c5ec0:1331:7)"

I've configured settings.py like so:

INSTALLED_APPS = [
    ...,
    'corsheaders',
    'rest_framework',
    'rest_framework.authtoken',
    'djoser'
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ...,
]

CORS_ALLOWED_ORIGINS = ['http://localhost:3000']
CORS_ALLOW_CREDENTIALS = True

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}

Edit:

The problem might be caused by authToken. In the root vue component app.vue, I am checking the store for an authentication token and setting an axios header accordingly:

onMounted(() => {
    if (store.authToken) {
        axios.defaults.headers.common['Authorization'] = `Token ${store.authToken}`
    }
})

If I remove this code, the error turns into 400 BAD_REQUEST. Although I don't understand why one would need an authToken when registering a new user.

store.authToken is set during initialization:

import {reactive} from "vue";

export const store = reactive({
    authToken: localStorage.authToken ?? null,
})

and shoud be null, when a new user is registered.

Edit2:

I followed some advice and used Postman to send the post request to http://localhost:8000/api/v1/users/ and it works. A new user is created.

CodePudding user response:

My authentication check in the vue root component app.vue was flawed:

<script setup>
onMounted(() => {
    if (store.authToken) {
        axios.defaults.headers.common['Authorization'] = `Token ${store.authToken}`
    }
})
</script>

store.authToken always returned true despite being null because it was fetched from localStorage being a string. JSON.parse() solved the problem.

  • Related