Django-Ninja CSRF Token & OpenAPI

176 Views Asked by At

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.

0

There are 0 best solutions below