In this lab, you'll learn how Firebase User Management works using Google SIgn-In as an example. With the skills you learn, you'll be able to quickly move on to using other providers such as Facebook and Twitter.

Using Xcode, create a new iOS App. Launch Xcode, and select ‘Create a new Xcode project' at the bottom of the screen. When asked for what type of application, select a ‘Single View Application'. Then, when asked to identify the application, be sure to remember the bundle identifier that is generated for you.

As you can see in the above screenshot, the bundle identifier is com.google.lmoroney.iOSAuthCodeLab. Remember yours, you'll need it later.

Select ‘Next', and then create the app. Keep note of the directory that it is created in. I'm using the Desktop for convenience.

Using Terminal, change to the directory containing your project and run pod init to initialize CocoaPods. You'll see that a file called Podfile is created for you:

Edit this Podfile, adding source directories for your pods, and the pods that you want to install. In this case, you'll need the ‘Firebase/Core', ‘Firebase/Auth' and ‘GoogleSignIn' pods. When you're done, your Podfile should look like this:

pod 'Firebase/Core'
pod 'Firebase/Auth'
pod 'GoogleSignIn'
target 'iOSAuthCodeLab' do
end

Next, run ‘pod install' using terminal. It will take a few moments, but the dependencies will be downloaded and installed for you. Your progress should look something like this:

You'll notice that this creates an ‘xcworkspace' file for you -- you should use that from now on for opening and editing your project. Before you start coding though, there's a few steps you need to follow on the Firebase Console. You'll do that next.

In the Firebase Console, you'll see a ‘Create new Project' button, like this:

Select it and create a new project. For the purposes of writing this codelab, I called it ‘iOS CodeLab', but you can use any suitable name.

Once you've created the project you'll be taken to the home screen. It will look like this:

At the top of the screen, you'll see an option to ‘Add Firebase to your iOS app'. Select it.

You'll be asked for your iOS Bundle ID, and an optional App Store ID. For the iOS Bundle ID, enter what was generated for you earlier. The App Store ID is optional, so you can leave it blank, or just enter a dummy value.

Select ‘Add App' and the Google Service Info plist file will be downloaded to your computer. Find your download folder, and drag the file from there to your Xcode project as shown.

Click through the rest of the wizard, and you'll see that your mobile app gets added to the Overview page of Firebase.

On the left hand side of the screen in the Firebase Console, you'll see a number of links to different technologies. Near the top is ‘Auth'. Select that. On the following screen, make sure ‘Sign In Method' at the top is selected. You'll see some Sign In providers underneath. Select ‘Google' from this list. A pencil icon will appear on the right. Click it, and you can edit the Google settings. It will look like this:

Click the switch to enable the API, and then Save. Firebase console is now ready for your app, so let's switch to Xcode to code and build it.

Now that you've set up your environment, and you've configured Firebase console, the next and final step will be to build your app to use Firebase Auth.

Set up your URL Schemes

Before continuing, find the GoogleService-Info.plist file from earlier and double click to open it. You'll need some of its settings in a moment.

In project explorer, select the project at the top of the window. Then, find the target selector -- in the red box in the below screenshot -- and ensure that the target is selected. It should have the same name as the project.

Once you've done this, find the ‘Info' tab, and at the bottom of the window you'll see ‘URL Types'. Click the ‘+' button to add a URL type. The box will expand, with fields where you can enter a number of pieces of data. The one you want is the URL Schemes entry field.

From the GoogleService-Info.plist, copy the value of the REVERSED_CLIENT_ID field into the URL Schemes box.

You also need to tell your app (via the App Delegate) how to handle these URLs.

At the top of AppDelegate.m, make sure that you import the GoogleSignIn library:

@import GoogleSignIn;
@import Firebase; 

Within the didFinishLaunchingWithOptions: function in the app delegate, you also need to initialize Firebase, like this:

[FIRApp configure];

Within the body of AppDelegate.m, you need to ensure that you are handling the openURL event:

-(BOOL)application:(UIApplication *)app 
    openURL:(nonnull NSURL *)url 
    options:(nonnull NSDictionary<NSString *,id> *)options{
        return [[GIDSignIn sharedInstance] 
          handleURL:url 
          sourceApplication:
             options[UIApplicationOpenURLOptionsSourceApplicationKey]        
          annotation:
             options[UIApplicationOpenURLOptionsAnnotationKey]];
}

Create your User Interface

Next you'll edit the Main.storyboard to add a GoogleSignIn button and a normal button for signing out.

To add a GoogleSignIn button, you first select the ‘Object Library' in the Storyboard View, and then find the ‘View' object.

Drag this and drop it onto the View Controller in the Storyboard. Note that you won't be able to see its contents, and just its sizing handles.

Also select the Identity Inspector, and ensure that the class is set to GIDSignInButton.

Now, select a Button in the Object Explorer and drag it onto the View surface. Size it so that it is similar to the View for the GIDSIgnInButton that you created earlier. It's a little tricky as you can't see the button, just its sizing handles, so just roughly the same will do.

Double click it when you're done, and you can set the caption -- change it to ‘Sign Out'.

