Параметры PKCE для Snapchat

#django #django-allauth #snapchat

#django #django-allauth #snapchat

Вопрос:

Я пытаюсь написать провайдера django-allauth для Snapchat, и я застрял на контрольно-пропускном пункте.

Snapchat требует параметров PKCE. Сначала я изменил параметры AUTH_PARAMS.

 'AUTH_PARAMS': {
            'code_challenge': 'state',
            'code_challenge_method': "S256"
        }
 

Это привело только к недопустимым ответам от API Snapchat на запрос Access_Token после того, как я получил ответ с кодом.

Эта ошибка — первая ошибка, которую я получил.

 {'error': 'invalid_request', 'error_description': 'Invalid code_verifier length.', 'state': ''}
 

После переопределения SocialLogin.stash_state я получаю эту ошибку.

 {'error': 'invalid_grant', 'error_description': 'Invalid code_verifier.', 'state': ''}
 

Из того, что я могу покопаться в коде all auth, я ничего не могу найти в кодовой базе по параметрам PKCE или URL-адресу base64 в кодировке SHA256.

Я готов реализовать решение, но я застрял в поиске, где можно подклассировать параметры состояния, а затем сопоставить их после.

В документах Snapchat также есть некоторые проблемы с этим.

https://gist.github.com/CisarJosh/733bb76a13f36f0a7944f05d257bb3f6

Это суть некоторых моих попыток.

Комментарии:

1. Так что немного непонятно, о чем вы спрашиваете. Итак, я начну с Provider.get_auth_params() того, что по умолчанию будет возвращено AUTH_PARAMS то, что вы настроили. Поскольку предполагается, что этот протокол должен быть динамическим, их статическая настройка может оказаться неправильной. Вместо этого переопределите get_auth_params() в своем провайдере, и, если я правильно понимаю, вам нужно будет сгенерировать там верификатор кода.

2. Хорошо, я буду работать над этим.

3. Позвольте мне уточнить. PKCE — это то, что мне нужно будет правильно реализовать с помощью S256 в качестве метода. Я спрашиваю, где сгенерировать code_verifier . Я не смог найти никого другого, кто бы это реализовал. Я начну с этого.

Ответ №1:

Я думаю, это поможет вам начать:

 from allauth.socialaccount.providers.oauth2.provider import OAuth2Provider
import secrets
import base64
import hashlib
import urllib.parse

VOCAB = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~0123456789"


def generate_code_verifier() -> str:
    length = max(43, secrets.randbelow(129))
    return "".join([secrets.choice(VOCAB) for i in range(0, length)])


def generate_state() -> str:
    return secrets.token_urlsafe(32)


class SnapchatProvider(OAuth2Provider):
    def get_auth_params(self, request, action):
        params = super().get_auth_params(request, action)
        code_verifier = generate_code_verifier()
        state = generate_state()
        # store this state token somewhere so it can be looked up
        challenge = hashlib.sha256(code_verifier).digest()
        encoded = base64.b64encode(challenge)
        urlencoded = urllib.parse.quote_plus(encoded)
        params.update(state=state, code_challenge=urlencoded)
        
        return params
 

Это моя интерпретация спецификации для этой части.