Almost every application needs an authentication strategy. The most common being the classic username and password combo. However, there's a new approach some apps are taking to avoid handling or storing user passwords: passwordless authentication. It generally involves sending a one-time PIN (OTP) through a user-owned channel such as their phone or email. If the user inputs the correct PIN, we give them access to the system.
You can see the final result in the screenshot below and download the complete source code in the Passwordless Chat App iOS GitHub repository. Let's dive in!
To follow this tutorial, create an account with Stream, Auth0, and Ngrok. You'll also need Xcode, NodeJS, and Ngrok installed.
Stream takes care of the chat features, Auth0 provides the passwordless authentication we need, and Ngrok lets us quickly expose our local NodeJS backend to the external world via HTTPS.
- A Stream account account
- An Auth0 account
- An Ngrok account
- Node v14 installed
- Ngrok installed
- Xcode 12 or later
Auth0's free plan includes the passwordless feature, and if you're an independent developer or with a small team, you may be eligible for Stream's free maker account. So, remember to sign up for it!
Since we'll need some details of the iOS project to configure the Auth0 dashboard, let's first create a UIKit project on Xcode with the UIKit App Delegate lifecycle.
Before we can dive into the code, let's visit our Auth0 account to enable passwordless authentication and get the credentials we need.
After you've created your Auth0 account and you're in the dashboard, go to
Authentication > Passwordless and enable "Email". Also, make sure to set the Default App’s switch to “on” for passwordless authentication in the Applications tab. You can also use SMS if you have a Twilio account.
After you've enabled Email authentication, go to your Default App in Applications and copy your Domain and Client ID. We'll need these later in the iOS code section.
After that, scroll a bit down to
Application Properties and change your application type to
Once that's done, scroll further down to
Advanced Settings > Device Settings and paste your Team ID (DEVELOPMENT_TEAM) and App ID (PRODUCT_BUNDLE_IDENTIFIER), which you can find in your Xcode .pbxproj file, which is contained within the .xcodeproj file. To reveal the .pbxproj file, right click the .xcodeproj file and select Show Package Contents.
Next, move to the Grant Types tab, enable Passwordless OTP, and hit save.
After that, move to the Certificates tab, download your PEM certificate, name it
public.pem, and place it in the same folder as your backend's
index.js. You will use this certificate to verify the authentication request in your backend.
The backend consists of a single endpoint that generates a Stream JWT for a given user id. When the iOS app makes this request, it must also include an Auth0 ID Token to be verified. If the verification fails, we return 401 (Unauthorized) instead of the token. If it succeeds, we produce the Stream token, thus providing our user access to the chat feature under the given user id.
Install the dependencies with
npm install express stream-chat jsonwebtoken --save or
yarn add express stream-chat jsonwebtoken, then run your backend with
To access this endpoint outside our local machine and serve it under HTTPS (ideal for iOS apps), we can use Ngrok. You can install Ngrok through homebrew by running the command
brew install ngrok, or visit the Ngrok website. You'll also need an account and the auth token set up.
After you have Ngrok and your account set up, run
ngrok http 3000. If your backend is running on a different port than 3000, make sure to use that number instead. After you run the command, you should copy the https URL. You'll need it in the next section.
Add the following dependencies to your iOS project.
You can install the dependencies with Xcode's built-in Swift Package Manager integration or CocoaPods.
First, we need code to ask our backend for the JWT. You can write a stand-alone function that does it like below. Remember to replace the Ngrok URL. You can paste the function anywhere you want. For example, you can create a fetchStreamJWT.swift file and paste it there.
After that, we also need a function that creates our Chat's UI stack. After reading Stream Chat's iOS Tutorial, we can quickly write a stand-alone function that sets up our UI. As with the last function, you can create a makeChat.swift file and paste it there.
In the ViewController.swift file, we'll use Auth0's Lock.swift SDK to show the authentication UI. Once the user inputs the OTP, the
onAuth callback is triggered, giving us the Auth0 ID token. We then call
fetchStreamJWT to hit our endpoint and
makeChat to display our chat UI.
If everything is right and your backend is running, you should be able to run your project in a device or simulator. Type in your email, and you'll receive a code. After typing the code correctly and pressing submit, it will take you to the chat screen.
Congratulations! You've built the basis of a functioning passwordless chat app with Stream Chat and Auth0. I encourage you to browse through Stream Chat's docs, Auth0's iOS passwordless docs, and experiment with the project you just built. Good luck on your app development!