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

Documentation for AppleID and/or authorization code flows #105

Open
denizdogan opened this issue Jan 10, 2022 · 15 comments
Open

Documentation for AppleID and/or authorization code flows #105

denizdogan opened this issue Jan 10, 2022 · 15 comments
Labels
good first issue Good for newcomers help wanted Extra attention is needed

Comments

@denizdogan
Copy link
Contributor

I can't figure out how to sign in using AppleID with this library, and I can't understand how the authorization code flow is supposed to work in general.

The README explicitly says to use "Resource owner password-based", but that should obviously be "Authorization code" in this case. But what about the client ID and client secret? Do those work just like with convert_token? Can I use a fake URI for redirect URIs? It seems that no matter which way I twist and turn things, I get invalid_client or invalid_grant back.

Much appreciated.

@wagnerdelima
Copy link
Owner

@denizdogan yes Apple Sign in is a little bit of a mistery so far. It's in my list of todos to include it here. Did you find anything interesting yourself that can be included to the docs?

@denizdogan
Copy link
Contributor Author

@wagnerdelima Not yet, was hoping that someone else had made it work. The whole chain of dependencies is so convoluted, it's hard to know what library does what. PyCharm goes a long way, but even then it's hard to keep track. :)

@denizdogan
Copy link
Contributor Author

Having debugged this one for a little bit, it seems like there's a Grant object missing while validating the authorization code. Line 412 in oauth2_provider.oauth2_validators.OAuth2Validator.validate_code raises Grant.DoesNotExist. It seems to me that this Grant object is meant to be created in oauth2_provider.views.mixins.OAuthLibMixin.create_authorization_response.

From what I've been able to gather, it seems that the idea is that this is created in AuthorizationView with an HTML page and a form. Obviously, this is not suitable for AppleID login, so I'm definitely missing something. (Or some library is missing something.)

Trying a completely different approach, I've tried to POST some authorization code data to /api/auth/complete/apple-id/, but all that does is give me:

django.urls.exceptions.NoReverseMatch: 'social' is not a registered namespace
Internal Server Error: /api/auth/complete/apple-id/

This is the same problem that has been mentioned here two weeks ago: #79 (comment)

I'm not sure where to go from here. It seems that something is missing here, but I'm not entirely sure what it is.

@wagnerdelima
Copy link
Owner

Unfortunately I never tried to use the apple sign on. I can try debugging this a little later once I am done with my current task.

@denizdogan
Copy link
Contributor Author

