Build your first SwiftUI app (Part 5): Handling authorization

Dino Trnka
Ministry of Programming — Technology
6 min readJan 23, 2023

We have accomplished a lot! In the previous part of the series, we got the mock server running so we could send a request from our app and receive a JSON response.

However, currently, nothing happens when we successfully log in. We only print the access token to the console, and we don’t navigate to the home screen of the app as we should. In this article, we will handle authorization by implementing several functionalities. Our app needs to be able to securely save the access and refresh tokens. It also needs to navigate to the home screen after login, and it needs to remember our session when we log in, so we don’t have to enter a username and password each time we launch the app.

Let’s think about what we need to make this work.

Storing sensitive data in Keychain

First, we need a secure place to store our tokens. The best place to store these is the Apple Keychain. But instead of working with the keychain directly, we can simplify the process by using this handy SwiftKeychainWrapper library that takes care of all the heavy lifting for us.

So, let’s install this library by adding pod ‘SwiftKeychainWrapper’ in our Podfile and running pod install, just like we did before with our SwiftLint library.

Speaking of SwiftLint, we don’t want to receive any linter errors from our Pods, as we are basically treating them like black boxes and don’t care about their internal code. So, let’s exclude all Pods from linting by modifying our .swiftlint.yml script to look like this:

And before you say it, yes, I explicitly disabled the trailing_whitespace rule from the linter. It is a very annoying rule, don’t judge me. 😛

Next, we need to define a class that will handle our authorization. It needs to be able to:

  • Store our credentials (access and refresh token) in the keychain after user successfully logs in,
  • Retrieve the credentials from the keychain and check if user is logged in,
  • Delete the credentials from the keychain when user logs out.

Create the Auth class

Let’s create a singleton helper class called Auth in the Utilities folder:

This utility class makes use of the SwiftKeychainWrapper library to provide us with the basic authorization features. After a successful login, we will call the setCredentials() method and pass the tokens received from the response, so they are saved to the keychain. We will also set our loggedIn flag variable to true, as our root view will observe this variable for changes and navigate accordingly from the Login screen to the Home screen. More on that later. On logout, the tokens are removed from the keychain, and the loggedIn variable is set to false, which will cause our LoginScreen to show up again.

The code in the init() is very important for ensuring that users don’t have to go through the login process each time they start the app. If the access token is in the keychain on app start, then the loggedIn variable will be initialized to true, ensuring that the user skips the login screen and lands on the home screen.

Let’s modify our LoginViewModel now so that it uses the Auth class to set our credentials.

Looking good! Now we are storing our tokens in the keychain each time a user successfully logs in. But we are still stuck on our Login screen. We want to navigate to the Home screen instead, so let’s make that happen now.

Create the Home screen

In the Features/Home/Screens folder, create a file called HomeScreen.swift with the following contents:

It’s just a simple screen that shows a welcome message and a logout button. Our HomeViewModel is going to be extremely simple.

And here’s the updated Localizable file:

Enabling navigation

Now let’s implement the navigation. What do we want to accomplish? Our root screen needs to switch between the Login screen and the Home screen, depending on whether the user is logged in or not. As you might have guessed, we will check the value of the variable loggedIn in our Auth class.

What is our root screen, anyway? It is ContentView. But I like to keep ContentView clean and free of any logic because it’s our entry point to the app, so we will create another screen that will hold this logic instead. Let’s create a Root feature folder and add a RootScreen file to it:

Our screen will have the following code:

As you can see, we declared our observable Auth class instance as EnvironmentObject, which means we can listen to the changes in all of the Auth class fields that are marked as Published. In our case, we are interested only in the changes in the loggedIn variable. When this variable changes, our RootScreen will be redrawn to show the right screen (HomeScreen or LoginScreen), depending on what the new value is.

Now all that’s left is to connect our RootScreen with our ContentView. Note that whenever you use a class with EnvironmentObject property wrapper, you need to declare that class in the ancestor view with the environmentObject() modifier so that your app doesn’t crash when you access it. This is how the ContentView will look after our updates:

And that’s it! Let’s run the app to test how it works.

Voila! We got what we expected. We are navigated to the home screen after logging in, and even if we close and restart our app, it will remember that we were logged in and redirect us back to the home screen. Only if we click on the Logout button will we return to the Login screen.

Cleanup

We’ve finished what we wanted to do, so let’s do some cleaning up now. First, let’s look at the Auth class. We are holding our Credentials structure and our KeychainKey enum inside our Auth class, making it bigger than it needs to be. Let’s put them in their own separate files inside our Common/Models folder.

Next, let’s take a look at our Login and Logout buttons in our LoginScreen and HomeScreen views.

Apart from their background color, they have basically the same UI code! They have the same font size, font weight, button height, text color, and corner radius. So, let’s move this common code to a view modifier, so we can reuse this UI and also make our screens look cleaner. Create a ViewModifiers folder inside your Common folder, and add a file called MainButton.swift:

Now we can simply call this view modifier on our buttons.

Much nicer! You can use view modifiers to reuse common UI code in a very elegant way.

Demo project ❤️️

If you want to download a project that contains everything we’ve done so far, you can do it by clicking here.

Build your first SwiftUI app” is part of a series of articles designed to help you get started with iOS app Development.

If you have any questions on any of the above-outlined thoughts, feel free to share them in the comment section.

Click here to read Part 1.: Project setup
Click
here to read Part 2.: Project Architecture
Click
here to read Part 3.: Create the Login screen
Click
here to read Part 4.: Set up a mock server with Postman

Next part ⏭️

We've made a way to handle authorization, and in the next article, we'll improve our API request code by creating a reusable API request class that will be used in all of our actions! So, get ready for action! 😎

--

--

Dino Trnka
Ministry of Programming — Technology

Programmer, gamer, musician and all-around geek. I get hyped easily and love to share it with others.