Social login (via Google, Facebook, Apple, etc.) is one of the easiest ways to boost user adoption and simplify onboarding. Instead of asking users to remember another password, you let them sign in using identities they already trust. Amazon Cognito makes this process straightforward by handling OAuth2 and identity federation behind the scenes — all you need to do is configure it correctly and plug it into your app. This post walks you through setting up Social Login in AWS Cognito, integrating it into your app, and handling the OAuth2 callback + token exchange using Node.js.
What Is Amazon Cognito?
- User Pools – Handle user management (sign up, sign in, MFA, password policies, etc.)
- Identity Pools (Federated Identities) – Allow access to AWS resources using federated identities from external providers.
Step 1: Create a Cognito User Pool
- Open AWS Console → Cognito → Create user pool
- Name it (e.g., myapp-user-pool)
- In Sign-in experience, enable Federated sign-in
- Add the social providers you want to support
Step 2: Configure a Social Identity Provider (Google Example)
- Go to your User Pool → Federation → Identity providers
- Select Google
- Paste your Client ID and Client Secret from Google Cloud Console
- Save changes
Step 3: Set Callback and Logout URLs
- Callback URL(s) → where Cognito redirects users after successful login e.g.,
https://myapp.com/callback - Sign-out URL(s) → where Cognito redirects after logout e.g.,
https://myapp.com/logout
Step 4: Using the Hosted UI
https://<your-domain>.auth.<region>.amazoncognito.com/login?client_id=&response_type=code&scope=email+openid+profile&redirect_uri=https://myapp.com/callback
Step 5: Handling the Callback and Exchanging Tokens
1. Install dependencies
npm install express axios qs dotenv
2. Create .env
COGNITO_DOMAIN=https://your-domain.auth.ap-southeast-1.amazoncognito.com
COGNITO_CLIENT_ID=xxxxxxxxxxxxxxx
COGNITO_CLIENT_SECRET=yyyyyyyyyyyyyyyy
COGNITO_REDIRECT_URI=https://myapp.com/callback
3. Create server.js
import express from "express";
import axios from "axios";
import qs from "qs";
import dotenv from "dotenv";
dotenv.config();
const app = express();
app.get("/callback", async (req, res) => {
const code = req.query.code;
if (!code) return res.status(400).send("Missing authorization code");
try {
const tokenUrl = `${process.env.COGNITO_DOMAIN}/oauth2/token`;
const data = qs.stringify({
grant_type: "authorization_code",
client_id: process.env.COGNITO_CLIENT_ID,
code,
redirect_uri: process.env.COGNITO_REDIRECT_URI,
});
// Cognito expects Basic Auth header with client_id and client_secret
const authHeader = Buffer.from(
`${process.env.COGNITO_CLIENT_ID}:${process.env.COGNITO_CLIENT_SECRET}`
).toString("base64");
const response = await axios.post(tokenUrl, data, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: `Basic ${authHeader}`,
},
});
const { id_token, access_token, refresh_token } = response.data;
// Decode the JWT ID token (you can also verify signature later)
const userInfo = JSON.parse(
Buffer.from(id_token.split(".")[1], "base64").toString("utf-8")
);
res.send(`Login successful!`);
} catch (err) {
console.error(err);
res.status(500).send("Token exchange failed");
}
});
app.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
How It Works
- Cognito redirects the user back to
/callbackwith a code. - You exchange that code for tokens via the
/oauth2/token endpoint. - You decode the id_token (JWT) to extract user info like email, sub, and name.
Conclusion
Cover image from freepik.com









