The Complete Guide to Implement Social Login With AWS Amplify
This blog post was published on PurpleBox website on Mar 30th, 2022.
This article is about how to set up a full-stack serverless ReactJS application using AWS Amplify with Google and Facebook Login functionality. We will also talk about the Amazon Cognito service for user authentication and authorization, how to set up serverless apps, hosting in AWS Cloud, managing state using React ContextAPI.
What is AWS Amplify?
AWS Amplify is a set of tools and services that can be used together or on their own, to help developers build scalable full-stack applications, powered by AWS. With AWS Amplify, you can configure app backends and connect your app in minutes, deploy static web apps in a few clicks, and easily manage app content in the AWS console.
AWS Amplify supports web and mobile applications where the developers can create and connect to a serverless backend hosted on AWS. To learn about the AWS serverless concept, you can check our previous article: How to Create Web Apps with AWS Serverless Microservice Patterns.
Amplify supports popular web frameworks including JavaScript, React, Angular, Vue, Next.js, and mobile platforms including Android, iOS, React Native, Ionic, Flutter. Today we are going to use Amplify with ReactJS.
Let’s take a look at the roadmap. In the first section, we will talk about creating a ReactJS App, creating an app backend with AWS Amplify, and hosting an app using AWS Amplify Console. The second and third sections are dedicated to creating Facebook and Google Apps. Then in the fourth section, we will configure our AWS Amplify project to add auth category. In this section, we will add the Amazon Cognito service to our app. After configuring the auth category we will configure Facebook and Google Apps in the fifth and sixth sections. Then we will continue with adding environment variables to our Amplify app in the seventh section. After that, we will configure our front end, add Login with Facebook and log in with Google buttons in the last section. In this section, we will also talk about ReactJS specific subjects such as Context API. We will use ContextAPI for holding user states and accessing these states from other components of our ReactJS App.
Let’s build it together.
Set up a React Application, Create an Amplify Project, and Add Hosting in AWS
a. Configure AWS Amplify CLI
To create, configure and edit amplify projects we will need to install and configure Amplify CLI. If you already have an AWS Amplify CLI you can skip this part.
We will run this command to install Amplify CLI
$ npm install -g @aws-amplify/cli
Then we will configure CLI.
$ amplify configure
You must have an AWS account and its credentials at this point. You can also follow the official getting started documents for step-by-step instructions.
b. Initialize a ReactJS app
We will use the create-react-app for our ReactJS app. Then change the directory and open the project with your favorite code editor. Start the development server and head to localhost:3000.
$ npx create-react-app amplify-social-signin-workshop$ cd amplify-social-signin-workshop/$ code .$ npm start
c. Create an AWS Amplify project
Now, we can create our app backend with Amplify CLI. Run the following command from the root directory of your ReactJS app.
$ amplify init
After running Amplify init command, Amplify CLI will collect information about your project. AWS Amplify can infer some information about your project from your configuration. For example, because we are using create-react-app language, framework and build commands are populated automatically. The initial result will look like this.
Type “Y” to continue, it will ask the authentication method and profile that you want to use. Select these according to your configuration.
It will take 3–5 minutes to initialize everything. After that, you will see a success message like this:
After successful initialization, you can log into the AWS console and open Amplify service, you will see that an Amplify Project is generated for you.
d. Install and configure AWS Amplify libraries
Now, we must install Amplify libraries to interact with our cloud resources from the client-side ReactJS application. We will use the NPM package manager at this point but if you prefer yarn, it is also a valid option.
We will install 2 Node packages:
- aws-amplify
- aws-amplify/ui-react
$ npm install aws-amplify @aws-amplify/ui-react
Next, we must configure our ReactJS app to recognize our AWS Amplify project using these packages. Open src/index.js and add the following code.
import {Amplify} from "aws-amplify";
import awsExports from "./aws-exports";Amplify.configure(awsExports);
The src/index.js should look like this:
import React from 'react'import ReactDOM from 'react-dom'import './index.css'import App from './App'import reportWebVitals from './reportWebVitals'//Configure Amplifyimport { Amplify } from 'aws-amplify'import awsExports from './aws-exports'Amplify.configure(awsExports)ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root'))reportWebVitals()
e. Hosting React App on AWS Amplify Console
First of all, commit and push your change to your Github repository. Then it is time to host our ReactJS app using AWS Amplify Console. To do this, head back to AWS Console and choose your app from Amplify Console. Select the Hosting Environments section. Choose Github and click Connect Branch.
Find your repository name and choose the main branch then click the Next button.
Choose the dev environment (that you created from CLI earlier). Choose a service role for AWS Amplify so that it can communicate with other AWS services on your behalf. if you do not have a service role, you can create it by clicking Create a New Role button. Then follow the guide to create the necessary IAM permissions for the service role. Then click next and on the summary page click Save and Deploy.
We completed our CI/CD pipeline now. After a successful build, you will see your application like this:
Congratulations! If you complete all instructions at this point you now have a serverless full-stack application on AWS Cloud. Also, you have an auto-generated domain name that looks like this https://{env}.{appID}.amplifyapp.com/
Let’s continue with creating our Google API App to use while signing in with Google Sign-In.
Create a Google API Project in Google Developer Console
We need a client ID and client secret to implement Login with Google functionality in our app. To get these credentials, we have to create a Google API Project from the Google Developer Console. Later, we will use them to connect with Amazon Cognito using OAuth2.0
- Go to Google Developers Console and log in with your credentials. If it is your first time in the console you may see some approval screens. Follow the instructions.
- Click Create Project and start your project.
- Once the project has been created, select the project and go to APIs and Services page and select the OAuth consent screen.
The consent screen is the screen that your users will see when they click the Login with Google button. So, you can configure it according to your application needs.
- We want our application to be accessible to everyone. So, select External for user type and click Create.
- Give your application a name. This name will appear to your users when they want to sign in with their Google account. Provide a support email for your users to contact you whenever they want. You can import your app logo, but it is not necessary for this step.
- You can give the app domain, privacy policy, and terms of service link to your application. It is not required at this step but if you do not provide it your app will not be approved later. Developer Contact information is a required section. Provide your email so that Google can contact you about incidents of your OAuth application. Then, click Save and Continue.
- In the scopes tab, you can define the user attribute scopes that you want to collect from Google such as first name, last name, and phone number. This is not required, and you can always edit afterward. So, click Save and Continue. You can skip the Test users tab also because we do not need test users now. In the summary section, you will see the details of your consent screen.
- Next click “Credentials”, create your OAuth2.0 credentials by choosing OAuth client ID from the Create credentials drop-down list.
- Choose “Web application” as the application type and name OAuth Client then click Create. Download as JSON your client id and secret for the next steps.
Now we have OAuth ClientID and Client Secret. Let’s continue with creating our Facebook App.
Create a Facebook Login App in Meta For Developers Console
- Go to Meta For Developers Console, create a Facebook developer account.
- Click the Create App button. Select Consumer as the application type for using Facebook Login App. Name your app and provide a contact email.
- Next, from the navigation bar choose Settings and then Basic. Copy your app id and app secret to use configure with Facebook Login and jump to the next step.
Add Auth Category to AWS Amplify Project
We now have Google and Facebook App IDs and App secrets. We also configure and initialize our Amplify project. So, we can add the auth category now.
a. Configure Amazon Cognito Service with Amplify CLI
Let’s implement the auth category of our project. Type “amplify add auth”, this command will ask specifications about your needs and create a User Pool and Identity Pool using Amazon Cognito. Amazon Cognito is an authentication and authorization solution service in AWS Cloud.
$ amplify add auth
This command will make us follow a series of steps:
- Do you want to use the default authentication and security configuration? Default configuration with Social Provider (Federation)
- How do you want users to be able to sign in? Username
- Do you want to configure advanced settings? No, I am done.
- What domain name prefix do you want to use? amplify-social-signin-workshop (give it a name or default one is also fine)
What are “redirect sign in” and “signout URIs”?
When authentication operations (sign in, sign out) are completed on Facebook or Google domains, Facebook/Google must redirect the user to our main page. These URIs define where users should be redirected after certain operations.
We provide both the localhost domain for development purposes and our default URL generated by AWS Amplify for production purposes. (Or your domain).
- Enter your redirect sign in URI: http://localhost:3000/
- ? Do you want to add another redirect sign in URI Yes
- Enter your redirect sign in URI: https://{YourEnv}.{YourAppID}.amplifyapp.com/
- ? Do you want to add another redirect sign in URI No
- Enter your redirect signout URI: http://localhost:3000/
- ? Do you want to add another redirect signout URI Yes
- Enter your redirect signout URI: https://{YourEnv}.{YourAppID}.amplifyapp.com/
- ? Do you want to add another redirect signout URI No
- Select the social providers you want to configure for your user pool: Facebook, Google
We created the Facebook Login app in the previous steps. You can find your Facebook App ID and App Secret in Meta For Developers Console.
- Enter your Facebook App ID for your OAuth flow: ***********************
- Enter your Facebook App Secret for your OAuth flow: *******************
We also created the Google API Project in the previous steps. Click API’s and Services section. You will see the Credentials tab in the left navigation. All credential-related information can be found there.
- Enter your Google Web Client ID for your OAuth flow: *******************
- Enter your Google Web Client Secret for your OAuth flow: ***************
b. Push Changes to AWS Cloud
We now successfully added auth resources locally. All our AWS Cloudformation templates that create back-end resources are ready. We must push these local configurations to AWS Cloud. So run amplify push command:
$ amplify push
- ? Are you sure you want to continue? Yes
After a few minutes, you will see a success message like this when everything is deployed in the cloud.
- ✔ All resources are updated in the cloud
This means you create an Amazon Cognito service, User Pool, and Identity Pool.
c. Copy OAuth Endpoint
We now have an OAuth endpoint that looks like this.
https://{your-domain}.auth.{your-region}.amazoncognito.com/”
You can find this OAuth endpoint in src/aws-exports.js. We will need this OAuth endpoint to configure our Facebook and Google Apps.
Configure Google API Project
We now have a valid OAuth endpoint so we can use this endpoint to configure our Google API Project.
a. Add Authorized JavaScript origins
Go to the Google developer console. Click credentials and select the OAuth 2.0 Client that you created earlier. Fill the Authorized JavaScript origins section with your OAuth endpoint.
“https://{your-domain}.auth.{your-region}.amazoncognito.com”
b. Add Authorized redirect URIs
Type your OAuth endpoint into Authorized Redirect URIs. Add /oauth2/idpresponse at the end of the domain.
“https://{your-domain}.auth.{your-region}.amazoncognito.com/oauth2/idpresponse”
Click Save and Google Oauth client is ready for use.
Configure Facebook Login App
a. Provide App Domains
Open Meta for Developer console and click Basic Settings. Paste the User Pool Oauth endpoint to the App Domains section. You should add your endpoint in following format:
{your-domain}.auth.{your-region}.amazoncognito.com
Then add your application domain into the App Domains section. Your domain should look like this: You can find it in the AWS Amplify dashboard.
https://{env}.{appID}.amplifyapp.com/
b. Add Web Platform
Scroll down to the Basic settings page and click Add Platform, choose the website, and click Next. Add the application domain to the Site URL section. The URL format should look like this:
https://{env}.{appID}.amplifyapp.com/
And click Save Changes.
c. Add Facebook Login Product
Click Products from the Side Bar. Click Add Product. Choose Facebook Login and click Set Up. Choose a Web Platform.
d. Provide Valid OAuth Redirect URIs to Facebook Login Product
Click Facebook Login from the side panel and choose Settings and add the OAuth endpoint to Valid OAuth Redirect URIs. The URL format should look like this.
“https://{your-domain}.auth.{your-region}.amazoncognito.com/oauth2/idpresponse”
e. Update Permissions and Features
Now we should update the permissions of our Facebook login Product to access the user’s email and public profile.
Click App Review from the left navigation menu and select Permissions and Features. Find public_profile and email attributes from the list. Click request advance access for both of them.
f. Make Facebook App live
There is a toggle input for App Mode at the top of the page. You should click “on” to make your app live. You should provide some information like the Privacy Policy URL, Terms of Service URL, etc. to switch live mode.
Add Environment Variables to Amplify Console
We have to provide our Facebook and Google ClientID and Client Secret Credentials as Environment Variables to Amplify Console. Because we do not store this information in source code for security purposes. So to build our app successfully from Amplify Console.
Go to AWS Amplify Console and select your Amplify App. From the left navigation select Environment Variables. Click Manage Variables and then Add variables.
Type these 4 variables and their values. And click Save. You can find their values in Facebook and Google developer dashboards.
- AMPLIFY_FACEBOOK_CLIENT_ID
- AMPLIFY_FACEBOOK_CLIENT_SECRET
- AMPLIFY_GOOGLE_CLIENT_ID
- AMPLIFY_GOOGLE_CLIENT_SECRET
For more details, you can check out the official AWS documents.
Setup Frontend, Add Login Buttons and Configure Context API
a. Listening to multiple Redirect URLs in index.js
We have 2 URLs. The first one is localhost for development purposes http://localhost:3000/, the second one is the production URL that is created in AWS Amplify Console. It should look like this: https://{env}.{appID}web.amplifyapp.com/
We should detect which is which before deciding to redirect the user. So import this code piece to the src/index.js file before calling Amplify.configure() function.
//Check if you are in localhost or productionconst isLocalhost = Boolean( window.location.hostname === 'localhost' || // [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' || // 127.0.0.0/8 are considered localhost for IPv4. window.location.hostname.match( /^127(?:.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ ))const signInURI = awsExports.oauth.redirectSignIn.split(',')const signOutURI = awsExports.oauth.redirectSignOut.split(',')if (isLocalhost) { awsExports.oauth.redirectSignIn = signInURI[0] awsExports.oauth.redirectSignOut = signOutURI[0]} else if (window.location.hostname ===
// Add Your Application Domain here. For Example:
// https://{env}.{appID}.amplifyapp.com/
) { awsExports.oauth.redirectSignIn = signInURI[1] awsExports.oauth.redirectSignOut = signOutURI[1]} else { console.alert('This is not possible')}//Check if you are in localhost or production//Then Configure ResourcesAmplify.configure(awsExports)
Update window.location.hostname variable according to your domain name. You can find it in the AWS Amplify Dashboard. It looks like this: https://{env}.{appID}
.amplifyapp.com/
b. Create a UserContext to store User Information
We could use React UseState Hook for managing user states. But in larger applications, you most probably need a better solution like Redux, Context. We will use React ContextAPI for holding the user state.
Create a /contexts folder in /src. You should create a JS file named UserContext.js in src/contexts. Your UserContext.js should look like this:
import { createContext, useState, useEffect } from 'react'
//Amplify package
import { Auth, Hub } from 'aws-amplify'
export const UserContext = createContext()
export const UserContextProvider = (props) => {
const [user, setUser] = useState(null)
const [progressCircle, setProgressCircle] = useState(true)
Hub.listen('auth', (data) => {
switch (data.payload.event) {
case 'signOut':
setUser(null)
break
case 'cognitoHostedUI':
// console.log('cognitoHostedUI', data)
break
default:
break
}
})
useEffect(() => {
Hub.listen('auth', ({ payload: { event, data } }) => {
switch (event) {
case 'cognitoHostedUI':
checkUser()
break
case 'signOut':
setUser(null)
break
}
})
checkUser()
}, [])
const checkUser = async () => {
try {
const responseUser = await Auth.currentAuthenticatedUser()
setUser(responseUser)
setProgressCircle(false)
} catch (error) {
setUser(null)
setProgressCircle(false)
}
}
return (
<>
{progressCircle ? (
'Loading'
) : (
<UserContext.Provider value={{ user, setUser }}>
{props.children}
</UserContext.Provider>
)}
</>
)
}
We are using Amplify Client libraries such as Auth, and Hub. We are listening to authentication events with the Amplify Hub module. So we can catch all auth events and set our local state according to it.
Now we have to import our User Context to the src/index.js file and wrap the App component with Context Provider. After that, we will be able to access the user state from any child component of our app.
Open src/index.js file and update this part of the code.
//Context imports
import { UserContextProvider } from './contexts/UserContext'
<UserContextProvider>
<App />
</UserContextProvider>
The final status of src/index.js file should look like this:
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import reportWebVitals from './reportWebVitals'
//Configure Amplify
import { Amplify } from 'aws-amplify'
import awsExports from './aws-exports'
//Context imports
import { UserContextProvider } from './contexts/UserContext'//Check if you are in localhost or production
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' ||
// 127.0.0.0/8 are considered localhost for IPv4. window.location.hostname.match(
/^127(?:.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
)
const signInURI = awsExports.oauth.redirectSignIn.split(',')
const signOutURI = awsExports.oauth.redirectSignOut.split(',')if (isLocalhost) {
awsExports.oauth.redirectSignIn = signInURI[0]
awsExports.oauth.redirectSignOut = signOutURI[0]
} else if (window.location.hostname === // Add Your Application Domain here. For Example:
// https://{env}.{appID}.amplifyapp.com/
) {
awsExports.oauth.redirectSignIn = signInURI[1]
awsExports.oauth.redirectSignOut = signOutURI[1]
} else {
console.alert('This is not possible')}
//Check if you are in localhost or production
//Then Configure Resources
Amplify.configure(awsExports)ReactDOM.render(
<React.StrictMode>
<UserContextProvider>
<App />
</UserContextProvider>
</React.StrictMode>,
document.getElementById('root')
)
reportWebVitals()
c. Inner App and Login Page Components
We can access the user state now. So we can write some logic that decides to show the Login Page if the user state is null or the Inner App component if there is a signed-in user in Context.
Open src/App.js and import this code:
import { useContext } from 'react'
//Context
import { UserContext } from './contexts/UserContext'
//Pages
import LoginPage from './Pages/LoginPage'
import InnerApp from './Pages/InnerApp'function App() {
const { user } = useContext(UserContext)
if (user) {
return <InnerApp />
} else {
return <LoginPage />
}
}export default App
Then we should create a Login Page component. In this component, we have 2 buttons for Facebook and Google buttons. We will add functionality to these buttons using the Auth module of the AWS-amplify package.
Create a Pages folder under src. Then create LoginPage.js, import this piece of code.
import { Auth } from 'aws-amplify'function LoginPage() {
return (
<div>
<h1>Login</h1>
<button onClick={() => Auth.federatedSignIn({ provider: 'Facebook' })}>
Sign In with Facebook
</button> <button onClick={() => Auth.federatedSignIn({ provider: 'Google' })}>
Sign In with Google
</button>
</div>
)
}export default LoginPage
What about signed-in users? We should show them inside of our app, maybe a signout button for now. Create an InnerApp.js file under the src/Pages folder and import this code:
import { Auth } from 'aws-amplify'function InnerApp() {
return (
<div>
<h1>Hello</h1>
<h3>Welcome to App</h3>
<button onClick={() => Auth.signOut()}>Sign Out</button>
</div>
)
}export default InnerApp
d. Testing the App
After completing all of these steps, commit and push your changes to Github. This action will trigger a build in Amplify Console. After our CI/CD pipeline completes you can visit the link of your application and try the Login with Facebook and log in with Google buttons.
If everything goes well you will see the InnerPage component. When you visit AWS Console and open the Amazon Cognito service you will see your signed-in user in the Users and Groups tab.
Summary
Congratulations we now have a full-stack serverless ReactJS App that has social login functionality on AWS Cloud. You can find the source code of this application on Github. If you have any questions or ideas feel free to open an issue.
We hope you enjoyed our how-to guide for social login with AWS Amplify. Check out our Devops services to stay secure!
If you want to read more on this topic, feel free to check out the PurpleBox Blog Section.