I am using Django-Ninja and want to use authentication in it.
Here is my authentication process :
from ninja_extra import NinjaExtraAPI
from ninja.security import django_auth
api = NinjaExtraAPI(csrf=True)
# AUTHENTICATION
#//////////////////////////////////////////////////////////////////////////////
@api.post("/login")
def login_user(request, username: str, password: str):
# Authentification de l'utilisateur
user = authenticate(request, username=username, password=password)
if user is not None:
# Connexion de l'utilisateur
login(request, user)
return {"message": "Login successful"}
else:
return {"message": "Login failed"}
@api.post("/logout", auth=django_auth)
def logout_user(request):
# Déconnexion de l'utilisateur
logout(request)
return {"message": "Logout successful"}
#//////////////////////////////////////////////////////////////////////////////
When I go to http://127.0.0.1:8000/api/docs, I can try the login route and it works.
And the other hand, the logout route fails with a CSRF verification failed. Request aborted..
I then tried to look closer to the queries and here is what I found :
1.
GET http://127.0.0.1:8000/api/docs
-------------------------------------------------------------------
HTTP/1.1 200 OK
Date: Thu, 18 Jan 2024 13:16:07 GMT
Server: WSGIServer/0.2 CPython/3.10.9
Content-Type: text/html; charset=utf-8
X-Frame-Options: DENY
Vary: Cookie
Content-Length: 974
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin
Set-Cookie: csrftoken=ZMn7RxrJl3fdnrMHGKNmlgB0GiB0Eyeq; expires=Thu, 16 Jan 2025 13:16:07 GMT; Max-Age=31449600; Path=/; SameSite=Lax
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/swagger-ui.css">
<link rel="shortcut icon" href="https://django-ninja.rest-framework.com/img/favicon.png">
<title>NinjaExtraAPI</title>
</head>
<body>
<div id="swagger-ui">
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/swagger-ui-bundle.js"></script>
<script>
const ui = SwaggerUIBundle({
url: '/api/openapi.json',
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
layout: "BaseLayout",
requestInterceptor: (req) => {
req.headers['X-CSRFToken'] = "nrYHNtn8eZZjuEYLxF6YrrzvJzRSrs2Jc3bEuQEHpS4mHVAi3fJaCx0lfHiIVQ6Z"
return req;
},
deepLinking: true
})
</script>
</body>
</html>
What does the script does regarding the csrf token ?
Then I try to login :
###
POST http://127.0.0.1:8000/api/login?username=user_name&password=password
accept: application/json
Content-Type: application/json
X-CSRFToken: ZMn7RxrJl3fdnrMHGKNmlgB0GiB0Eyeq
-------------------------------------------------------------------
HTTP/1.1 200 OK
Date: Thu, 18 Jan 2024 13:17:44 GMT
Server: WSGIServer/0.2 CPython/3.10.9
Content-Type: application/json; charset=utf-8
X-Frame-Options: DENY
Vary: Cookie
Content-Length: 31
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin
Set-Cookie: csrftoken=pHkge9pHbJM6DvjiPtISk6EmgnwxED3S; expires=Thu, 16 Jan 2025 13:17:44 GMT; Max-Age=31449600; Path=/; SameSite=Lax,sessionid=4yjmgze6et1448h9g6crru8bk7rlfn9m; expires=Thu, 01 Feb 2024 13:17:44 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax
{
"message": "Login successful"
}
Here is the interesting part, to logout (and for all POST requests), if do not use the new token from the login response, I get the error or this response.
###
POST http://127.0.0.1:8000/api/logout
Content-Type: application/json
X-CSRFToken: pHkge9pHbJM6DvjiPtISk6EmgnwxED3S
-------------------------------------------------------------------
HTTP/1.1 200 OK
Date: Thu, 18 Jan 2024 13:28:24 GMT
Server: WSGIServer/0.2 CPython/3.10.9
Content-Type: application/json; charset=utf-8
X-Frame-Options: DENY
Content-Length: 32
Vary: Cookie
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin
Set-Cookie: sessionid=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/; SameSite=Lax
{
"message": "Logout successful"
}
My question, why when I am using the http://127.0.0.1:8000/api/docs/ page to check does the csrf token is not updated ? I would keep with the first value of the token and so fails when trying to logout.