ra-auth-google
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

ra-auth-google

An auth provider for react-admin that handles authentication using the Google Identity Services (GIS).

It allows to easily enable users to sign to your app in using their Google account, either personal, or professional via Google Workspaces.

ra-auth-google

This package provides:

  • An authProvider to use with your react-admin app
  • A <LoginButton> component to render the Sign in with Google button
  • A <OneTapButton> component to enable the One Tap feature on your website
  • An httpClient to make authenticated requests to your API
  • A helper method called initGoogleAuthProvider, allowing to get all the above from a single configuration object

Supported Features

The following features are not (yet) included in this demo, but should also be supported:

Limitations

Since they would require a back-end, the following features are not supported by this package:

It's up to you to implement these features in your back-end if you need them.

Installation

yarn add ra-auth-google
# or
npm install --save ra-auth-google

Basic Usage

The following example implements Sign in with Google button in popup mode, using the client id configured in the .env file.

# in .env
VITE_GOOGLE_CLIENT_ID="my-application-client-id.apps.googleusercontent.com"
<!-- in index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Add the following line to load the Google Identity Services library -->
    <script async defer src="https://accounts.google.com/gsi/client"></script>
  </head>
  <body>
    <!-- ... -->
  </body>
</html>
// in src/App.tsx
import React from "react";
import { Admin, Resource, Login } from "react-admin";
import { initGoogleAuthProvider } from "ra-auth-google";
import dataProvider from "./dataProvider";
import posts from "./posts";

const App = () => {
  const { authProvider, LoginButton } = initGoogleAuthProvider();

  const LoginPage = () => (
    <Login>
      <LoginButton theme="filled_black" />
    </Login>
  );

  return (
    <Admin
      authProvider={authProvider}
      dataProvider={dataProvider}
      title="Example Admin"
      loginPage={LoginPage}
    >
      <Resource name="posts" {...posts} />
    </Admin>
  );
};
export default App;

Tip: This example uses the <Login> component provided by react-admin to create the login page. You can also include the <LoginButton> component in your own login page if you prefer.

LoginPage

Providing Client ID Via Props

You can also provide the client id via a prop instead of using the .env file.

// in src/App.tsx
import React from 'react';
import { Admin, Resource, Login } from 'react-admin';
import { initGoogleAuthProvider } from "ra-auth-google";
import dataProvider from './dataProvider';
import posts from './posts';

const App = () => {
  const { authProvider, LoginButton } = initGoogleAuthProvider({
    client_id: "my-application-client-id.apps.googleusercontent.com",
  });

  const LoginPage = () => (
    <Login>
      <LoginButton />
    </Login>
  );

  return (
    <Admin
      authProvider={authProvider}
      dataProvider={dataProvider}
      title="Example Admin"
      loginPage={LoginPage}
    >
      <Resource name="posts" {...posts} />
    </Admin>
   );
};
export default App;

One Tap Button

The <OneTapButton> component can be used to enable the One Tap button on one or more pages.

OneTapButton

It can be used as a standalone component, or to wrap a page.

import { initGoogleAuthProvider } from "ra-auth-google";

const Standalone = () => {
  const { OneTapButton } = initGoogleAuthProvider();
  return (
    <div>
      <OneTapButton />
      <h1>My Page</h1>
    </div>
  )
};

const Wrapper = () => {
  const { OneTapButton } = initGoogleAuthProvider();
  return (
    <OneTapButton>
      <div>
        <h1>My Page</h1>
      </div>
    </OneTapButton>
  )
};

Here is a full example enabling the One Tap button on a custom route:

// in src/App.tsx
import React from "react";
import { Admin, Resource, Login, CustomRoutes } from "react-admin";
import { Route } from "react-router-dom";
import { initGoogleAuthProvider } from "ra-auth-google";
import dataProvider from "./dataProvider";
import posts from "./posts";

const App = () => {
  const { authProvider, LoginButton, OneTapButton } = initGoogleAuthProvider();

  const LoginPage = () => (
    <Login>
      <LoginButton />
    </Login>
  );

  return (
    <Admin
      authProvider={authProvider}
      dataProvider={dataProvider}
      title="Example Admin"
      loginPage={LoginPage}
    >
      <Resource name="posts" {...posts} />
      <CustomRoutes>
        <Route
          path="/custom"
          element={
            <div>
              <OneTapButton />
              <h1>My Page</h1>
            </div>
          }
        />
      </CustomRoutes>
    </Admin>
  );
};
export default App;

Customizing The Sign In With Google Button

Google does not support using your own button to sign in. However, you can customize the button, using the provided props, to better integrate it with your app.

LoginButton

You can also use the code generator to try out the different options.

For instance, here is how to use a black-filled button theme instead of the default one:

// in src/App.tsx
import React from 'react';
import { Admin, Resource, Login } from 'react-admin';
import { initGoogleAuthProvider } from "ra-auth-google";
import dataProvider from './dataProvider';
import posts from './posts';

const App = () => {
  const {
    authProvider,
    LoginButton,
  } = initGoogleAuthProvider();

  const LoginPage = () => (
    <Login>
      <LoginButton theme="filled_black" />
    </Login>
  );

  return (
    <Admin
      authProvider={authProvider}
      dataProvider={dataProvider}
      title="Example Admin"
      loginPage={LoginPage}
    >
      <Resource name="posts" {...posts} />
    </Admin>
   );
};
export default App;

Automatic Sign-In

You can enable Automatic sign-in by setting the auto_select param to true:

// in src/App.tsx
import React from "react";
import { Admin, Resource, Login, CustomRoutes } from "react-admin";
import { Route } from "react-router-dom";
import { initGoogleAuthProvider } from "ra-auth-google";
import dataProvider from "./dataProvider";
import posts from "./posts";

const App = () => {
  const { authProvider, LoginButton, OneTapButton } = initGoogleAuthProvider({
    auto_select: true,
  });

  const LoginPage = () => (
    <Login>
      <LoginButton />
    </Login>
  );

  return (
    <Admin
      authProvider={authProvider}
      dataProvider={dataProvider}
      title="Example Admin"
      loginPage={LoginPage}
    >
      <Resource name="posts" {...posts} />
      <CustomRoutes>
        <Route
          path="/custom"
          element={
            <div>
              <OneTapButton />
              <h1>My Page</h1>
            </div>
          }
        />
      </CustomRoutes>
    </Admin>
  );
};
export default App;

Configuring The Google Identity Services Library

initGoogleAuthProvider accepts all the parameters supported by the GIS library.

For example, to change the text of the title and messages in the One Tap prompt, use the context parameter:

// in src/App.tsx
import React from "react";
import { Admin, Resource, Login, CustomRoutes } from "react-admin";
import { Route } from "react-router-dom";
import { initGoogleAuthProvider } from "ra-auth-google";
import dataProvider from "./dataProvider";
import posts from "./posts";

const App = () => {
  const { authProvider, LoginButton, OneTapButton } = initGoogleAuthProvider({
    context: "use",
  });

  const LoginPage = () => (
    <Login>
      <LoginButton />
    </Login>
  );

  return (
    <Admin
      authProvider={authProvider}
      dataProvider={dataProvider}
      title="Example Admin"
      loginPage={LoginPage}
    >
      <Resource name="posts" {...posts} />
      <CustomRoutes>
        <Route
          path="/custom"
          element={
            <div>
              <OneTapButton />
              <h1>My Page</h1>
            </div>
          }
        />
      </CustomRoutes>
    </Admin>
  );
};
export default App;

Making Authenticated Requests To The API

ra-auth-google includes an httpClient that can be used to make authenticated requests to your API. This helper automatically adds the credentials token to the request headers.

Here is an example with ra-data-json-server:

// in src/App.tsx
import { initGoogleAuthProvider } from "ra-auth-google";
import jsonServerProvider from "ra-data-json-server";
import React from "react";
import { Admin, Login, Resource } from "react-admin";
import posts from "./posts";

const App = () => {
  const { authProvider, LoginButton, httpClient } = initGoogleAuthProvider();

  const dataProvider = jsonServerProvider(
    "https://jsonplaceholder.typicode.com",
    httpClient
  );

  const LoginPage = () => (
    <Login>
      <LoginButton />
    </Login>
  );

  return (
    <Admin
      authProvider={authProvider}
      dataProvider={dataProvider}
      title="Example Admin"
      loginPage={LoginPage}
    >
      <Resource name="posts" {...posts} />
    </Admin>
  );
};
export default App;

Choosing The Token Storage Strategy

By default, ra-auth-google will store the received token in localStorage, under the "token" key.

If you want to store it somewhere else, or need to use a different key, you can provide your own tokenStore:

// in src/myTokenStore.tsx
import { TokenStore } from "ra-auth-google";

export const myTokenStore: TokenStore = {
  getToken: () => localStorage.getItem("my_token"),
  setToken: (token) => localStorage.setItem("my_token", token),
  removeToken: () => localStorage.removeItem("my_token"),
};
// in src/App.tsx
import { initGoogleAuthProvider } from "ra-auth-google";
import jsonServerProvider from "ra-data-json-server";
import React from "react";
import { Admin, Login, Resource } from "react-admin";
import posts from "./posts";
import { myTokenStore } from "./myTokenStore";

const App = () => {
  const { authProvider, LoginButton, httpClient } = initGoogleAuthProvider({
    tokenStore: myTokenStore,
  });

  const dataProvider = jsonServerProvider(
    "https://jsonplaceholder.typicode.com",
    httpClient
  );

  const LoginPage = () => (
    <Login>
      <LoginButton />
    </Login>
  );

  return (
    <Admin
      authProvider={authProvider}
      dataProvider={dataProvider}
      title="Example Admin"
      loginPage={LoginPage}
    >
      <Resource name="posts" {...posts} />
    </Admin>
  );
};
export default App;

API

initGoogleAuthProvider

Use initGoogleAuthProvider to create an authProvider, a login button, a One Tap button and an httpClient from a single configuration object.

const { authProvider, LoginButton, OneTapButton, httpClient } = initGoogleAuthProvider();

It accepts the following parameters:

  • client_id: Optional - The Google API client ID of your application. Tries to use the GOOGLE_CLIENT_ID environment variable if not provided.
  • tokenStore: Optional - The token store to use to store the token. Defaults to localStorageTokenStore.
  • Other parameters: Optional - All the other parameters are passed to the Google Identity Services library. See the documentation for the full list of supported parameters.
const { authProvider, LoginButton, OneTapButton, httpClient } = initGoogleAuthProvider({
  client_id: "my-application-client-id.apps.googleusercontent.com",
  context: "use",
  tokenStore: myTokenStore,
});

googleAuthProvider

Returns an authProvider that can be used with react-admin.

It accepts the following parameters:

  • gsiParams: Required - Parameters for the Google Identity Services library. See the documentation for the full list of supported parameters.
  • tokenStore: Optional - The token store to use to store the token. Defaults to localStorageTokenStore.
const authProvider = googleAuthProvider({
  gsiParams: { 
    client_id: "my-application-client-id.apps.googleusercontent.com",
    ux_mode: "popup", 
  },
  tokenStore: myTokenStore,
});

<GoogleLoginButton>

Returns a component that can be used to render the Sign in with Google button.

It accepts the following props:

  • gsiParams: Required - Parameters for the Google Identity Services library. See the documentation for the full list of supported parameters.
  • sx: Optional - Allows to customize the MUI <Box> inside which the button is rendered. See MUI sx prop for more information.
  • Other parameters: Optional - All the other parameters are passed to the Sign in with Google button, and allow for customization. See the documentation for the full list of supported parameters.
const LoginButton = () => (
  <GoogleLoginButton 
    gsiParams={{ 
      client_id: "my-application-client-id.apps.googleusercontent.com"
    }}
    theme="filled_black"
  />
);

<GoogleOneTapButton>

The <GoogleOneTapButton> can be used either as a standalone component, or as a wrapper.

The component itself doesn't render anything, but it triggers the Google API to display the One Tap prompt if the user is not yet signed in.

Use it in the pages that you want to enable the One Tap feature on.

const Standalone = () => (
  <div>
    <GoogleOneTapButton />
    <h1>My Page</h1>
  </div>
);

const Wrapper = () => (
  <GoogleOneTapButton>
    <div>
      <h1>My Page</h1>
    </div>
  </GoogleOneTapButton>
);

It supports the following props:

  • children: Optional - The children to render. If provided, the component will be used as a wrapper.
  • Other parameters: Required - All the other parameters are passed to the Google Identity Services library. See the documentation for the full list of supported parameters.
const MyPage = () => (
  <div>
    <GoogleOneTapButton 
      client_id="my-application-client-id.apps.googleusercontent.com" 
    />
    <h1>My Page</h1>
  </div>
);

googleHttpClient

Returns an httpClient that can be used to make authenticated requests to your API.

It accepts the following parameters:

  • tokenStore: Optional - The token store to use to store the token. Defaults to localStorageTokenStore.
const httpClient = googleHttpClient({ tokenStore: myTokenStore });

Demo

You can find a working demo, along with the source code, in this project's repository: https://github.com/marmelab/ra-auth-google

License

This auth provider is licensed under the MIT License and sponsored by marmelab.

Readme

Keywords

none

Package Sidebar

Install

npm i ra-auth-google

Weekly Downloads

69

Version

1.0.0

License

MIT

Unpacked Size

112 kB

Total Files

58

Last publish

Collaborators

  • fzaninotto