I finally managed to get AppleID sign-in working, but not with the authorization code, rather with the identity token (which I didn't realize we receive from the SDK). Here is how it's done in SwiftUI:

SignInWithAppleButton(.continue) { request in
    request.requestedScopes = [.fullName, .email]
} onCompletion: { result in
    switch result {
    case .success(let authResults):
        switch authResults.credential {
        case let credential as ASAuthorizationAppleIDCredential:
            guard let identityToken = credential.identityToken else {
                print("no identity token received")
                return
            }
            let identityTokenString = String(decoding: identityToken, as: UTF8.self)
            // convert the identity token to an access token:
            // POST /auth/convert-token/
            // {
            //     "grant_type": "convert_token",
            //     "backend": "apple-id",
            //     "client_id": "<application ID>",
            //     "client_secret": "<application secret>",
            //     "token": identityTokenString
            // }
        default:
            // failed to get credentials
        }
    case .failure(let error):
        // sign-in failed
    }
}

Thanks to this comment in the deprecated repo: RealmTeam/django-rest-framework-social-oauth2#241 (comment)

Close this issue if you'd like, otherwise let's consider this issue to be about documenting this somewhere.

@wagnerdelima
Copy link
Owner

Hi @denizdogan
I am happy you found a solution. I just saw your comment in the deprecated repo. Let's keep this issue open so I can document it!

@SolomonPetrovich
Copy link

Does anyone knows how to get identityToken form apple account for testing, for example google has OAuth2 playground? (https://developers.google.com/oauthplayground/)

@wagnerdelima wagnerdelima added the good first issue Good for newcomers label Apr 17, 2023
@wagnerdelima
Copy link
Owner

@denizdogan @SolomonPetrovich did you find out how to create an apple app to get client id and client secret?

@wagnerdelima wagnerdelima added the help wanted Extra attention is needed label Apr 27, 2023
@SolomonPetrovich
Copy link

@denizdogan @SolomonPetrovich did you find out how to create an apple app to get client id and client secret?

Nope

@denizdogan
Copy link
Contributor Author

@wagnerdelima I did manage to get it working after a lot of trial and error.

I don't have access to any of the actual code anymore, but this is pretty much how it works. Hopefully someone else can try this and get back to me and tell me if it works or not.

If this works, someone should document this properly, this comment is not good enough :)

# settings.py

# not sure if all three are needed here tbh
INSTALLED_APPS = [
  # ...
  "oauth2_provider",
  "social_django",
  "drf_social_oauth2",
  # ...
]

# add the apple id backend
AUTHENTICATION_BACKENDS = (
    "social_core.backends.apple.AppleIdAuth",
    "drf_social_oauth2.backends.DjangoOAuth2",
    "django.contrib.auth.backends.ModelBackend",
)

# configure apple id backend settings, i think all of these are mandatory?
SOCIAL_AUTH_APPLE_ID_CLIENT = # ...apple bundle id...
SOCIAL_AUTH_APPLE_ID_TEAM = # ...apple team id...
SOCIAL_AUTH_APPLE_ID_KEY = # ...apple key id...
SOCIAL_AUTH_APPLE_ID_SECRET = # ...apple key secret...
SOCIAL_AUTH_APPLE_ID_SCOPE = ["email", "name"]
// MyLoginButton.swift
struct MyLoginButton: View {
  func onRequest(_ request: ASAuthorizationAppleIDRequest) {
    request.requestedScopes = [.fullName, .email]
  }

  func onCompletion(_ result: Result<ASAuthorization, any Error>) {
    Task { @MainActor in
      do {
        guard
          case let .success(auth) = result,
          case let cred = auth.credential as! ASAuthorizationAppleIDCredential,
          let identity = cred.identityToken?.utf8 else {
            throw MyError.authFailed
          }
        // send this to the django backend:
        // POST /auth/convert-token/
        // {"token": <identity>, "backend": "apple-id"}
        // (the response will contain the token we want)
      } catch {
        // ...
      }
    }
  }

  var body: some View {
    SignInWithAppleButton(
      .continue,
      onRequest: self.onRequest,
      onCompletion: self.onCompletion
    )
  }
}

@denizdogan
Copy link
Contributor Author

Sorry, maybe I misunderstood your question, was my response what you were looking for? I don't really remember.

@wagnerdelima
Copy link
Owner

The question was not how to set up the configuration. It's just that I have not found a way to create an apple application to get the apple key, apple secret etc. Do you know where to get those variables from?

@denizdogan
Copy link
Contributor Author

@wagnerdelima Here's some example values, with some explanation below.

SOCIAL_AUTH_APPLE_ID_CLIENT = "com.foobar.MyApp"
SOCIAL_AUTH_APPLE_ID_TEAM = "FDHPXE33MD"
SOCIAL_AUTH_APPLE_ID_KEY = "3AB82BA21G"
SOCIAL_AUTH_APPLE_ID_SECRET = "-----BEGIN PRIVATE KEY-----\nVdH8so0J1DSjnWydQYEXIgBXJznkeOxL9UwKDuipH4KSDzbBF4ehTlbkui4eo3fB\nDk2qNRWtomLL1Rh0lqtmvQ7BdqqLXA8aYba7p12DWSIqP0ZOZsHPGTOmdSDXfkak\nfW9cT2tS7XxGtqtnm8mpHP9c8WzufCN7Cri6Co27ULUTz8MUPQebws7ugYiFT0Xf\n52F6BIw8\n-----END PRIVATE KEY-----"
SOCIAL_AUTH_APPLE_ID_SCOPE = ["email", "name"]

Obviously all values above are fake.

  • SOCIAL_AUTH_APPLE_ID_CLIENT – literally just your app bundle ID, you choose this yourself when creating your app
  • SOCIAL_AUTH_APPLE_ID_TEAM – the team ID, can be found in e.g. App Store Connect, or in Apple Developer, etc.
  • SOCIAL_AUTH_APPLE_ID_KEY – you need a private key to use Sign in with Apple, just follow the guides linked below. They describe the process of generating a key and where to find its ID. The ID can also be found in the actual filename of the .p8 file, e.g. "AuthKey_3AB82BA21G.p8". Anyway, the private key ID goes in this field.
  • SOCIAL_AUTH_APPLE_ID_SECRET – literally the content of your .p8 file, just replace newlines with \n

Additionally, you need to add the "Sign in with Apple" entitlement to your app. It's simple to do via "Signing & Capabilities" in your app project, and when done correctly you will have a .entitlements file in your app project root, and it will look like this:

Screenshot 2023-04-28 at 15 41 22

Hopefully this helps. I'm not 100% sure what is being asked exactly.

@resuls
Copy link

resuls commented Feb 10, 2024

https://prog.world/django-drf-sign-in-with-apple/
This explains how to get the necessary stuff for Apple.

@wagnerdelima
Copy link
Owner

@resuls thank you for sharing! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers help wanted Extra attention is needed
Projects
Development

No branches or pull requests

4 participants