Letting Visitors Log in with Google

[New in 1.7.0] Scrivito supports logging in to a website as a visitor via identity providers such as Google. This allows you to provide selected content only to those having identified themselves towards your site.

In this tutorial, we are going to show you how to integrate visitor authentication into your website. We will use a third-party package for this and add a “Log in with Google” button to the top navigation of the Scrivito Example Application.

To follow along, authentication via Google needs to be set up first in your Google account and on your CMS dashboard. For details on how to accomplish this, see Setting up Identity Providers for Your Website. It's easy.

All that’s needed here is the ID of your authentication client at Google.

The package we will be using is react-google-oauth, which has been derived from react-google-login. It provides us with an API component as well as customizable log-in and log-out components. Events allow us to make logged-in visitors known to Scrivito. Only then, restricted content will be made available to those visitors.

How it works

For Scrivito to let logged-in visitors see restricted content, the SDK needs to be put into visitor authentication mode. This can be done in a call to Scrivito.configure which must be called when the application initializes, i.e. immediately after it has been loaded into the browser. As a consequence, the app needs to reload after a visitor has logged in. Then, the visitor’s access token originating from the identity provider needs to be passed to the SDK so that restricted pages can be delivered based on the validity of the token.

Turning visitor authentication on

To be able to turn “visitor authentication” mode on when the app is loaded, we need to determine whether the visitor has already logged in or not. In our LoginWithGoogle component we are going to show you below, we’ll persist the login state in the browser’s local storage and set a constant for accessing it, visitorLoggedInWithGoogle. This allows us to switch authentication on or off during the initialization phase:

src/config/scrivito.js
Copy
import * as Scrivito from "scrivito";
import { visitorLoggedInWithGoogle } from "../Components/LoginWithGoogle";


var config = {
  tenant: process.env.SCRIVITO_TENANT,
  visitorAuthentication: visitorLoggedInWithGoogle,
};

if (process.env.SCRIVITO_ORIGIN) {
  config.origin = process.env.SCRIVITO_ORIGIN;
}

Scrivito.configure(config);

Providing the Login Component

As mentioned, our component is based on the react-google-oauth package, so let’s install it first. Switch to the root of your project directory, then run:

Copy
npm --save i react-google-oauth

As the components in this package use Google’s API, the corresponding URL or domain, “apis.google.com”, needs to be added to the “script-src” section of the content security policy, which is defined in “public/_headersCsp.json”. Also, the component uses button images from “csi.gstatic.com”.

Now, in your project’s “src/Components” directory, create the component file and add the following code to it:

src/Components/LoginWithGoogle.js
Copy
import * as React from "react";
import * as Scrivito from "scrivito";
import {
  GoogleAPI,
  GoogleLogin,
  GoogleLogout,
  googleGetAuthResponse,
} from "react-google-oauth";

const CLIENT_ID =
  "468795843720-6akgnpes5b4lo9582c7na52i7r2ac55k.apps.googleusercontent.com";

export const visitorLoggedInWithGoogle = !!window.localStorage.getItem(
  "loggedInWithGoogle"
);

function setGoogleVisitor({ idToken }) {
  if (visitorLoggedInWithGoogle) {
    Scrivito.setVisitorIdToken(idToken);
  } else {
    window.localStorage.setItem("loggedInWithGoogle", "yes");
    window.location.replace(window.location.href.replace(/404\?path=\%2F/, ""));
  }
}

function clearGoogleVisitor() {
  window.localStorage.removeItem("loggedInWithGoogle");
  if (visitorLoggedInWithGoogle) {
    window.location.reload();
  }
}

class LoginWithGoogle extends React.Component {
  render() {
    return (
      <GoogleAPI
        clientId={CLIENT_ID}
        onUpdateSigninStatus={isSignedIn => {
          if (isSignedIn) {
            setGoogleVisitor({ idToken: googleGetAuthResponse().id_token });
          } else {
            clearGoogleVisitor();
          }
        }}
        onInitFailure={clearGoogleVisitor}
      >
        {visitorLoggedInWithGoogle ? (
          <GoogleLogout text="Log out" width="160px" />
        ) : (
          <GoogleLogin text="Log in" width="140px" />
        )}
      </GoogleAPI>
    );
  }
}

export default LoginWithGoogle;

The GoogleAPI component is for initializing Google’s API and provides us with two events, onUpdateSigninStatus and onInitFailure. Inside GoogleAPI, either a GoogleLogin or a GoogleLogout component is rendered, depending on the login state we are setting and clearing via the onUpdateSigninStatus callback.

Logging in

After successfully clicking the login button, the onUpdateSigninStatus callback is executed, causing setGoogleVisitor to be called. If no visitor has been logged in before, setGoogleVisitor persists the new login state in the local storage and reloads the page.

The reload causes the app to be initialized and, of course, the components to be rendered again. This time, the call to Scrivito.configure enables visitorAuthentication, and setGoogleVisitor calls setVisitorIdToken to pass the ID token to the SDK.

Logging out

If the visitor actively logs out, the new login state is persisted by removing loggedInWithGoogle from the local storage. Then the page is reloaded, causing visitorAuthentication to be set to false in Scrivito.configure. If the page last viewed by the visitor is restricted, the 404 error page will be displayed. 

Integrating the LoginWithGoogle component

Now that we have the component, let’s use it in the Scrivito Example App! For having a means to log in available wherever the visitor enters our site, we will add the component to the top navigation bar.

Open “FullNavigation.js” in “src/Components/Navigation/” and add the import statement as well as the component to this file as indicated:

src/Components/Navigation/FullNavigation.js
Copy
// Other imports
import LoginWithGoogle from "../LoginWithGoogle";

class FullNavigation extends React.Component {
⋮
          <Collapse isOpen={this.state.expanded} navbar>
            <div className="navbar-collapse">
              <LoginWithGoogle />
              <Nav
                closeExpanded={this.closeExpanded}
                expanded={this.state.expanded}
              />
            </div>
          </Collapse>
⋮

That was it! After starting your app, you should see the log-in button in the navigation bar. Clicking it opens Google’s sign-in dialog.

Enhance it!

If you don’t want the log-in/out button to be displayed to logged-in editors, there’s Scrivito.isEditorLoggedIn to conditionally hide it. Note that the SDK doesn’t apply restrictions if an editor is logged in.

The component lets you access the user profile sent by Google after logging in. You could display some pieces of this data, e.g. the user’s name, in addition to the logout button.

If you would like to have the login/logout functionality available as a widget, put the GoogleAPI component in your application file (App.js), and implement the widget around the buttons.