st4lk / django-rest-social-auth

OAuth signin with django rest framework
MIT License
519 stars 122 forks source link

Does this package support PKCE flow for preventing authorization code interception attacks? #136

Open anoopemacs opened 3 years ago

anoopemacs commented 3 years ago

PKCE flow diagram from its RFC:-

Screenshot 2020-11-20 at 2 09 23 AM
vecchp commented 6 months ago

Few years late... but given I landed on this page when doing my own research I figured I'd answer. I believe you need to modify the backend to support PKCE. This is what I ended up doing to get it to work for me. You need to make sure the code_verifier is sent along in the body (as opposed to the url params) of the post otherwise you defeat the purpose of using it.

from social_core.backends.google import BaseGoogleOAuth2API
from social_core.backends.oauth import BaseOAuth2

class GoogleOAuth2PKCE(BaseGoogleOAuth2API, BaseOAuth2):
    """Google OAuth2 authentication backend"""

    name = "google-oauth2-pkce"
    REDIRECT_STATE = False
    AUTHORIZATION_URL = "https://accounts.google.com/o/oauth2/auth"
    ACCESS_TOKEN_URL = "https://accounts.google.com/o/oauth2/token"
    ACCESS_TOKEN_METHOD = "POST"
    REVOKE_TOKEN_URL = "https://accounts.google.com/o/oauth2/revoke"
    REVOKE_TOKEN_METHOD = "GET"
    # The order of the default scope is important
    DEFAULT_SCOPE = ["openid", "email", "profile"]
    EXTRA_DATA = [
        ("refresh_token", "refresh_token", True),
        ("expires_in", "expires"),
        ("token_type", "token_type", True),
    ]

    def auth_complete_params(self, state=None):
        params = super().auth_complete_params(state=state)
        params["code_verifier"] = self.data.get("code_verifier", "")
        return params

I didn't have to modify the OAuth2InputSerializer serializer for the field to pass through but it might be worth a PR to put it in an optional param like the following.'

class OAuth2InputSerializer(serializers.Serializer):
    provider = serializers.CharField(required=False)
    code = serializers.CharField()
    code_verifier = serializers.CharField(required=False)
    redirect_uri = serializers.CharField(required=False)