Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Using new DJ5.1 LoginRequiredMiddleware with login_not_required erroneously redirects API call to login-page#9503

Unanswered
RobKuipers asked this question inPotential Issue
Discussion options

Using the new Django 5.1LoginRequiredMiddleware, I ran into an issue with calling an API that uses Basic Authentication. It suddenly kept redirecting to the login-page.
So I marked my API call with@login_not_required, only to find the problem remained!

Moving the@login_not_required decorator to the top (setting it as the first decorator, before@api_view(['GET'])), circumvented the problem.
But this seems very ugly. With the need to set the@login_not_required decorator on all API's, and more importantly, having to know it needs to be first.

I'm of the opinion API-calls should never redirect to a login-page, but rather return the appropriate http-statuscode.
But, where (and how) to implement this?

Very interested in your opinions/solutions.

You must be logged in to vote

Replies: 4 comments

Comment options

I'm not sure this is the best solution, but you can create a custom middleware that bypassesLoginRequiredMiddleware for specific URL patterns using regex.django-stronghold had the same type of functionality.

# app/middleware.pyfromdjango.confimportsettingsfromdjango.contrib.auth.middlewareimportLoginRequiredMiddlewarefromdjango.utils.deprecationimportMiddlewareMixinimportreclassCustomLoginRequiredMiddleware(LoginRequiredMiddleware):def__init__(self,get_response=None):self.get_response=get_responseself.open_urls= [re.compile(url)forurlinsettings.OPEN_URLS]super().__init__(get_response)defprocess_view(self,request,view_func,view_args,view_kwargs):forurlinself.open_urls:ifurl.match(request.path):returnNone# Pass through, no login requiredreturnsuper().process_view(request,view_func,view_args,view_kwargs)

Insettings.py, defineOPEN_URLS and use the custom middleware:

# app/settings.pyMIDDLEWARE= [# ..."app.middleware.CustomLoginRequiredMiddleware",]# Regex patterns for paths that bypass LoginRequiredMiddlewareOPEN_URLS= [r"^/my-api/.*",# ...]

I'm also very interested in opinions and solutions.

You must be logged in to vote
0 replies
Comment options

As far as I understand, it's because DjangoLoginRequiredMiddleware kicks in before the DRF view-level auth happens, so as far as Django is concerned, the HTTP request isn't authenticated until the DRF logic kicks in, which AFAIU is done at the view level:

definitialize_request(self,request,*args,**kwargs):
"""
Returns the initial request object.
"""
parser_context=self.get_parser_context(request)
returnRequest(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)

def_authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
forauthenticatorinself.authenticators:
try:
user_auth_tuple=authenticator.authenticate(self)
exceptexceptions.APIException:
self._not_authenticated()
raise
ifuser_auth_tupleisnotNone:
self._authenticator=authenticator
self.user,self.auth=user_auth_tuple
return
self._not_authenticated()

calling an API that uses Basic Authentication

I would be curious if you see the same behaviour with session auth. My expectation is that it would work, because this relies on a Django built-in auth mechanism, while the others (Basic and token based auth) are DRF specific.

With regards to solutions, one might be for DRF to provide a specialized version of Django'sLoginRequiredMiddleware. AFAIK, that fits into the maintenance policy to keep up to date with newer Django features.

You must be logged in to vote
0 replies
Comment options

I've dug this a bit more to attempt to add compatibility to DRF as part of#9514 and just realised that DRF already offers a way to make sure all endpoints are authenticated, via theDEFAULT_PERMISSION_CLASSES setting.

You must be logged in to vote
0 replies
Comment options

@browniebroke Came accross this, since I was thinking weather I should be using DRFDEFAULT_PERMISSION_CLASSES or a django middleware (concerning login-required functionality; my custom authenticated user checks, such as email-verified, policy-agreed etc.; and specific permission checks for individual views, e.g. roles). And I noticed this in the docs:
Note: when you set new permission classes via the class attribute or decorators you're telling the view to ignore the default list set in the settings.py file.
Which if being the case, doesn't satisfy my use case, since I wanna stack permission checks (login-required + authenticated-related-almost-ubiquitous-checks + individual-view-checks), not overwrite them. And specifying all of them at view-level results in a lot of duplication and is error-prone. At first glance a quick solution to this might be to subclassBasePermission, but I felt hesitant going this way as middleware approach seemed cleaner. Please fix me if I misunderstood smth, but it looks like for my use case I'll have to work at django middleware level andLoginRequiredMiddleware ain't gonna help much. :)

You must be logged in to vote
0 replies
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Labels
None yet
4 participants
@RobKuipers@browniebroke@apetryla@thomaslrg

[8]ページ先頭

©2009-2025 Movatter.jp