I'm using django-allauth (headless, {app}) as my authentication backend along with django-ninja. I've set-up django-allauth configurations properly. If I login using POST http://127.0.0.1:8000/_allauth/app/v1/auth/login with a valid body (username & pass), it successfully responds with a session token. As instructed in the docs, when I set X-Session-Token header with this token value & send a request to http://localhost:8000/_allauth/app/v1/auth/session (Get authentication status), it also responds successfully with json body containing "meta": {"is_authenticated": true}, meaning the user is authenticated.
So far, everything is fine & the authentication is working perfectly. But, when I hit another api url (for example: GET http://localhost:8000/api/website/blog_category with header X-Session-Token: <TheToken>), then I find from that function, request.user is always AnonymousUser. My understanding was, since django-allauth has its own middleware, it should have populated the request.user correctly since a valid X-Session-Token is correctly sent as a header.
Hers's my urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path("accounts/", include("allauth.urls")),
path("_allauth/", include("allauth.headless.urls")),
path("api/", api.urls),
]
api.py:
from ninja import NinjaAPI
api = NinjaAPI()
api.add_router("website/", "website.api.router")
Here is my website.api.py:
from ninja import Router
from ninja.security import django_auth # setting auth=django_auth, always returns permission denied
from typing import List
from .models import blog_category
from .schema import BlogCategoryRetrieveSchema
router = Router(auth=None) # since django-auth returns permission denied, so lets run without auth to print request.user & request.META.get('HTTP_X_SESSION_TOKEN')
@router.get("/blog_category", response=List[BlogCategoryRetrieveSchema])
async def blog_category_retrieve(request):
print(request.user)
print(request.META.get('HTTP_X_SESSION_TOKEN'))
# logic here
return something
Console says:
AnonymousUser # for print(request.user)
8jdtkzt69n9xp2xlqf9r6hc1eyw78p0k # for print(request.META.get('HTTP_X_SESSION_TOKEN'))
Meaning, session token is properly sent but django-allauth is not authenticating the user. Shouldn't django-allauth have done it automatically from the middleware? or am I missing anything?
I was expecting that django-allauth's middleware would take care of authenticating the user and populate request.user if a valid x-session-token is sent, in every request. Though, allauth's api urls (headless, {app}) are working perfectly; when requesting to other urls, I don't see any authentication being done leaving the request.user as AnonymousUser. I tried:
from ninja.security import django_auth
router = Router(auth=django_auth)
# But setting auth=django_auth, always returns permission denied
Now, I could write a middleware or maybe a function that uses 'Get authentication status' functionality from 'django-allauth' to validate a user & use this mechanism to set 'auth' (ninja). But isn't there any generic way of doing this? Am I missing something?
My approach was (this way we can have a little more manual control):
from allauth.headless.account.views import SessionView
class get_user_from_sessionview(SessionView):
def dispatch(self, request, *args, **kwargs):
return request.user
then, we can easily use it like this:
get_user_from_sessionview.as_api_view(client='app')(request) # client is either 'app' or 'browser'
If I remember correctly, it returned the user object.