Open denizdogan opened 2 years ago
@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?
@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. :)
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: https://github.com/wagnerdelima/drf-social-oauth2/issues/79#issuecomment-1002739804
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.
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.
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: https://github.com/RealmTeam/django-rest-framework-social-oauth2/issues/241#issuecomment-932751527
Close this issue if you'd like, otherwise let's consider this issue to be about documenting this somewhere.
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!
Does anyone knows how to get identityToken form apple account for testing, for example google has OAuth2 playground? (https://developers.google.com/oauthplayground/)
@denizdogan @SolomonPetrovich did you find out how to create an apple app to get client id and client secret?
@denizdogan @SolomonPetrovich did you find out how to create an apple app to get client id and client secret?
Nope
@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
)
}
}
Sorry, maybe I misunderstood your question, was my response what you were looking for? I don't really remember.
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?
@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 appSOCIAL_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:
Hopefully this helps. I'm not 100% sure what is being asked exactly.
https://prog.world/django-drf-sign-in-with-apple/ This explains how to get the necessary stuff for Apple.
@resuls thank you for sharing! :)
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.