I do have a problem with apple signin in python but it's mostly not python, just mysterious stuff.... So, I read this article https://medium.com/@aamishbaloch/sign-in-with-apple-in-your-django-python-backend-b501daa835a9 It should be quite easy to implement it but my implementation doesn't work, so what I did is: I've added appleapiprovider class which being used in rest framework, this AppleProvider being called this way:
provider = AppleApiProvider()
provider.verify_token(token_sent_from_ios_device) # NOT JWT TOKEN, just code.
and here is what happening in the method verify_token
def verify_token(self, token):
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',
'redirect_uri': 'https://example-app.com/redirect'
}
res = requests.post('https://appleid.apple.com/auth/token', data=data, headers=headers)
def get_key_and_secret(self):
headers = {
'kid': KID
}
payload = {
'iss': ISS,
'iat': timezone.now(),
'exp': timezone.now() + timedelta(days=180),
'aud': 'https://appleid.apple.com',
'sub': 'com.APP.staging.signin',
}
client_secret = jwt.encode(
payload,
open('/etc/apple.pem', 'rb').read(),
algorithm='ES256',
headers=headers
).decode("utf-8")
return 'com.APP.staging.signin', client_secret
And in result I get
{error: 'invalid_grant'}
Any idea ? It's not a problem with client_id and client_secret, I tried to use there just absolutely random strings and it says, invalid_client Possible duplicate is: New Apple Sign in keeps throwing Error HTTP 400 Invalid_grant but there's no exact solution to my problem, it should be quite small and I don't know how to debug it.
My error was using the JWT token as the 'code' parameter instead of the authorization_code.
I am using the '@invertase/react-native-apple-authentication' React Native package to handle Apple Sign in on client side. I think the data transmitted there may be similar across Native and other packages.
What this package returns on apple sign-in is the following object:
{
authorizationCode: string <- this should be sent as "code"
authorizedScopes: [],
email: string <- will be null, except for first request. To reset for testing, disconnect the app from apple signin
fullName: {...} <- will contain null values only, except for first request. see above
identityToken: string
nonce: string
realUserStatus: 1
state: ?
user: string <- should be used to identify users
}
The identityToken is a JWT token that when decoded contains the following data:
header:
{
"kid": string, <- can be used to identify the apple public key one can use to verify the signature (fetched from here https://appleid.apple.com/auth/keys)
"alg": "RS256"
}
payload:
{
"iss": "https://appleid.apple.com",
"aud": <your package ID>,
"exp": number,
"iat": number,
"sub": string, <- same as "user" in above datastructure
"nonce": string,
"c_hash": string,
"email": "[email protected]", <- contains the email, even if the above structure does not contain it
"email_verified": "true",
"is_private_email": "true",
"auth_time": number,
"nonce_supported": true
}
One confusing aspect is, that the email can be null in the first obj, but still be contained in the JWT. It is a bit unclear whether we need the JWT token in all cases. It seems like for a simple authentication service the authorizationCode and user parameters suffices.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With