Sign in with Apple Using Vapor 4

In this Vapor 4 tutorial, you’ll learn how to implement Sign in with Apple with an iOS companion app and a simple website. By Christian Weinberger.

Leave a rating/review
Download materials
Save for later
Share

At WWDC19, Apple announced Sign in with Apple (SiwA), a new single sign-on (SSO) solution that allows users to set up an account with an app and website using their Apple ID, similar to the way you can log in with Google or Facebook.

Offering an SSO authentication method to your users will improve the first-time user experience, as a user won’t have to create yet another password to remember. Sign in with Apple even goes a step further: It allows users to hide their email addresses from apps and use relay email addresses instead. This is great for privacy!

In this tutorial, you’ll:

  • Learn how to validate an Apple identity token, provided by an iOS app, with your Vapor 4 back end.
  • Use this information to authenticate an existing user or create a new account for them.
  • Create a tiny website that allows users to sign in with Apple to achieve the same result without an iOS app.
  • Xcode 11 and Swift 5.2
  • A paid iOS developer account for setting up the required profiles, keys and certificates
  • An iOS 13 device, as the simulator does not always work properly
  • The ngrok CLI and a free account to connect your Sign in with Apple back end with your iOS app and to Apple’s Sign in with Apple services without deploying it.
  • A REST client to run requests against your back end. This tutorial uses Insomnia Core, but Postman, Paw, RESTed or even curl work fine.
Note: You’ll need the following for this project:

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.

Look in the starter directory and you’ll notice there are two folders with projects inside.

  • siwa-vapor: This is your Vapor 4 back end. You’ll use it to implement Sign in with Apple endpoints and the website.
  • siwa-ios: This is your iOS companion app. It already contains everything necessary to get an identity token from Apple. You’ll connect it to your Vapor 4 back end by adding its URL.

Now it’s time to inspect the project.

Looking at the Vapor Project

Open the Vapor app in Xcode by double-clicking the Package.swift file in siwa-vapor. While you wait for the Swift Package Manager (SPM) to resolve dependencies, check out the existing project in /Sources/App:

The project structure of the Vapor project.

There are a handful of things to pay particular attention to:

  1. siwa.leaf: This is the leaf template you’ll use to implement the Sign in with Apple front end.
  2. ProjectConfig.swift: This contains a couple of project-wide configurations. Your Sign in with Apple-related variables are loaded from environment variables, which you’ll set up later.
  3. Controllers: You’ll see two subdirectories — one for API controllers and one for view controllers. UserAPIController.swift allows you to retrieve the profile of an authenticated user. You’ll implement SIWAAPIController and SIWAViewController later.
  4. Migrations: You’ll find the migrations for User and Token here.
  5. Models: This contains various models used in the project.
  6. configure.swift: Here’s where anything required for this tutorial — such as Sessions, Leaf, Databases and Migrations — are set up.
  7. routes.swift: All routes required for your project are already set up. You’ll find anything user-related under /api/users. The Sign in with Apple endpoints will be under /api/auth/siwa, and you’ll find the Sign in with Apple front end at /web/auth/siwa.

A starter project with Bearer authentication is available in the project. You’ll implement an authentication flow using Sign in with Apple, in which you’ll return a Bearer token to your users that they can use for authentication.

Note: If you want to learn more about Bearer authentication, please read Vapor 4 Authentication: Getting Started by Natan Rolnik.

Running the Vapor Project

When SwiftPM finishes downloading all dependencies, select the Run scheme and My Mac as your platform. Then build and run.

Now switch to Insomnia, or your preferred REST client, and call GET http://localhost:8080/api/users/me:

Insomnia REST Client displaying the request to /api/users/me

You’ll notice your server returns 401 Unauthorized because the token-protected route expects a Bearer token in the authorization header. Also, there are no users in your database yet.

Setting up ngrok

To make your local back end available to both your iOS companion app and Apple — keeping in mind that web authentication requires a reachable callback — you’ll use ngrok. It will create an instant and secure URL that connects to your localhost server.

First, download the client from ngrok.com and move it to your /Applications folder.

Then, if you don’t yet have an account, register for free on ngrok’s signup page. Once you have an account, sign in and go to your dashboard to grab your authtoken from Authentication ▸ Your Authtoken.

Switch to Terminal and configure ngrok with your authttoken:

$ /Applications/ngrok authtoken {your auth token}

You successfully configured ngrok. Now run:

$ /Applications/ngrok http 8080

This will start an HTTP tunnel forwarding to your local port, 8080. In Terminal, you’ll see something similar to:

The running ngrok in Terminal.

Note: ngrok allows you to inspect incoming requests by clicking on the Web Interface link.

In Insomnia, replace localhost:8080 with the highlighted URL. If your server still runs, you’ll see the same response:

Insomnia REST Client displaying the request to /api/users/me, this time using the ngrok base URL.

Note: If you’re on the free tier of ngrok, the URL will change whenever you restart ngrok. Leave ngrok running throughout the tutorial, as both your iOS app and Apple’s callback for web authentication will use this URL.

Looking at the iOS App

Open the iOS app source by double-clicking SignInWithApple.xcodeproj in siwa-ios. You’ll find this structure:

Project structure of the iOS starter project.

There are only a few relevant files:

  1. ContentView.swift: This contains the code for showing the Sign in with Apple button. It’s capable of displaying errors and user profiles in an alert.
  2. SignInWithAppleDelegates.swift: This handles the callbacks from Apple’s ASAuthorizationController and calls the WebAPI.
  3. WebAPI directory: This contains the UserProfile model, as well as a small wrapper to make calls to your Vapor back end. The implementation for getting a profile is already provided. You’ll implement authorizeUsingSIWA(identityToken:email:firstName:lastName:completion:) later.
Note: The iOS starter project comes from our article, Sign in with Apple Using SwiftUI by Scott Grosch. Check it out if you want to understand more.