Set up an AWS Amplify app with Google Sign In
This article discusses how to set up an Amplify app with Google Sign In using a React app frontend. This will also mention how to configure multiple redirect URIs per app.
The first section is dedicated to boilerplate setup with React, Github, Amplify, and the Google developer console, while the second is about adding auth.
/** Skip the setup step if you’ve created an app already, and move right to the heading Add auth to Amplify app */
Set up React and Amplify
1. Create a new React app and GitHub repo, add a project in the Google developer console
On the command line
- Create a react app with
npx create-react-app google-test
,cd
into the app, and runnpm start
to start it on your local machine. - Create a new repo in GH for the app and push it to this repo.
In the AWS console
- Log into the AWS console and find the Amplify service.
- On the main Amplify page, select Get started and Deliver to create a web app or from the apps page, select New app and Web app.
- Select GitHub as the provider.
- Auth with GH if you haven’t.
- Choose repo and branch
main
. - Select default build settings. I use npm as a package manager so I changed from
yarn
tonpm
in thenpm start
andnpm run build
commands. - Save.
Your GH repo will be synced with the Amplify instance and continuous deploy will be set up —
In Google developer console
- Create a project and name it.
- In the APIs and Service page, select the Oauth consent screen tab.
- Set up OAuth consent screen with the required fields—these can all be changed later.
- Select the Credentials tab → Create credentials→ Oauth client ID
- Name the project and save it to get Oauth client ID and secret. I downloaded it as JSON to easily access it later.
2. Set up Amplify in the React app
On the command line
npm install -g @aws-amplify/cli
— install the Amplify CLI, which allows you to use CLI commands prefixed withamplify
.
In the AWS console
- In your project page, click the Backend env tab → Get started. This will initialize a backend environment.
- When it finishes, click the Local setup instructions dropdown and copy the CLI command:
amplify pull --appId {appId} --envName staging
On the command line
- Run the copied command.
- Sign in the Amplify Admin UI in the browser.
- Select the defaults, or the applicable choices for your project, from the options listed.
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path: src
? Distribution Directory Path: build
? Build Command: npm run-script build
? Start Command: npm run-script start
? Do you plan on modifying this backend? Yes
amplify pull
npm install aws-amplify
Add auth to the Amplify app
1. Add auth to the Amplify backend and finish setting up the Google Oauth consent screen
On the command line
amplify add auth
— we’re now adding the auth infrastructure to our app!- It will present a list of options—select Default configuration with Social Provider (Federation) to use social sign on with direct sign in, and select how else you want users to be able to authenticate (email, username, phone number).
Do you want to use the default authentication and security configuration? Default configuration with Social Provider (Federation)
Warning: you will not be able to edit these selections.
How do you want users to be able to sign in? Email
Do you want to configure advanced settings? No, I am done.
What domain name prefix do you want to use? googlesignin
Enter your redirect signin URI: https://main.dpdzznty4hgmh.amplifyapp.com/
? Do you want to add another redirect signin URI Yes
Enter your redirect signin URI: http://localhost:3000/
? Do you want to add another redirect signin URI No
Enter your redirect signout URI: https://main.dpdzznty4hgmh.amplifyapp.com/
? Do you want to add another redirect signout URI Yes
Enter your redirect signout URI: http://localhost:3000/
? Do you want to add another redirect signout URI No
Select the social providers you want to configure for your user pool: Google
- For the domain name prefix, you can use the default given, I just had a protected word,
aws
in mine so I had to change it. - For the redirect signin/signout URIs add, the URL of the Amplify app, which you can find the Frontend environments tab, with a structure like
main. ... .amplifyapp.com
. I added two redirect signin/signout URIs, one for the “deployed” URL, and one for localhost to test auth on my local machine. amplify push
❓ Q: What is a redirect signin/signout URI?
⁉️ A: When a user clicks Sign In with Google, they are taken to a page operated by Google, where their Google credentials are validated. If you look at the URL of this page it’s something like:
accounts.google.com/o/oauth…
. This means that once sign up is complete, the user has to be pushed back to the main site. This URL defines where that user will be pushed.
In React > src folder
- Once the updates are pushed, the
aws-exports.js
file in the/src
folder in will have updated with the Oauth config set in Amplify. - Copy the
domain
in the oauth object, e.g.googlesignin-staging.auth.us-east-2.amazoncognito.com
In Google developer console
- Credentials tab → Oauth 2.0 Client IDs → Click the pencil icon to edit your project.
- Add the copied domain as an authorized Javascript origin and redirect URI. At the end of the domain in the redirect URIs section, add
/oauth2/idpresponse
. This is not configurable, so you must add that fragment exactly.
❓ Q: What is the
/oauth2/idresponse
fragment for?⁉️ A: This is an existing endpoint from Amplify that handles redirects during Oauth sign in. Because your Amazon Cognito user pool URL is associated with your app, it can use this endpoint to send your users to the redirect you specified in your Amplify configs.
Use Sign In with Google on the frontend
1. Configure index.js to listen to multiple redirect URIs
- First we will import Amplify and the auth config into the React app and add some conditionals to detect which redirect signin/signout URI we will use by env.
- I roughly used the code example outlined in the Amplify docs here, under the Redirect URIs heading.
index.js
// add to existing imports
import Amplify from 'aws-amplify';
import config from './aws-exports';
// check if env is localhost or not
// if you're not developing on localhost, you will need to detect this is another way—the docs linked above give some examples. const isLocalhost = !!(window.location.hostname === "localhost");
// split redirect signin and signout strings into correct URIsconst [
productionRedirectSignIn,
localRedirectSignIn ] = config.oauth.redirectSignIn.split(",");const [
productionRedirectSignOut,
localRedirectSignOut ] = config.oauth.redirectSignOut.split(",");
// use correct URI in the right envconst updatedAwsConfig = {
...config,
oauth: {
...config.oauth,
redirectSignIn: isLocalhost
? localRedirectSignIn
: productionRedirectSignIn,
redirectSignOut: isLocalhost
? localRedirectSignOut
: productionRedirectSignOut, }
}
Amplify.configure(updatedAwsConfig);
You could avoid having multiple redirect URIs by ONLY enabling the auth to work on dev or production envs… but this seems like it will make testing/deployment more difficult.
- Some basic UI is needed to finish the example. I ran
npm i skylight-react
to use a basic component library I made, but the components used are up to you! To use the AWS UI library, install the@aws-amplify/ui-react
package too… I think this UI library is Simply Drab, but that’s subjective. - We will configure App.js to check if a user exists on each page refresh using the Amplify Auth class and listen for the auth events sign in and sign out using the Hub, which is an event listener component.
2. Listen for auth and store user in state
This sets up a basic config where if there is a user, they are directed to <UserHome/> and if not, a generic <Landing/> page.
- I’m storing the user in simple useState for this example, but larger apps would store the user with the useContext hook or a state management library.
App.js
import React, { useEffect, useState } from 'react';
import { Hub, Auth } from 'aws-amplify';
import { Loader } from 'skylight-react';
import './App.css';
import 'skylight-react/dist/skylight.css';
import Landing from './modules/Landing';
import UserHome from './modules/UserHome';function App() {// init state to store user and show loader const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
// get userasync function getUser() {
try {
const token = await Auth.currentAuthenticatedUser();
setLoading(false);
setUser(token);
} catch(err) {
console.log(err);
setLoading(false);
}
}//listen for sign in + out events, if neither are happening check if user exists useEffect(() => {
Hub.listen('auth', ({ payload }) => {
if (payload.event === 'signIn') {
return getUser();
} if (payload.event === 'signOut') {
setUser(null);
return setLoading(false);
}
});getUser();
}, []);
// show loading screen while fetching, otherwise return pageif(loading) return <Loader/>return (<div className="App"> {user ? <UserHome email={user.attributes.email}/> : <Landing/>}</div>)};export default (App);
- We check for the user on each sign in event or any pageload without a signout event. The
currentAuthenticatedUser()
method returns a CognitoUser class that has information about the user and their metadata. This object looks like this:
- The
attributes
property is an object that contains information about the user, like email. This is how to use theuser.attributes.email
properties to get the user’s email on the frontend. - If there is no auth user, nothing will be returned.
- See the resources section at the bottom for the dev docs to the Hub and Auth.
3. Make the Sign in with Google button and add to a landing page
- Download the assets or get the specs for the button from Google here.
import React from 'react';
import { Auth } from 'aws-amplify';
import btn from '../../assets/auth/btn_normal.png';const GoogleSignIn = () => {return (<button onClick={() => Auth.federatedSignIn({ provider:"Google" })}><img src={btn} alt="Google Sign In button" className="googleSignIn" style={{height:"45px", width:"190px"}}/></button>);}export default GoogleSignIn;
Landing.js
import React from 'react';
import GoogleSignIn from './auth/GoogleSignIn';
import { Flex } from 'skylight-react';const Landing = () => {return (
<Flex column center middle gap={1} height="100vh" width="100%"><h3>Authenticate to continue</h3><GoogleSignIn/></Flex>);
}export default Landing;
- Create a basic page for the authenticated users.
- Show the user’s email on the screen to prove they’re logged in.
4. Create a protected page only available to auth users
UserHome.js
import React from 'react';import { Flex } from 'skylight-react';const UserHome = ({ email }) => {return (<Flex center middle height="100vh" width="100%" gap={1}><h3>Hello, {email}.</h3><p>This route is for protected users :~)</p></Flex>);}export default UserHome;
- Push to GitHub and wait for the changes to sync in Amplify.
- This should work on both the URL given to us by AWS and localhost:3000!
- Click Sign in with Google
- Notice the name on the Oauth screen is amazoncognito.com, and not the app name configured. This is because our app is an unverified external app, and will have to be verified with Google to use the display name.
- Choose an account and be authenticated.
- To see the user, go to the Cognito service in the AWS console and click on User Pools → select your project → Users and groups
Here is our single user!
We are effectively done this guide. Some final things to think about …
- Amazon uses local storage to store ID, access, and refresh tokens. All of these can be seen by opening up local storage in your browser’s dev tools, inspecting it in JS, or running
const session = await Auth.currentSession()
and viewingsession
.
- Access and id tokens are 60 minutes by default but can be up to one day. Source.
- Refresh tokens can refresh access for 30 days since issue time, but can be set for 60 minutes to 10 years. Source.
Amplify references:
Amplify Oauth implementation docs—very comprehensive, see code examples
Auth docs ⚫️ Explanation of user retrieval methods—this is useful because the Auth API docs are poor
Hub docs ⚫️ Full list of Hub auth events that may be listened
Google Sign In button dev documentation
Social sign on references:
AWS | Social provider federation under the hood