Sending Push Notifications With Vapor

Adding push notifications to your app enriches the user experience by delivering data to their devices when it becomes available. In this article, you’ll learn how to send push notifications with Vapor. By Natan Rolnik.

5 (9) · 1 Review

Download materials
Save for later
Share

Adding push notifications to your app enriches your users’ experience by delivering data to devices as it becomes available, rather than forcing users to constantly fetch that data.

If you want to add push notifications to your app, third party services like Firebase or OneSignal are easy to set up. In many cases, though, using the Apple Push Notification Service — APNS — directly from your server is a better option.

Using APNS means you don’t need to use a third party SDK in your iOS app. Plus, it means you don’t share your users’ data with any third-party companies.

In this tutorial, you’ll learn how to connect to APNS and how to send push notifications with Vapor. You’ll learn how to send notifications to a specific user’s device as well as to many devices via subscription channels.

You’ll do this by working on an app called AirplaneSpotter, which tells aviation enthusiasts when airplanes are about to land at the airports that interest them.

For this tutorial, you’ll need the following:

  • An iOS device: Push notifications don’t work in a simulator, so you’ll need to use an actual device.
  • An Apple Developer Program membership: To send push notifications, you need a push notification certificate for your app, which requires a program membership.

Getting Started

After opening the Starter folder in the downloaded materials, you’ll notice that there are three directories: one for the Server app, one for the iOS app and another for code shared between these two.

Open Package.swift in the Server folder, either by double-clicking it on Finder or by running open Package.swift in Terminal. Xcode will open the Server app and start fetching all the required dependencies.

While Xcode is doing that, take the time to go over the existing code.

Start with the files in Sources/App/Models, which are: Airport.swift, Flight.swift and Device.swift.

In Migrations, you’ll see how to create each model and its associated properties in the database. You can add initial data in migrations as well, as shown in CreateAirport.swift.

Every model also has an associated controller, located in Controllers, which handles incoming requests.

After Xcode finishes resolving the project’s dependences, make sure you can run the project by selecting My Mac in the device pop-up and clicking the Run button — or by pressing Command-R.

Now, open the iOS starter project with Xcode and confirm that it compiles without any errors. Don’t run it yet, as the server isn’t ready, just press Command-B to build it. You can do this immediately, as it doesn’t have any external dependencies.

Understanding the Sample App’s Limitations

Before doing a quick recap of how APNS works, take a look at the limitations of this tutorial’s sample project:

  • Scaling pushes: A single instance of a server running on Vapor can send notifications without delays to a few thousand devices. If you need to send notifications to hundreds of thousands — or millions — of users, it’s worth building a queuing system on top of Vapor.
  • Users: This tutorial has no concept of a user; every device is a separate row in the database. If your app has a User entity, you’ll want to link every user to a list of Devices via a one-to-many relationship.
  • Authorization and authentication: In the routes of the sample project, there is no authorization required. In a real app, you’d protect the routes according to the user or admin permissions.
  • SQLite Database: This tutorial uses an on-disk SQLite database. In later stages of development, and certainly in production, you should use a scalable database running on a dedicated server. Good choices include PostgreSQL and MySQL.

Understanding and Configuring APNS

Now that you understand the differences between this sample project and one you could put into production, it’s time to take a look at how to set up APNS.

APNS Device Registration Flow

Apple’s documentation defines APNS in the following way:

The Apple Push Notification Service (APNS) is the centerpiece of the remote notifications feature. It is a robust, secure, and highly efficient service for app developers to propagate information to iOS (and, indirectly, watchOS), tvOS, and macOS devices.

The guide also mentions providers, which are the server counterparts of your app. They have three responsibilities:

  1. Receiving and storing the device tokens, which belong to instances of your app.
  2. Determining when and what to send to each device.
  3. Building and sending the payload to APNS containing the delivery information.

The figure below explains these steps:

The APNS device registration flow

The APNS token registration flow

The APNS device registration flow

Here’s the run down:

1A. Your app registers for remote notifications with APNS by calling UIApplication‘s registerForRemoteNotifications().

1B. APNS creates a unique device token and your app receives it via UIApplicationDelegate‘s application(_:didRegisterForRemoteNotificationsWithDeviceToken:).

1C. Your app converts the device token from Data to String and issues a request to your server to store it in the database.

2. Your server decides when the appropriate moment to send the notification is.

3A. The server builds the notification payload and submits it to APNS (for each device).

3B. APNS delivers the notification to the device.

Creating the APNS Push Key

Apple introduced push notifications with iOS 3. At that time, servers used a single certificate, exported as a .p12 file, to authenticate with APNS. Developers had to manually generate these certificates for each app in the Developer Portal and they were only valid for one year.

In 2016, Apple added a better way to manage authenticating with APNS: token-based connections, which use signing keys. In this context, the authentication token has no relationship with a device token.

This mechanism has a few advantages over certificates. The main one is that your server can use the same token to send notifications to multiple apps you own. Another advantage is that the key doesn’t expire, although it’s a good practice to revoke it and use a new one every once in a while.

Because this is now the recommended method, this tutorial uses an APNS key. To start generating one, go to https://developer.apple.com and log in with your credentials. In the left panel, under Program Resources, click Certificates, IDs & Profiles. In the left menu again, click Keys, then click the Plus button.

Certificates, IDs & Profiles screen with arrows pointing to the Keys tab and Plus button

The Register a New Key page will load. Give your key a name and select the APNS checkbox:

Register a New Key page with arrows pointing to the Key Name field and Enable button

Click Continue then click Register to confirm:

Register a New Key page with arrows pointing to the Register button

Once you’ve registered the new key, a Download button will appear. Download the file and use a text editor to open the key and copy the content.

Notice that the file name includes a ten character long identifier: This is the key identifier.

You now have everything you need to configure your server in the next section.

Important: The Developer Portal only allows you to download this key once. Store it in a safe place and make sure you have a backup.