Your view controller scene should look something like this:

Next, use the Assistant Editor button to open ViewController.h and the View Controller Scene side by side. Make sure that it's ViewController.h that is open on the right -- Xcode often defaults this to the .m file.

Holding the Control key down, drag the SignInButton view to the code, just below ‘@interface'. You'll see a popup appear:

Enter the text ‘signInButton' for the name, but leave the rest the same. In particular make sure that the connection type is ‘Outlet'.

Repeat this for the Sign Out button, but use ‘signOutButton' as the name.

Repeat again for the Sign Out button, but this time set the Connection type to be an Action, and set the name to be ‘signOutClicked' as shown here:

You will probably see an error on the signInButton property line. That's just because you don't have the required import yet. You can change this by adding importing GoogleSignIn.

Your ViewController.h should now look like this:

You'll need to make one more change, and that is to change the @interface declaration to use the delegates for sign in, and the sign in user interface. So edit the ‘@interface' line to this:

@interface ViewController : UIViewController<GIDSignInDelegate, GIDSignInUIDelegate>

The next step will be to write the code for the View Controller.

Coding the View Controller

Now that your view is designed, the next step is to write the code for the View Controller. Right now it probably looks something like this:

The signOutClicked at the bottom is based on the name you gave the action in the previous step. If you used a different name, that will show up here instead.

First, you'll need the imports for Firebase. Below the #import line, and above the @interface line, add the following code:

@import Firebase;
@import GoogleSignIn;

Next, in the viewDidLoad: function, you'll do some initialization. You'll do this by setting up a clientID for the application, setting the delegates for signing in, and UI based signing in to this view, and then disabling the signOut button. Add the following code:

[GIDSignIn sharedInstance].clientID = 
    [FIRApp defaultApp].options.clientID;
[GIDSignIn sharedInstance].delegate = self;
[GIDSignIn sharedInstance].uiDelegate = self;
_signOutButton.enabled = false;

Because you delegated sign in functions to this view, it will support the didSignInForUser function, which will get called back to after the user has gone through the sign in flow.

In this function, you will receive a GIDGoogleUser object. This has an ‘authentication' property that you can use to initialize a GIDAuthentication object. This in turn can be used to generate a FIRAuthCredential to authenticate against Firebase, which you can then sign into Firebase with. When you do that, the callback defined in the inline ‘completion' clause will run, and this simply extracts the user's displayName and creates an Alert Dialog with it.

It also disables the sign in button, and enables the sign out one.

-(void)signIn:(GIDSignIn *) signIn didSignInForUser:(GIDGoogleUser *)user 
                                   withError:(NSError *)error {
    if(error == nil) {
        GIDAuthentication *authentication = user.authentication;
        FIRAuthCredential *credential = [FIRGoogleAuthProvider 
                             credentialWithIDToken:authentication.idToken  
                             accessToken:authentication.accessToken];
        
        
        [[FIRAuth auth] signInWithCredential:credential 
            completion:^(FIRUser * _Nullable user, 
                         NSError * _Nullable error) {
            if(user){
                NSString *welcomeMessage = [NSString stringWithFormat:
                           @"Welcome to Firebase, %@", user.displayName];
                NSString *alertTitle = [NSString stringWithString:
                           @"Firebase Auth Codelab"];
                UIAlertController *alertController = [UIAlertController                         
                           alertControllerWithTitle:alertTitle
                           message:welcomeMessage                                      
                           preferredStyle:UIAlertControllerStyleAlert];
                UIAlertAction *okAction = [UIAlertAction                                         
                     actionWithTitle:NSLocalizedString(@"OK", @"OK action")
                     style:UIAlertActionStyleDefault
                     handler:^(UIAlertAction *action)
                         {  NSLog(@"OK action");}];

                [alertController addAction:okAction];
                [self presentViewController:alertController 
                      animated:YES completion:nil];

                _signInButton.enabled = false;
                _signOutButton.enabled = true;
            }
        }];
    } else {
        NSLog(@"%@", error.localizedDescription);
    }
}

Finally you will code up the action for signing out. This simply calls the fireBaseAuth sign out method, and when complete, re-enables the signInButton, and disables the Sign Out Button

- (IBAction)signOutClicked:(id)sender {
    // [START auth_signout]
    FIRAuth *firebaseAuth = [FIRAuth auth];
    NSError *signOutError;
    BOOL status = [firebaseAuth signOut:&signOutError];
    if (!status) {
        NSLog(@"Error signing out: %@", signOutError);
        return;
    }
    // [END auth_signout]
    _signInButton.enabled = true;
    _signOutButton.enabled = false;

}

Running the App

When you run the app in the emulator, you'll see the Sign In button is enabled, and the Sign Out button is disabled.

If you press the Sign In button, a browser window will open, where you sign in to your Google Account.

It will then ask for the account permissions:

Once you approve them, you'll be returned to the app, which will throw up an alert dialog with the full name of the user associated with that Google Account:

And that's it! You've just integrated secure sign in using Google Sign In in Firebase Auth. Well done!

You've taken your first steps into the world of federated authentication and identity. Well done! Some next steps to consider: