How do you build a secure, scalable app as a solo founder without a massive budget? I’m doing it with AWS Cognito for KaziHub, a smart job board empowering African developers with verified tech jobs, scam detection, and skill-based matching.
In this post, I’ll walk you through how I implemented user authentication with Cognito + React + AWS Amplify — a stack perfect for lean startups looking to scale fast.
🧱 Why AWS Cognito?
Cognito is a powerhouse for startups like mine because:
- ✅ Handles user sign-up, login, email verification, and password resets out of the box
- ✅ Scales effortlessly, so I don’t worry about infrastructure as KaziHub grows
- ✅ Integrates seamlessly with AWS services like Lambda, S3, and DynamoDB, which I’m using for job matching
- ✅ Saves me from building a custom auth backend, keeping costs low and development fast
AWS’s serverless tools are a game-changer for solo founders, letting me focus on KaziHub’s mission: connecting African developers with verified opportunities.
🔧 Setting Up Cognito
Create a User Pool
Go to AWS Console → Cognito → User Pools → Create new pool
I enabled email as the sign-in method and applied strong password policies.Set up an App Client
Created a client ID without a client secret (since the frontend is public).Configure the Hosted UI Domain
This allows a seamless experience for verification, sign-up, and password recovery.
💻 Setting Up My React Frontend
Install AWS Amplify
npm install aws-amplify
Configure Amplify
// src/awsConfig.js
export const awsConfig = {
Auth: {
region: "us-east-1",
userPoolId: "us-east-1_XXXXXXX", // Replace with your User Pool ID (Based on how close it is to your location to reduce latency)
userPoolWebClientId: "XXXXXXXXXXXXXX", // Replace with your App Client ID
},
};
// main.jsx
import { Amplify } from "aws-amplify";
import { awsConfig } from "./awsConfig";
Amplify.configure(awsConfig);
🧑💻 Auth Flows
🔐 Sign Up
import { Auth } from "aws-amplify";
const handleSignUp = async () => {
await Auth.signUp({
username: email,
password,
attributes: { email },
});
};
🔓 Login
const handleLogin = async () => {
await Auth.signIn(email, password);
};
🔁 Recover Password
await Auth.forgotPassword(email);
await Auth.forgotPasswordSubmit(email, code, newPassword);
✅ Confirm Sign Up
await Auth.confirmSignUp(email, code);
🔒 Protecting Routes (Optional)
To protect authenticated-only pages (like posting jobs), I created a simple PrivateRoute
component:
const PrivateRoute = ({ children }) => {
const [user, setUser] = useState(null);
useEffect(() => {
Auth.currentAuthenticatedUser()
.then(setUser)
.catch(() => (window.location.href = "/login"));
}, []);
return user ? children : null;
};
🧠 Lessons Learned
- AWS documentation can feel dense. Setting up email flows and user pools took trial and error.
-
InvalidParameterException
was my nemesis — usually caused by misconfigured attributes. - Once it’s set up, Cognito just works. It’s magical watching everything sync across the hosted UI and your frontend.
🛠 What’s Next
- Build job posting + application logic using Lambda and DynamoDB
- Add user roles for Job Seekers and Employers
- Set up CI/CD pipeline with GitLab
- Deploy via AWS Amplify Hosting or S3 + CloudFront
💬 Final Thoughts
AWS Cognito and Amplify have been game-changers for KaziHub. I’m building a secure, scalable platform for African developers — without having to manage infrastructure or auth complexity.
🚀 We’ve already onboarded 100+ users in beta, and thanks to Cognito, every sign-up, login, and password reset has been smooth.
Got questions or ideas? Ping me on X — happy to connect with fellow builders!