How to Implement Sign In With SwiftUI and AWS Amplify

Part 1: Sign in with Google

Victor Sanchez
Mar 23 · 11 min read
A macbook with Xcode open
A macbook with Xcode open
Photo by Gustas Brazaitis on Unsplash

Why Use AWS Amplify/Cognito for Sign In?

There are many guides and resources on how to let users sign-in on iOS. From these, many use Firebase because it is quite simple.

While it might be true that it is simple and I’ve also used it in the past, there is a big limitation with this platform: you can’t use it in China. With the largest number of smartphone users in the world (over 800,000,000), it is certainly a country many don’t want to miss.

If we plan to grow and launch in China, we can’t do it while using Firebase. For a small team that wants to use mobile back end as a service initially, this can be a problem, especially in countries like Taiwan where Firebase works.

In Taiwan, developers may decide to do a soft launch locally first, being a smaller market where they can do several iterations of their app and improve based on user feedback, then launch in China after some growth, because it’s a culturally similar country.

In a case like this, it’s good to use a platform that can support usage in China from the start.

Of course, if you launch your app in China with multiple social media sign-in options, the user won’t be able to sign in with Google or Facebook, but it’s easier to remove those options for users in China and only allow providers like Apple or email than to change your whole back end.

Whatever your reason for wanting to use AWS for your mobile back end as a service, let’s get to it!

In this tutorial, I’ll assume we are starting an app from the very beginning and want to add authorization for users. I’ll go through the process of adding sign in with Google, Facebook, Apple, and email.


Setting Up

Before starting with the heavy work, you need to follow the Get Started guide if you are not familiar with AWS Amplify CLI. The steps are basically signing up for an AWS account, installing it, and configuring the CLI.

You can follow their Getting Started guide to get a head-start to how their GraphQL API works, and they even have a demo SwiftUI project.

If you are interested in preparing the sign in before getting to building APIs and sending data to your database, just follow this tutorial.

Let’s start by going to Xcode and creating a new project. Select Single View App. In Language, select Swift and in User Interface select SwiftUI. Give it the product name and organization name that you want.

Screen for creating a new project on Xcode. Here, SwiftUI is Selected for User Interface
Screen for creating a new project on Xcode. Here, SwiftUI is Selected for User Interface
Don’t forget to set SwiftUI for the user interface

After creating the project, take note of the bundle identifier for your project:

Where to find your Bundle Identifier inside your project’s Target
Where to find your Bundle Identifier inside your project’s Target
We will use this in a moment

Before being able to write our code to sign in with the different providers, you’ll need to create a project on the Google and Facebook Developer portals, since you’ll be asked for credentials from those providers.


Creating a Project in the Google Developers Console

To enable sign in with Google, we need to get OAuth credentials from them.

To do so, we go to Google Developers Console. Sign in with your Google account, then create a new project for your app. After that, go to your newly created project.

First, you need to go to the “OAuth consent” screen in the left menu and set up the required details before adding credentials.

Choose External as the User Type, then fill in the name of the app and click the Save button. You can fill in the additional details here or come back later to fill them in.

The options you need to access in the Google Developers Menu are OAuth consent screen and Credentials
The options you need to access in the Google Developers Menu are OAuth consent screen and Credentials
Here we just need to access the OAuth consent screen and credentials

After setting the consent screen, choose Credentials in the left menu. Select Create Credentials, OAuth client ID, and Web application. You can save the client ID and client secret or come back to the console to get them when you are asked for them.

Now, select Create Credentials, OAuth client ID, and iOS. Enter the bundle identifier you got after creating the project on Xcode. Again, you can save the created ID or come back to get it later.


Creating a Project on the Facebook Developers Console

To enable sign in with Facebook, we need to follow a similar process.

Go to the Facebook Developers Console. Sign in with your Facebook account. Go to My Apps, Create App.

Now, in the left menu, go to Settings, Basic. On the bottom, click on Add Platform, iOS, enter your project’s bundle identifier, then click on Save Changes.

Again, you can save the app ID and app secret or come back later to get them.

For now you just need to access Basic Settings in the Facebook Developers console for your app
For now you just need to access Basic Settings in the Facebook Developers console for your app
Here we just need to access Settings/Basic

Add Amplify to the iOS Project

In the terminal, go to the folder of the project you just created, then run the following command:

$ amplify init

The CLI will take us through some steps:

  • Enter a name for the project: Choose the default by pressing enter or enter your preferred project name.
  • Enter a name for the environment: Choose your preferred environment name, such as “local”.
  • Choose your default editor: Visual Studio Code (or your preferred editor).
  • Choose the type of app that you’re building: iOS.
  • Do you want to use an AWS profile? Y.
  • Please choose the profile you want to use: Choose your AWS profile.

After a while, you should receive a success message. Now that our project was created, you can check the AWS Amplify Console if you want and verify that it is there.

When clicking on your project and going to the Backend environments tab, you should see that the project has no enabled categories yet, as in the image below:

