social-core
social-core copied to clipboard
Authorization backend function do_auth called twice
I've implemented apple sign-in following this article using subclass: https://github.com/truffls/sign-in-with-apple-using-django/blob/master/backend.md
Code:
import jwt
import requests
from datetime import timedelta
from django.conf import settings
from django.utils import timezone
from social_core.utils import handle_http_errors
from social_core.backends.oauth import BaseOAuth2
class AppleOAuth2(BaseOAuth2):
name = 'apple'
ACCESS_TOKEN_URL = 'https://appleid.apple.com/auth/token'
SCOPE_SEPARATOR = ','
ID_KEY = 'uid'
@handle_http_errors
def do_auth(self, access_token, *args, **kwargs):
response_data = {}
client_id, client_secret = self.get_key_and_secret()
headers = {'content-type': "application/x-www-form-urlencoded"}
data = {
'client_id': client_id,
'client_secret': client_secret,
'code': access_token,
'grant_type': 'authorization_code',
}
res = requests.post(AppleOAuth2.ACCESS_TOKEN_URL, data=data, headers=headers)
response_dict = res.json()
id_token = response_dict.get('id_token', None)
if id_token:
decoded = jwt.decode(id_token, '', algorithms=["ES256"], options={"verify_signature": False})
response_data.update({'email': decoded['email']}) if 'email' in decoded else None
response_data.update({'uid': decoded['sub']}) if 'sub' in decoded else None
response = kwargs.get('response') or {}
response.update(response_data)
response.update({'access_token': access_token}) if 'access_token' not in response else None
kwargs.update({'response': response, 'backend': self})
return self.strategy.authenticate(*args, **kwargs)
def get_user_details(self, response):
email = response.get('email', None)
details = {
'email': email,
}
return details
def get_key_and_secret(self):
headers = {
'kid': settings.SOCIAL_AUTH_APPLE_ID_KEY
}**strong text**
payload = {
'iss': settings.SOCIAL_AUTH_APPLE_ID_TEAM,
'iat': timezone.now(),
'exp': timezone.now() + timedelta(days=180),
'aud': 'https://appleid.apple.com',
'sub': settings.SOCIAL_AUTH_APPLE_ID_CLIENT,
}
client_secret = jwt.encode(
payload,
settings.SOCIAL_AUTH_APPLE_ID_SECRET,
algorithm='ES256',
headers=headers
)
return settings.SOCIAL_AUTH_APPLE_ID_CLIENT, client_secret
Authorization succeeds during first call, i receive access token from apple, new entries in Users & User social auths tables are created but after that function do_auth
is called one more time causing duplicate entry:
The very time user logs in - new entry in Users & User social auths tables created.
During the second call id_token is empty because apple's authorization code is one time token. So SOCIAL_AUTH_PIPELINE in settings.py now are commented, I tried different variants. Can somebody help me?