Integrating Google Firebase Auth

Google Firebase offers a host of utilities and services for mobile and web development. One of them is Firebase Authentication, a versatile authentication system, which neatly integrates with static websites as well as single-page apps, and offers most of the sign-in methods visitors have gotten used to: via email credentials, or identity providers such as Google, Facebook, Twitter or Github, and a couple more. Additionally, with classic email-based authentication, signing up and recovering one’s password is possible as well.

In this tutorial, we are going to show you how to integrate Firebase Auth into the Scrivito Example App. We’ll do this by providing you with a widget that fully encapsulates all of the Firebase Auth functionality needed. To follow along with us, you’ll require a Google account, a Scrivito CMS (including a working copy to experiment with), and a locally installed Example App connected to this CMS.

Before we start, notice that Firebase Auth uses OpenID as a default for managing email/password sign-ups and sign-ins. Again as a default, for selecting an email account to sign in with, the Firebase UI redirects to accountchooser.com, which refuses to load in Scrivito’s UI iframe. So, for testing the live behavior of the sign-in UI, publish the working copy and remove “scrivito/” from the URL path.

Create your Firebase project and set up authentication

Getting started with Firebase is easy. At the time of writing, you’ll be on the “Spark” plan initially, which is free.

  • Open the Firebase homepage in your browser and log in if you haven’t done so already.
  • Click GET STARTED. Your existing projects (if any) will be displayed.
  • Click Add project.
  • Fill in the form and click Create project.
  • After your project has been provisioned, click Continue. This will take you to your Firebase Console.
  • In the Firebase Console, open the Develop section and click Authentication. You should see a screen like this:

Have you noticed the Web setup button at the top right? You don’t need to click it right now, but keep in mind that this is where to look up the Firebase Auth configuration for your app later on.

Next, take the suggested action and set up the sign-in methods you wish to support:

For this tutorial, we’ve enabled only two providers, “Email/password” and “Google”. To set up a sign-in method, click the corresponding provider, enable it, and specify the required pieces of data, e.g. the App ID for Facebook or Twitter.

Next, scroll down to view the “Authorised domains” section. For now, nothing needs to be altered here as “localhost” covers your local development environment. Later, after deploying your app, come back to this screen and add the domain for which your Firebase Auth project should be authorized.

Also, take a look at the “Users” and “Templates” tabs at the top. The former lets you add and remove users, or reset their respective password, should this be required. The latter is for defining the contents of the emails to be sent to users after signing up with their email credentials, or after they started the password recovery procedure.

Create the Firebase Auth widget

Luckily, a React wrapper around the Firebase UI is available. We are going to use the provided code to build our Scrivito widget from it. But let’s first install the required modules.

Install the Firebase modules

In our React app, we require the UI package and the base package: In a terminal window, change to the project directory of your Scrivito Example App, then:

Copy
npm install --save react-firebaseui
npm install --save firebase

Define the FirebaseAuthWidget model class

If you haven’t worked with Scrivito components yet, you might want to take a look at the Introduction to Creating and Rendering Pages and Widgets (or any of the more basic Developer Guides) first.

A Scrivito widget is comprised of two mandatory parts and one optional part. The mandatory parts are a widget model class definition and a component for rendering instances of it. For widgets requiring some configuration on the editor’s side, an editing configuration can be provided. The Scrivito SDK expects those parts to be specifically named files located in a widget-specific directory underneath “src/Widgets”.

Let’s call our widget “FirebaseAuthWidget” and define its model class.

Basically, we are merely registering the widget class with Scrivito here. We’re providing it with two attributes, one for customizing the welcome message to display after signing in, and the other for the text on the sign-out button:

src/Widgets/FirebaseAuthWidget/FirebaseAuthWidgetClass.js
Copy
import * as Scrivito from "scrivito";

const FirebaseAuthWidget = Scrivito.provideWidgetClass("FirebaseAuthWidget", {
  attributes: {
    welcomeText: "string",
    signoutText: "string",
  },
});

export default FirebaseAuthWidget;

Yes, that’s all. Scrivito.provideWidgetClass creates a widget class declaring the attributes its instances will be equipped with.

Define the FirebaseAuthWidget editing configuration

As indicated, we want to enable editors to customize the welcome text and the sign-out button text, so let’s make the above attributes known to the Scrivito editing UI:

src/Widgets/FirebaseAuthWidget/FirebaseAuthWidgetEditingConfig.js
Copy
import * as Scrivito from "scrivito";
import buttonWidgetIcon from "../../assets/images/button_widget.svg";

Scrivito.provideEditingConfig("FirebaseAuthWidget", {
  title: "Firebase Authentication",
  thumbnail: buttonWidgetIcon,
  attributes: {
    welcomeText: {
      title: "Welcome text",
      description: "Displayed after signing in, prepended to user name"
    },
    signoutText: {
      title: "Sign-out text",
      description: "Text on sign-out button"
    }
  },
  properties: [
    "welcomeText", "signoutText"
  ],
  initialContent: {
    welcomeText: "Signed in as",
    signoutText: "› Sign out",
  },
});

The title and thumbnail are used in the widget selection dialog that opens when adding a widget to a page (for brevity, we are reusing the thumbnail of the “ButtonWidget” here), whereas the other keys define the contents of the properties view. For details, see Scrivito.provideEditingConfig.

Create the  FirebaseAuthWidget component

The code below constitutes the React component for rendering FirebaseAuthWidget instances. It utilizes the Firebase UI.

src/Widgets/FirebaseAuthWidget/FirebaseAuthWidgetComponent.js
Copy
import * as React from "react";
import * as Scrivito from "scrivito";
import StyledFirebaseAuth from "react-firebaseui/StyledFirebaseAuth";
import * as firebaseui from "firebaseui";
import firebase from "firebase";

class FirebaseAuthWidgetComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isSignedIn: false // Local signed-in state
    };

    // Configure FirebaseUI.
    this.uiConfig = {
      // "popup" sign-in flow rather than "redirect" flow
      signInFlow: "popup",
      // We will display Email and Google as auth providers.
      signInOptions: [
        firebase.auth.EmailAuthProvider.PROVIDER_ID,
        firebase.auth.GoogleAuthProvider.PROVIDER_ID
      ],
      credentialHelper: firebaseui.auth.CredentialHelper.ACCOUNT_CHOOSER_COM,
      // or NONE, or GOOGLE_YOLO for one-tap sign-in
      // signInSuccessUrl: '/welcome',
      callbacks: {
        // Avoid redirects after sign-in
        signInSuccessWithAuthResult: () => false
      }
    };

    this.onSignoutClick = this.onSignoutClick.bind(this);
  }

  // Listen to the Firebase Auth state and set the local state
  componentDidMount() {
    this.unregisterAuthObserver = firebase
      .auth()
      .onAuthStateChanged(user => this.setState({ isSignedIn: !!user }));
  }

  // Make sure we un-register Firebase observers when the component unmounts
  componentWillUnmount() {
    this.unregisterAuthObserver();
  }

  onSignoutClick() {
    firebase.auth().signOut();
  }

  render() {
    if (!this.state.isSignedIn) {
      return (
        <div>
          <StyledFirebaseAuth
            uiConfig={this.uiConfig}
            firebaseAuth={firebase.auth()}
          />
        </div>
      );
    }
    return (
      <div>
        <i className="fa fa-user-circle-o fa-1x" aria-hidden="true"></i>
        {` ${this.props.widget.get('welcomeText')} `}
        <strong>
          {`${firebase.auth().currentUser.displayName} `}
          <a
            href="#"
            className="text-danger initialism"
            role="button"
            onClick={this.onSignoutClick}
          >
            {this.props.widget.get('signoutText')}
          </a>
        </strong>
      </div>
    );
  }
}

Scrivito.provideComponent("FirebaseAuthWidget", FirebaseAuthWidgetComponent);

Instances of our widget wouldn’t work without having initialized Firebase. As mentioned, you can obtain the configuration needed for this from your Firebase Console: In the Develop / Authentication section, click Web setup at the top right, and copy the contents of the second <script> element to the clipboard.

Then create a file, “src/config/firebase.js”, and add the following initialization code to it, using your configuration from the clipboard:

src/config/firebase.js
Copy
// Configure Firebase
import firebase from "firebase";

firebase.initializeApp({
  apiKey: "IzaSy_BxCdNBnWfAO4c7TGPUZjKRz8_oT0B7B6Y",
  authDomain: "fir-auth-scrivito.firebaseapp.com",
  databaseURL: "https://simple-auth-fire.firebaseio.com",
  projectId: "fir-auth-scrivito",
  storageBucket: "fir-auth-scrivito.appspot.com",
  messagingSenderId: "745853197965"
});

For the code in this file to be executed at startup, import it via “index.js” in the same directory.

Finally, let’s take a closer look at the “FirebaseAuthWidgetComponent” definition (including the Firebase UI configuration):

  • The component is set up as a React component class, which is passed to Scrivito.provideComponent to make it known to Scrivito.
  • The isSignedIn state variable is updated after signing in and out, causing the Firebase UI to be re-rendered correspondingly.
  • The Firebase UI is configured using the uiConfig instance variable, which is passed to the StyledFirebaseAuth component in the render method. Next to the sign-in methods (signInOptions), the UI config includes various options for fine tuning the behavior of the Firebase UI.
  • Firebase Auth lets you manage users via the Firebase Console as well as create email/password-based user accounts and access the current user’s data programmatically. This is great for taking care of users individually after they signed in. You can also provide your own forms for signing up and in via email credentials. See Manage Users in Firebase for details.
  • Our component configures the Firebase UI to use the ACCOUNT_CHOOSER_COM credentialHelper. For one-tap sign-up and automatic sign-in with email-based authentication, try GOOGLE_YOLO, which, however, at the time of writing, has not been released for production use.
  • After signing in, the welcomeText and signoutText widget attributes are rendered together with the currentUser’s displayName. Feel free to improve the design, add further attributes, etc.

Final words

One of the most compelling aspects of Google Firebase Authentication is that you can simply set up a project, and Google takes care of the rest: storage space, database, user management, etc. The numerous integration options, the versatile API, a highly configurable user interface – all this is awesome, and we only scratched the surface here. Using the Admin Auth API, you could even integrate an external user system or import and export users, to name just a few of its benefits. Just for the fun of it, in a terminal window, from within your project directory, execute:

Copy
firebase --project fir-auth-scrivito auth:export users.json --format=json

Happy authenticating!