Skip to content

Get Started with EasyAuth

Ben Myers edited this page Apr 22, 2022 · 13 revisions

Overview

Welcome to EasyAuth! πŸŽ‰

EasyAuth makes it fast and easy to:

  • create user objects with pre-defined properties,
  • manage user details, including email, password, profile images, and unique usernames,
  • listen to user data updates from Firestore,
  • and sign in with third-party providers like Apple and Google.

Requisites

Example Project

This tutorial uses code that is demonstrated in the πŸ“• Example Project.

What You'll Learn

In this page, you'll learn about:

  1. Setting up authentication in Firebase Console β†’
  2. Setting up your user class β†’
  3. Pre-defined user properties β†’
  4. Adding custom user properties β†’
  5. Listening to updates β†’
  6. Creating an account β†’
  7. Signing in and out β†’

Get Started

Setting Up Authentication in Firebase Console

To get started, you'll need to set up Authentication in your Firebase console. Find the Authentication tab and click the Get Started button.

Add the Email sign-in method.

When you're finished, you should have the Email sign-in method enabled in your Sign-in Providers list.

Setting Up your User Class

In your project structure, create a new file for your User class. Import EasyFirebase. Then, declare your class. Ensure that your user class extends the EasyUser open class.

ExampleUser.swift

import EasyFirebase

class ExampleUser: EasyUser {
  
}

Pre-Defined User Properties

The EasyUser open class has several pre-defined properties. These properties should save you time from having to implement your own sign-in system. In this article, we'll only focus on using a few of these properties (marked with a ⭐️).

Property Name Description Settable?
notifications The user's Cloud Messaging Notifications. Yes
disabledMessageCategories The user's disabled Cloud Messaging categories. Yes
progress The user's onboarding progress. Yes
deviceToken The user's unique Cloud Messaging device token. No
appVersion The user's most recent version string, determined by the "Version" field of the app target. No
lastSignon The user's last sign-on date. No
⭐️ email The user's email address. No
⭐️ username The user's unique username. No
⭐️ displayName The user's (not necessarily unique) display name. No
profileImageURL A URL to the user's profile image. No
index The index of the user. Starts at 0 and increments for each user created. No
⭐️ id The user's unique id, obtained from FirebaseAuth's generated user ID. No
dateCreated The date upon which the user was created. No
ℹ️ Quick Tip If the user is signed out, it may be in a Guest User state. You can check to see if your global user object is actually a guest by checking the guest user's default values. In particular, a Guest User will have an id of "Guest", an email [email protected], and a username guest-user.

Adding Custom User Properties

Let's start by adding some custom properties to our ExampleUser class. In our example, we want to keep track of three things: the user's favorite food, their age, and whether they have a job.

ExampleUser.swift

class ExampleUser: EasyUser {
  var favoriteFood: String?
  var age: Int = -1
  var hasJob: Bool = false
}

Note that we define default values for each of these properties, except for the first. Doing so is necessary, except for Optional values.

⚠️ Note: All custom properties introduced to your own user object must be of types that conform to Codable.

When adding your own user properties, EasyAuth needs to know which properties should be encoded. So, you'll need to implement encode(to:), init(), and init(from:) within your custom user class, in addition to your CodingKeys:

ExampleUser.swift

class ExampleUser: EasyUser {
  
  var favoriteFood: String = ""
  var age: Int = -1
  var hasJob: Bool = false
  // (add more here!)
  
  // Implementation
  
  enum CodingKeys: String, CodingKey {
    case favoriteFood, age, hasJob
  }
  
  override func encode(to encoder: Encoder) throws {
    try super.encode(to: encoder)
    var container = encoder.container(keyedBy: CodingKeys.self)
    // do for each property!
    try container.encode(favoriteFood, forKey: .favoriteFood)
    try container.encode(age, forKey: .age)
    try container.encode(hasJob, forKey: .hasJob)
  }
  
  required init(from decoder: Decoder) throws {
    try super.init(from: decoder)
    let values = try decoder.container(keyedBy: CodingKeys.self)
    // do for each property!
    favoriteFood = try values.decode(String.self, forKey: .favoriteFood)
    age = try values.decode(Int.self, forKey: .age)
    hasJob = try values.decode(Bool.self, forKey: .hasJob)
  }
  
  required init() {
    super.init()
  }
}

Listening to Updates

Now, let's handle user data updates. EasyAuth handles a lot of the grunt work with auth state and user object updates. Any time the auth state changes, or any time the user object updates in Firestore, a callback to onUserUpdate is called. This also applies to the user's first sign-in, or account creation.

So, you'll need to start listening for these updates when your app launches. Wherever your app first launches, run the following code:

EasyAuth.onUserUpdate(ofType: ExampleUser.self) { user in
  // Check to make sure the `user` object passed in the closure is the right type, and is not `nil`
  guard let user = user as? ExampleUser else { return }
  // Set your global `user` instance used across the app
  global.user = user
}

⚠️ Note: As mentioned in Installation, you'll need to call EasyFirebase.configure() before running any of this code. Calling this directly before EasyAuth.onUserUpdate(perform:) is the best action.

To review, calling EasyAuth.onUserUpdate(perform:) will pass your user object to the closure when any of the following occur:

  • The user signs in or out
  • The user creates a new account
  • The user's data changes in Firestore

Creating an Account

Next up, we'll need to have the ability to create new user accounts. Create some text fields, then grab their inputs and store them in variables named emailField and passwordField. Then, pass their String values. The callback to the completion handler in createAccount(email:password:completion:) passes one value -- an Error?:

EasyAuth.createAccount(email: emailField, password: passwordField) { error in
  if let error = error {
    // Display your error to the user here
  } else {
    // No error, your account has been created, and you're signed in.
  }
}

If the error exists, display it. Otherwise, you're good to go-- Firebase Auth has created an account for you, and signed you in. The callback you created in EasyAuth.onUserUpdate should fire, and you should update your views to display the changed account status.

⚠️ Note: This example did not have the user confirm their password, and check their password strength: it's up to you to implement those features!

ℹ️ Quick Tip We don't yet have support for phone number sign-ins, but we plan to add it in the future. If you have knowledge of EasyFirebase and FirebaseAuth, feel free to contribute with your own code in a pull request! :)

Signing In and Out

Naturally, you'll need to implement sign-in. It's just about the same as creating an account:

EasyAuth.signIn(email: emailField, password: passwordField) { error in
  // ...
}

Signing out is even easier:

EasyAuth.signOut()

And that's it! You've activated and implemented Firebase Auth into your app to create accounts, sign in, and sign out.

Next Steps

πŸ”‘ Implement Sign In with Google

πŸ”‘ Implement Sign In with Apple

πŸ”₯ Get Started with EasyFirestore