Server-Side Sign in with Apple

Nov 15 2022 · Swift 5.6, macOS 12, iOS 15, Xcode 13.3

Part 1: Add Sign in with Apple to an iOS Project

05. Authenticate Existing Users with Sign in with Apple

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 04. Connect Your iOS App to Your Vapor App Next episode: 06. Setting up Sign in with Apple for the Web

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 05. Authenticate Existing Users with Sign in with Apple

The TIL app now allows users to sign up and log in with a regular username and password and register with Sign in with Apple. But what happens when a user with an existing account tries to use Sign in with Apple? At the moment they’ll get an error because their user already exists. It’s time to fix that!

Handling existing users

If the Vapor app is still running from the previous video, stop it with CRTL+C and open Package.swift to open the project in Xcode. Navigate to UsersController.swift and find the signInWithApple(_:) route handler. Here you want to see if you can find the user using their email before creating a new one:

if let existingUser = try await User.query(on: req.db).filter(\.$username == email).first() {
    
} else {

}

Wrap the existing register logic in the else block:

let newUser = User(name: name, username: email, password: UUID().uuidString, siwaIdentifier: siwaToken.subject.value)
try await newUser.save(on: req.db)
user = newUser

If the user already exists in the database, set the user to the found user, update the user’s siwaIdentifier and then save the user:

user = existingUser
user.siwaIdentifier = siwaToken.subject.value
try await user.save(on: req.db)

Now, if an existing user tries to Sign in with Apple they’ll be able to. It’s important to note that this only works if the user provides their email to the app - if they choose Sign in with Apple and choose to hide their email, they’ll have a separate account created as there’s no way for the backend to link the existing account.

Trying it out

To try this out, first you need to reset the database so you can register via the normal means:

swift Scripts/dockerDB.swift reset

This stops the existing Docker container, deletes it and recreates it so you have a fresh database to start with. Build the Vapor app and run it via Terminal:

swift run

Again if the firewall asks you to allow connections, click Allow. Next, You need to reset Sign in with Apple for the app, otherwise iOS will not send the necessary data to the backend. In iOS go to Settings, your iCloud account, Password & Security and Apps Using Apple ID. Find your iOS app and tap on it and click Stop using Apple ID.

Now, you can create a user using a REST client like Paw, send a POST request to /api/users to register the user. You must pass a name, username and password in the request body. The username must be your email address that you use for your iCloud account.

Send a GET request to /api/users to ensure the user exists. Then, run the app on your Apple Device. You can just relaunch it from iOS, you don’t need to run it via Xcode. If you’re already loggen in, go to the Users tab and tap Log Out. Sign in with Apple and you’ll be logged in. Send a GET request to /api/users again and you’ll get just the one user returned as the Vapor app found your existing user and linked it with Sign in with Apple!