Sign in with Apple using SwiftUI |

@gargoyle is it safe using directly credentials.user to identify a user on app server without doing any validation with Apple servers? I’m using native AuthenticationServices and I don’t understand how to use identityToken and authorizationCode. Thanks!

credentials.user is the ID that you store for the user. It’s where you’d historically have had them use an email address to create an ID in the past. There is no security around that user though. It’s a string of characters that anybody could spoof if they knew what it was.

The identityToken and authorizationCode are for the OAuth type flows that you’d handle server side. There a potential bug right now with the server side expiration dates that I’m working with Apple, and once I have that resolved I’m planning to post a tutorial on handling server side via Vapor.

If you are only on the device then you can trust the user provided. If you’re making a REST call to your backend server, then you need to implement the authorization via Apple’s REST API.

1 Like

Yes, I’m making REST call to my backend server… so I need to implement OAuth flow. Thanks for your answer, I’ll wait for your Vapor tutorial and then I’ll try to make it work in PHP :smiley:

I fixed the issue but I do not quite understand the whole process of Sign in with Apple.

1.) I check if there is already an Apple ID shared for login with this app.
2.) If not I request the credentials I need and store them in the local keychain.
3.) I was always looking for an entry for my app in Settings => Passwords & Accounts. But I realized that this has nothing to do with it.
4.) When my app is starting I am always checking if there is an entry for my app in the local keychain.
5.) So I don’t need to store anything in a seperate/external database.

Is that right? Did i get it?

Thanks in advance,

I’m also having the exact same problem. Try running the final project and it will show the error:

Screen Shot 2020-02-14 at 20.34.14

How did you fix the issue? I’m having same issue.

1 Like

In Xcode 11.4 this line causes an error; ‘Value of type ‘EnvironmentValues’ has no member ‘window’’

@Environment(\.window) var window: UIWindow?

How do you suggest populating the window variable?

Nevermind, I hadn’t created the extension from EnvironmentWindowKey.swift

I am having the same issue…

I tried
Xcode 11.3.1 (11C504)
Xcode 11.4 beta 2 (11N123k)

‘ContentView’ is not a member type of ‘SignInWithApple’

BuildError: Failed to build ContentView.swift

Compiling failed: ‘ContentView’ is not a member type of ‘SignInWithApple’

failedToBuildDylib: /Users/brent/Library/Developer/Xcode/DerivedData/SignInWithApple-gbyfszqmlonwrkbcsvqpgaudyrbu/Build/Intermediates.noindex/Previews/SignInWithApple/Intermediates.noindex/ error: ‘ContentView’ is not a member type of ‘SignInWithApple’
typealias ContentView = SignInWithApple.ContentView
~~~~~~~~~~~~~~~ ^
/Users/brent/Library/Developer/Xcode/DerivedData/SignInWithApple-gbyfszqmlonwrkbcsvqpgaudyrbu/Build/Intermediates.noindex/Previews/SignInWithApple/Intermediates.noindex/ error: replaced function ‘performSignIn(using:)’ could not be found
@_dynamicReplacement(for: performSignIn(using:)) private func __preview__performSignIn(using requests: [ASAuthorizationRequest]) {
/Users/brent/Library/Developer/Xcode/DerivedData/SignInWithApple-gbyfszqmlonwrkbcsvqpgaudyrbu/Build/Intermediates.noindex/Previews/SignInWithApple/Intermediates.noindex/ error: replaced function ‘performExistingAccountSetupFlows()’ could not be found
@_dynamicReplacement(for: performExistingAccountSetupFlows()) private func __preview__performExistingAccountSetupFlows() {
/Users/brent/Library/Developer/Xcode/DerivedData/SignInWithApple-gbyfszqmlonwrkbcsvqpgaudyrbu/Build/Intermediates.noindex/Previews/SignInWithApple/Intermediates.noindex/ error: replaced function ‘showAppleLogin()’ could not be found
@_dynamicReplacement(for: showAppleLogin()) private func __preview__showAppleLogin() {
/Users/brent/Library/Developer/Xcode/DerivedData/SignInWithApple-gbyfszqmlonwrkbcsvqpgaudyrbu/Build/Intermediates.noindex/Previews/SignInWithApple/Intermediates.noindex/ error: replaced accessor for ‘body’ could not be found
@_dynamicReplacement(for: body) private var __preview__body: some View {
/Users/brent/Downloads/SignInWithApple/final/SignInWithApple/ContentView.swift:79:5: error: use of unresolved identifier ‘appleSignInDelegates’
appleSignInDelegates = SignInWithAppleDelegates(window: window) { success in
/Users/brent/Downloads/SignInWithApple/final/SignInWithApple/ContentView.swift:79:61: error: use of unresolved identifier ‘window’
appleSignInDelegates = SignInWithAppleDelegates(window: window) { success in
/Users/brent/Downloads/SignInWithApple/final/SignInWithApple/ContentView.swift:88:27: error: use of unresolved identifier ‘appleSignInDelegates’
controller.delegate = appleSignInDelegates
/Users/brent/Downloads/SignInWithApple/final/SignInWithApple/ContentView.swift:89:46: error: use of unresolved identifier ‘appleSignInDelegates’
controller.presentationContextProvider = appleSignInDelegates
/Users/brent/Downloads/SignInWithApple/final/SignInWithApple/ContentView.swift:61:5: error: use of unresolved identifier ‘performSignIn’
performSignIn(using: [request])
/Users/brent/Downloads/SignInWithApple/final/SignInWithApple/ContentView.swift:49:34: error: use of unresolved identifier ‘showAppleLogin’
.onTapGesture(perform: showAppleLogin)

I am having a difficult time figuring out how to throw the UIWindow back into a regular ‘home screen’ that uses traditional SwiftUI. I know that you need to utilize UIKit to implement the sign in with apple button, but once authorization is successful/failed, I cannot seem to return a SwiftUI view.

The best I have been able to do is set a new Bool state in the ContentView for authentication success which triggers in the performSignIn private func if success. Thinking that would work, it seems to only return my new swift screen on the bottom half of the screen, but keeps the login screen on the top half and never refreshes away.

Any ideas?

Thanks for you help!

Is there any tutorial for implementing sign in with apple for iOS 12 devices. I am trying to figure it out but unfortunately it’s not working as expected. I followed the tutorial from here
Sign In With Apple

I’m getting invalid redirect_uri however I didn’t found anywhere what should we pass in the request for redirect_uri paramer. I’m calling the request from iPhone 6. Does anyone knows any solution to this ?

@rahulvyas The redirect_uri stuff is only used for the web based sign in. If you follow the tutorial it shows you what you need for iOS. if you’re not using swiftui you can just leave those parts out.

For iOS 13 you’re right we don’t need to code much, I’m looking for support in iOS 12 and older OSe’s.
If you read the docs it says we need to hit a URL and it will work something like facebook authorization. When I hit url (Using UIApplication openUrl method) I’m getting invalid redirect_uri error. If you know any other way to integrate it into iOS 12 and older devices do let me know…

So you’re using the web api’s then, which is out of scope for this article. In your Apple developer portal, though, you specify the redirect URI to use, and it’s kind of painful to get that all working.

Yes, It’s out of scope I know, all I want is help from someone who has implemented it for iOS 12 and older OS devices. Also we are having issue in backend as well to get key from .P8 file. Do you have any idea about it ?

@hidrodixtion @chipcastille @perlguy Do you still have issues with this?

Hi, I can’t remember offhand exactly what issue I was having. I will try to go back through the tutorial and see if things have changed.


I have a question, maybe is a stupid question but I can’t figure it out. I want to show the username in as text in my HomeView.swift. How can I get the username from the KeyChain?

@gargoyle Can you please help with this when you get a chance? Thank you - much appreciated! :]

@rahulvyas Do you still have issues with this?

@tommydr I wouldn’t do that, honestly. When you authenticate with your backend server have it send back the display name for the person and show that.