After you create a new amplify project, the console should display no backend environments
After you create a new amplify project, the console should display no backend environments
AWS Amplify console for a new project

Once you add Authorization, API, or Analytics, you should be able to access each of them from here.

Going back to the CLI, go to your project folder and run the command:

$ amplify add auth

Again the CLI will take us through a (little long) process:

  • Do you want to use the default authentication and security configuration? Default configuration with social provider (federation).
  • How do you want users to be able to sign in? Username.
  • Do you want to configure advanced settings? Yes, I want to make some additional changes.
  • What attributes are required for signing up? Email, name, picture*.
  • Do you want to enable any of the following capabilities? Skip.
  • What domain name prefix do you want us to create for you? Default or choose as you please.
  • Enter your redirect sign in URI: Myapp://.
  • Do you want to add another redirect sign in URI? N.
  • Enter your redirect sign out URI: Myapp://*.
  • Do you want to add another redirect sign out URI? N.
  • Select the social providers you want to configure for your user pool: Facebook, Google.
  • Enter your Facebook app ID for your OAuth flow: Enter the Facebook app ID you got before.
  • Enter your Facebook app secret for your OAuth flow: Enter the Facebook secret ID you got before.
  • Enter your Google Web Client ID for your OAuth flow: Enter the Web Client ID you got before.
  • Enter your Google Web Client secret for your OAuth flow: Enter the Web Client secret you got before.

*Note that here, I selected email, name, and picture as required attributes so I can display those details to the user. Choose attributes as you like, just noticing which ones are available for the log-in providers you use.

*We use myapp:// as a redirect URI because we want to go back to the app after signing in.

Now you can run the command:

$ amplify push

After some time, you should receive a success message. You can click on the link to test the auto-generated test UI.

This will try to redirect you to myapp:// though, which you can’t do in the browser. But if you had a valid redirect website to redirect you to after sign In, the test UI would take you there.


Finish Setting Up Sign In With Google

Now let’s go back to the Google Developers Console. In the credential lists, edit the Web Client.

In Authorized JavaScript origins, add the HostedUI Endpoint you just got from the AWS CLI, without the “/” at the end. It should look something like this:

https://yourswiftuiamplifyprojectf9af9929f9af9929-local.auth.us-east-1.amazoncognito.com

In Authorized redirect URIs, add the same HostedUIEndpoint, with /oauth2/idpresponse at the end. It should look like this:

https://yourswiftuiamplifyprojectf9af9929f9af9929-local.auth.us-east-1.amazoncognito.com/oauth2/idpresponse

Now you can save the web client credentials.

You need to get the iOS URL scheme from the iOS credentials. You can view it by clicking on the edit button, then copying it from the top-right corner.

You need to click on the edit button in order to see the iOS URL Scheme
You need to click on the edit button in order to see the iOS URL Scheme
Click on the edit button shown on the picture to view your iOS Credential details
The iOS URL Scheme should be on the top right corner, just after the Client ID
The iOS URL Scheme should be on the top right corner, just after the Client ID
Your iOS URL scheme should look like this

Finish Setting Up Sign In With Facebook

We also need to add the endpoints to our Facebook app.

Go back to the Facebook Developers Console. Go to Settings, Basic. Scroll down and select Add Platform, Website, then enter the HostedUIEndpoint, with /oauth2/idpresponse at the end:

https://yourswiftuiamplifyprojectf9af9929f9af9929-local.auth.us-east-1.amazoncognito.com/oauth2/idpresponse
On the bottom of the settings in Facebook Developers console, you should press “Add Platofrm” and insert the mentioned URL
On the bottom of the settings in Facebook Developers console, you should press “Add Platofrm” and insert the mentioned URL
Setting up website platform

Scroll up and in App Domains enter the same HostedUI Endpoint with /oauth2/idpresponse at the end, then save changes.

Next, in the left menu, choose Products, Facebook Login, Set Up. Choose iOS, ignore the quickstart and choose Settings, under Facebook Login in the left menu:

On Facebook Developers, access Facebook Login Settings on the Left Menu
On Facebook Developers, access Facebook Login Settings on the Left Menu
Now we just need to access Facebook Login/Settings

In Valid OAuth Redirect URIs, enter the Endpoint with idpresponse at the end:

https://yourswiftuiamplifyprojectf9af9929f9af9929-local.auth.us-east-1.amazoncognito.com/oauth2/idpresponse

Save changes, and now we can go on to the next step!


Edit Info.plist

Open your Info.plist file in a text editor so you can view it as an XML file. On the top of the file, add the following just after the beginning of the dictionary:

Keys you need to add to your Info.plist file

A few notes here, under CFBundleURLTypes, pay attention to add the letters fb before your app ID. Down, under FacebookAppID, you don’t need to add the letters fb. Your Info.plist file should look something like this:

A screenshot of how your Info.plist file should look
A screenshot of how your Info.plist file should look
Info.plist after adding the details above

Add Required Pods to the iOS Project

To add CocoaPods, in your project folder, run the following command:

$ pod init

Open the generated Podfile in a text editor and add the following Pods:

Now install them by running the command:

$ pod install --repo-update

Open your project .xcworkspace and let’s (finally) get to actually writing some Swift code!


Copy AWS Configuration Files Into Xcode

Before being able to use the AWSMobileClient, you need to copy two files to Xcode: awsconfiguration.json and amplifyconfiguration.json.

Drag them into your project and uncheck “Copy items if needed”, so you only keep a reference to the original files. This way, if you update your Amplify configurations, the reference you have on Xcode will keep track of those changes.

Your project should look like this:

A screenshot of Xcode showing all the files inside the Project now
A screenshot of Xcode showing all the files inside the Project now
Overview of files currently in Project

Initializing the AWS Mobile Client

In your AppDelegate, add the following import at the top:

import AWSMobileClient

Inside the AppDelegate class, add this function to initialize the AWS Mobile Client:

Code to initialize AWSMobileClient inside App Delegate

And of course, don’t forget to class that function on the application didFinishLaunchingWithOptions before the return. Your AppDelegate should look like this:

Screenshot of how the AppDelegate file should look after initializing the AWS Mobile Client.
Screenshot of how the AppDelegate file should look after initializing the AWS Mobile Client.
Don’t forget to call initializeAWSMobileClient()!

You can test that the AWS Mobile Client is initializing correctly by running your app in the simulator. You should see the following on the console:

AWSMobileClient initialized. Current UserState: signedOut

Creating the SwiftUI View

Open ContentView.Swift. Let’s add a VStack with a Button inside to sign in with Google.

Simple VStack with Google Sign In Button

For now, the button is not doing anything besides printing something in the console when running in your simulator or on your device. Feel free to add any styles to your buttons!


Sign In With Google

In order to use the AWSMobileClient methods with SwiftUI, we need to use it in a UIViewControllerRepresentable. Create a file named SignInViewController.swift, and add the following to it:

UIViewControllerRepresentable for Sign In Methods

A little explanation about this code. We create a UINavigationController above because the AWSMobileClient expects one to show the UI for each provider.

Note that when we set the hostedUIOptions, we set “email” and “profile” to get the additional details we ask from them (like name and profile picture).

let hostedUIOptions = HostedUIOptions(scopes: ["openid", "email", "profile"], identityProvider: "Google")

After signing in successfully, we get the userState. If we want to get the requested details above (email, name, profile picture), we need to do some extra work.

Documentation and forum answers suggest using AWSMobileClient getUserAttributes or AWSCognitoIdentityPool getDetails, but they are not working at the time of this writing (March 2020).

That’s why I chose to get the information from the JSON claims on this line:

AWSMobileClient.default().getTokens { (tokens, error) in …

Now we need to add the SignInViewController to our ContentView. Modify the body so it returns the SignInViewController in a ZStack under the VStack we already had, like this:

Adding SignInViewController to ContentView

After this, you can run the project in the simulator or on your device. Once you sign in successfully, you will see the user details being printed in the console.

Now you know that you are signed in, and if you restart your app you should see the following message after launch:

AWSMobileClient initialized. Current UserState: signedIn

Let’s do something more interesting. Let’s change to another screen after sign in.


Switching to Another Screen After Login

To propagate the changes through the app, I chose to create an ObservableObject called AppSettings. This will store details such as the username.

You can add other details of the user here, for example email or a URL to their profile picture. Create a file called AppSettings.swift, and add the following:

AppSettings to access User Defaults

Inside your ContentView, before the body, add this variable:

@ObservedObject var settings = AppSettings()

Now let’s change the body so the View shows a different message after signing in:

Showing a message on ContentView after Sign In

If the username is set on AppSettings, the app will show you a different message.

I also added two buttons to sign out here. One so you can sign out if you had done so before setting the username. The second one is displayed after you sign in, so you can sign out and test other sign-in methods.

I also added Dividers, so the Buttons are a little apart from each other.

Now, as you might have noticed, we didn’t set the username anywhere after signing in. Let’s go back to the SignInViewController and fix this. Add the following variable on the top, just before the navController:

@ObservedObject var settings = AppSettings()

And just after the print statements where you are getting username, email, and picture, add the following:

We need to set this variable inside the main queue because it is triggering some changes to the UI.

If you build your app, you will notice an error. Now we need to pass the settings ObservedObject to the SignInController:

let signInVC = SignInViewController(settings: settings)

Now, after running your app, press the sign out button if you were already signed in before, then try signing in and out to see the changes on the screen. Now you know how to add auth services to your apps with AWS!

If you want to take a look at the whole project, please check out the GitHub Repo.

Better Programming

Advice for programmers.

Victor Sanchez

Written by

MSc Information Systems. BSc Control Engineering. iOS Developer. Always learning. https://www.linkedin.com/in/victorrsanchezj/

Better Programming

Advice for programmers.

More From Medium

More from Better Programming

More from Better Programming

More from Better Programming

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade