Ошибка Bad Request при попытке обновить токен доступа для входа в Django
Пытаюсь обновить маркер доступа, который я получаю от Django каждые несколько секунд, однако получаю сообщение об ошибке
Request Method: POST Status Code: 400 Bad Request
Я отправляю свой токен обновления на эту конечную точку: "http://127.0.0.1:8000/api/token/refresh/"
Это мой urls.py:
from rest_framework_simplejwt.views import (TokenObtainPairView, TokenRefreshView, TokenVerifyView)
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
urlpatterns = [
path('', include(router.urls)),
path('admin/', admin.site.urls),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
# path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
path('api/register', RegisterApi.as_view()),
]
Вот как я отправляю свой токен обновления:
let updateToken = async ()=> {
try {
let response = await axios.post('http://127.0.0.1:8000/api/token/refresh/',JSON.stringify(authTokens.refresh))
//update state with token
setAuthTokens(authTokens => ({
...response.data
}))
//update user state
const decoded = jwt_decode(response.data.access)
setUser(user => ({
...decoded
}))
//store tokens in localStorage
//we stringify because we can only store strings in localStorage
localStorage.setItem('authTokens',JSON.stringify(response.data))
}
catch(err) {
//if fail, something is wrong with refresh token
console.log(err.response)
}
}
Вот какую ошибку я получаю:
config: {transitional: {…}, transformRequest: Array(1), transformResponse: Array(1), timeout: 0, adapter: ƒ, …}
data:
refresh: ['This field is required.']
[[Prototype]]: Object
headers:
content-length: "39"
content-type: "application/json"
[[Prototype]]: Object
request: XMLHttpRequest
onabort: ƒ handleAbort()
onerror: ƒ handleError()
onload: null
onloadend: ƒ onloadend()
onloadstart: null
onprogress: null
onreadystatechange: null
ontimeout: ƒ handleTimeout()
readyState: 4
response: "{\"refresh\":[\"This field is required.\"]}"
responseText: "{\"refresh\":[\"This field is required.\"]}"
responseType: ""
responseURL: "http://127.0.0.1:8000/api/token/refresh/"
responseXML: null
status: 400
statusText: "Bad Request"
timeout: 0
upload: XMLHttpRequestUpload {onloadstart: null, onprogress: null, onabort: null, onerror: null, onload: null, …}
withCredentials: false
[[Prototype]]: XMLHttpRequest
status: 400
statusText: "Bad Request"
[[Prototype]]: Object
Вот что у меня есть в authTokens:
{refresh: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90e…9tIn0._aS9oDcj3Rfomodbs9qMEFmgEm4oEdOfSwGSJJKLWmg', access: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90e…20ifQ.K1YCXWoMWF7o61fGAuVm-QoehB3-jA2A_dLZ4o4uYa8'}
В /api/token/refresh/ возвращается только маркер access.
Когда вы setAuthToken используете все данные ответа, вы, скорее всего, избавляетесь от refresh токена.
Теперь, когда вы в следующий раз делаете запрос, authTokens.refresh не определяется и, следовательно, не отправляется на бэкенд. Бэкенд справедливо жалуется, что это 400: Bad Request. refresh является обязательным полем.
Измените код фронтенда, чтобы обновлять только токен access. Когда срок действия токена refresh истечет, вам нужно будет вызвать /api/token/ для повторного входа.
В качестве альтернативы вы можете изменить бэкенд для ротации токенов обновления. Это позволит отправлять новый токен refresh каждый раз, когда обновляется токен access.
Это достигается установкой ROTATE_REFRESH_TOKENS = True в настройках.
Если вы хотите убедиться, что старый маркер обновления больше не может быть использован, вы можете внести его в черный список при ротации, установив BLACKLIST_AFTER_ROTATION = True