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

Here is the updated code for backend. #10

Open
srijan113 opened this issue Apr 2, 2024 · 0 comments
Open

Here is the updated code for backend. #10

srijan113 opened this issue Apr 2, 2024 · 0 comments

Comments

@srijan113
Copy link

srijan113 commented Apr 2, 2024

Here is the updated code for backend.

There were certain problems that I faced during this process. Unlike in docs I am not using any package for authentication. So, I had to strip down the code to bare minimum so below code is for creating client secret and validating the authorization_code.

Problem was with identity_token or authorization_code by client side
- In docs, access_token was mentioned and all that client side can provide was identity_token or authorization_code or both. Here I have used authorization_code.

How to use PRIVATE_KEY securely(maybe not a part that docs is related to). I have stored PRIVATE_KEY in my env file. I have just appended the private key into a single line and later on strip to get raw PRIVATE_KEY

Example:
    APPLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\nyourrandomnstring1\nyourrandomnstring2\nyourrandomnstring3\n-----END PRIVATE KEY-----

Original:
    -----BEGIN PRIVATE KEY-----
    yourrandomnstring1
    yourrandomnstring2
    yourrandomnstring3
    -----END PRIVATE KEY-----

Decoding of the id_token.During the time docs was made may be it was correct but the code mention in code didn't worked for me so I had to update the decoding processing.

PY JWT reading the claim without validation

```
decoded = jwt.decode(id_token, options={"verify_signature": False})
```

Things to remember:

  1. authorization_code is 1 time thing, create new one every time you try to login (client side).

  2. PRIVATE_KEY is 1 time thing once you download cannot be downloaded again

  3. Below code only creates client_secret and validates the authorization_code this is not a complete flow

  4. It only returns email if authorization_code is valid otherwise it returns empty dict.

import jwt
import requests
from datetime import timedelta
from medhavhilms.settings import env
from django.utils import timezone

APPLE_BUNDLE_NAME = env('APPLE_BUNDLE_NAME')
APPLE_KEY_ID = env('APPLE_KEY_ID')
APPLE_TEAM_ID = env('APPLE_TEAM_ID')
APPLE_BUNDLE_ID = env('APPLE_BUNDLE_ID')
APPLE_PRIVATE_KEY = env('APPLE_PRIVATE_KEY').strip().replace('\\n', '\n')  # Remove whitespace and replace escaped newlines

class AppleOAuth2():
    ACCESS_TOKEN_URL = 'https://appleid.apple.com/auth/token'

    def authenticate(self, auth_code):
        response_body = {}
        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': auth_code,
            '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, options={"verify_signature": False})
            response_body.update({'email': decoded.get('email')})
    
        return response_body
    
    def get_key_and_secret(self):
        headers = {
            'alg': 'ES256',
            'kid': APPLE_KEY_ID
        }

        payload = {
            'iss': APPLE_TEAM_ID,
            'iat': timezone.now(),
            'exp': timezone.now() + timedelta(days=180),
            'aud': 'https://appleid.apple.com',
            'sub': APPLE_BUNDLE_ID,
        }

        client_secret = jwt.encode(
            payload, 
            APPLE_PRIVATE_KEY, 
            algorithm='ES256', 
            headers=headers
        )
        return APPLE_BUNDLE_ID, client_secret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant