Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use with OAUTH2 - django-oauth-toolkit? #124

Open
bpsgit opened this issue Jul 3, 2018 · 2 comments
Open

How to use with OAUTH2 - django-oauth-toolkit? #124

bpsgit opened this issue Jul 3, 2018 · 2 comments

Comments

@bpsgit
Copy link

bpsgit commented Jul 3, 2018

Hi,

Trying to use with OAUTH2 - django-oauth-toolkit.

MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'oauth2_provider.middleware.OAuth2TokenMiddleware',
'defender.middleware.FailedLoginMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)
User blocking works fine in case of post on /admin/login/
Does not work on /accounts/login/

Thanks in advance.

@dopry
Copy link

dopry commented Jan 5, 2022

@bpsgit did you ever figure this out?

@dopry
Copy link

dopry commented Jan 5, 2022

I just figured out how to use it with the OAuthResourceOwnerPassword grant type... I needed to implement a CustomOAuth2Validator, and override the proper method for the login validation used by the grant type... There was one major gotcha, OAuthLib/OAuthToolkit have a different request class than django that doesnt have META, so I needed to shim that... and I also needed to figure out which errors to raise by looking at the method in the GrantType that was calling the Validator.validate_user... If you're working with another grant type, you'll probably need to shim a different method.

Hope this helps.

from defender.utils import add_login_attempt_to_db, check_request, is_already_locked
from django.contrib.auth import authenticate
from oauth2_provider.oauth2_validators import OAuth2Validator
from oauthlib.oauth2.rfc6749 import errors

class CustomOAuth2Validator(OAuth2Validator):
    # this method is called by oauthlib.oauth2.rfc6749.grant_types.ResourceOwnerPasswordCredentialsGrant
    # it looks like that is the only grant type that calls this method. 
    def validate_user(self, username, password, client, request, *args, **kwargs):
        """
        Check username and password correspond to a valid and active User,
        enforce django defender on authentication. 
        """
        # django-defender expects https://docs.djangoproject.com/en/3.2/ref/request-response/#django.http.HttpRequest.META
        # but OAuthLib.core.Request makes a simplified version without META
        # so we need to shim it here to make defender happy.
        request.META = request.headers
       
        locked = is_already_locked(request, username=username)
        # print('locked', locked)
        # print('request', request)
        # print('request', request.body)
        if locked:
            raise errors.InvalidGrantError(description='Too many failed login attempts.', status_code=403, request=request)
            
        u = authenticate(username=username, password=password)
        login_valid =  u is not None and u.is_active
        

        add_login_attempt_to_db(request, login_valid=login_valid, username=username)
        check_request(request, login_unsuccessful=not login_valid, username=username)

        if not login_valid: 
            raise errors.InvalidGrantError('Invalid credentials given.', status_code=401, request=request)

        request.user = u
        return login_valid

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants