Werner Digital

Technology

Amplify UI

Take advantage of the amplify UI for authentication tools in Gatsby without amplify theme

Contents

Executive Overview

Amazon amplify-ui has some great building blocks to jumpstart your development with secure authentication themed to your site. Using AWS Cognito as a backend, you can always swap it out with more custom code in the future.

Tech Overview

Secure front-end coupled with AWS Cognito backend.

Install

Requirements

  • npm add aws-amplify @aws-amplify/ui-react

Basic use

-import { AmplifyAuthenticator } from '@aws-amplify/ui-react';
+import { Authenticator } from '@aws-amplify/ui-react';
+import '@aws-amplify/ui-react/styles.css';
...
-        <AmplifyAuthenticator>
         <ThemeProvider theme={theme}><CssBaseline enableColorScheme />
+              <Authenticator>
+        {({ signOut }) => { return (
...
+
+        )}}
+      </Authenticator>
         </ThemeProvider>
-        </AmplifyAuthenticator>

Headless

Headless allows pages to be excluded from authentication and provides a method for using hooks to get authentication information without invoking the Auth amplify api. Headless changes include setting up a provider that wraps the app in gatsby-browser:

import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
...
 export const wrapPageElement = ({ element, props }) => {
     return (
       <Authenticator.Provider>
         <Layout {...props}>
           {element}
         </Layout>
       </Authenticator.Provider>

gatsby-ssr also needs changes to reflect the new DOM structure in gatsby-browser: (note the lack of css import)

import { Authenticator } from '@aws-amplify/ui-react';
...
 export const wrapPageElement = ({ element,props }) => {
   return (
    <Authenticator.Provider>
       <Layout {...props}>
         {element}
       </Layout>
    </Authenticator.Provider>
 )};

changes to the layout component include adding the useAuthenticator hook (to get auth information without invoking auth api) and accessing the location name which we will use to explicitly bypass authent on some pages.

Note: use authStatus to make sure the page re-renders when authStatus changes. The user object cannot be used because the user object doesn't undergo any shallow changes when the authentication status changes.

layout.tsx:

import { Authenticator, useAuthenticator } from '@aws-amplify/ui-react';

const Layout = ({ children }: LayoutProps) => {
const Layout = ({ children, location }: LayoutProps) => {
    const { authStatus } = useAuthenticator(context => [context.authStatus]);
    ...
    return(
        <Authenticator>  {({ signOut }) => { return (
        { (authStatus !== 'authenticated' && location?.pathname !== '/') ?
           ? <Authenticator /> :
           ... rest of page as normal

Authenticator parms

  • hideSignUp={true}

useAuthenticator

values

  • signOut function
  • toResetPassword function
  • user
    • username
  • error
  • validationErrors

Jest mocks

mocks/@aws-amplify/ui-react.js

import React from 'react';

export const Authenticator = props => {
    return (<div data-testid='authenticator'>{props.children}</div>);
}

export const useAuthenticator = props => {
    const user = {
        username: 'testusr',
    }
    return ({ user });
}

Customize Colors

use this pattern in your layout component:

const root = window.document.documentElement;
root.style.setProperty('--amplify-colors-background-primary', '#f2eee2');

or if you prefer add via css. Example:

:root {
  --amplify-primary-color: #eeeeee;
  --amplify-primary-contrast: #444464;
  --amplify-primary-shade: #444444;
  --amplify-primary-tint: #444444;
}

add --amplify- to the following:

  • colors-background-primary - background

  • colors-border-primary', 'var(--amplify-colors-blue-90)');

  • colors-border-focus', 'var(--amplify-colors-blue-60)');

  • components-button-primary-background-color', 'var(--amplify-colors-blue-60)');

  • components-button-primary-hover-background-color', 'var(--amplify-colors-blue-80)');

  • components-button-primary-active-background-color', 'var(--amplify-colors-blue-20)');

  • colors-font-primary', 'var(--amplify-colors-black)');

  • colors-font-interactive', 'var(--amplify-colors-blue-60)');

  • components-button-color', 'var(--amplify-colors-blue-60)');

  • components-button-hover-color', 'var(--amplify-colors-blue-60)');

  • components-button-hover-border-color', 'var(--amplify-colors-blue-90)');

  • components-button-hover-background-color', '#f5ce28');

  • components-button-link-hover-color', 'var(--amplify-colors-blue-60)');

  • components-button-link-hover-background-color', '#f5ce28');