Authentication is one of the first challenges developers encounter when building an application.
Initially, it seems straightforward: ask users for an email and password, verify the credentials, and allow access.
However, implementing authentication securely is much more involved than it first appears.
Questions quickly begin to arise:
- Where should passwords be stored?
- How should passwords be hashed?
- How are password resets implemented?
- How should Multi-Factor Authentication (MFA) be handled?
- How are secure authentication tokens generated?
- How can those tokens be trusted by the backend?
These responsibilities are exactly what AWS Cognito is designed to solve.
Rather than being just a JWT generator, Cognito is a fully managed identity and authentication service that handles the entire authentication lifecycle.
Why Use AWS Cognito?
Imagine building authentication entirely from scratch.
The authentication flow might look like this:
User
│
Email + Password
│
▼
Backend
│
Query Database
│
Retrieve Password Hash
│
Compare Password
│
Generate JWT
│
Return Access Token
In this design, the backend becomes responsible for:
- Storing passwords
- Hashing passwords
- Verifying credentials
- Password resets
- Email verification
- Multi-factor authentication
- Refresh tokens
- JWT generation
- JWT validation
Handling all of these securely is a significant engineering responsibility.
AWS Cognito removes much of this complexity by managing authentication on your behalf.
The User Pool
One of the central concepts in Cognito is the User Pool.
A User Pool is a managed identity database maintained by AWS.
It stores authentication-related information such as:
- Email address
- Username
- Password hash
- Phone number
- Email verification status
- MFA settings
- User status
- A unique identifier (
sub)
Conceptually:
User Pool
---------------------------------------
Email Password Hash
---------------------------------------
alice@example.com *************
bob@example.com *************
john@example.com *************
---------------------------------------
An important detail is that developers never have access to users' passwords or password hashes.
Those are managed entirely by Cognito.
Where Does the User Pool Live?
One question that initially confused me was where the User Pool actually exists.
It is not stored in:
- Amazon RDS
- DynamoDB
- An EC2 instance
- Your application's VPC
Instead, it exists inside AWS's managed Cognito service.
This separation is intentional because authentication is infrastructure managed by AWS rather than application-specific data.
Why Isn't Cognito Inside the VPC?
Many AWS resources live inside a Virtual Private Cloud (VPC), including:
- EC2
- RDS
- ECS
- Lambda (when configured for VPC access)
Cognito works differently.
Like IAM or Route 53, Cognito is an AWS-managed service that is accessed securely over HTTPS through AWS service endpoints.
Your application communicates with Cognito—it does not host Cognito.
How Authentication Works
When a user signs in, the flow is surprisingly simple.
User
│
│ Email + Password
▼
AWS Cognito
│
▼
User Pool
│
▼
Verify Credentials
│
▼
Generate Tokens
│
▼
Browser
Notice what does not happen.
The backend never:
- Receives the user's password
- Compares password hashes
- Generates authentication tokens
Cognito performs all of those responsibilities.
Signing Up
During registration, the process is similar.
User
│
│ Email
│ Password
▼
AWS Cognito
│
▼
User Pool
Cognito automatically:
- Validates password policies
- Stores passwords securely
- Sends verification emails (if configured)
- Creates the user identity
- Assigns a unique identifier
Applications no longer need to implement these features manually.
Understanding the Tokens
After successful authentication, Cognito returns three JWTs.
ID Token
The ID Token identifies the authenticated user.
It commonly contains information such as:
- User ID (
sub) - Username
Its purpose is identity.
Access Token
The Access Token is presented when calling protected APIs.
For example:
Authorization: Bearer <Access Token>
The backend validates this token before allowing access.
Refresh Token
Access Tokens eventually expire.
Instead of asking users to log in again, the Refresh Token can be exchanged for a new Access Token until it too expires.
This allows users to remain signed in without repeatedly entering credentials.
How Does the Backend Trust Cognito?
Every protected request includes the Access Token.
Browser
Authorization: Bearer eyJhbGci...
Rather than checking passwords, the backend validates the JWT.
Typical checks include:
- Signature verification
- Issuer validation
- Audience validation
- Expiration time
If the token is valid, access is granted.
Otherwise, the request is rejected with a 401 Unauthorized response.
The backend trusts the identity because the token was signed by Cognito.
Authentication Data vs Application Data
One important architectural lesson is that authentication data and business data should remain separate.
Cognito manages identity information such as:
- Password
- MFA
- Verification status
Meanwhile, application databases store business information such as:
- Orders
- Addresses
- User preferences
- Shopping carts
- Subscription details
Applications typically store the Cognito user identifier (sub) to associate business records with authenticated users.
Conceptually:
Authentication
│
▼
AWS Cognito
Business Data
│
▼
RDS / DynamoDB
Keeping these responsibilities separate improves both security and maintainability.
What If the Application Server Is Compromised?
A question that naturally came to mind was:
What happens if someone gains access to the EC2 instance?
An attacker might obtain:
- Application source code
- Environment variables
- Business database access (depending on IAM permissions)
- Access to other AWS services (depending on IAM policies)
However, they still cannot retrieve users' passwords from Cognito.
That's because:
- Passwords are never stored on the EC2 instance.
- Password hashes are never stored in the application database.
- Cognito does not expose password hashes through its APIs.
Separating authentication from application infrastructure significantly reduces the impact of a server compromise.
Can AWS Administrators See Passwords?
Another common misconception is that AWS administrators can retrieve user passwords.
They cannot.
Administrators can perform management operations such as:
- Creating users
- Disabling users
- Resetting passwords
- Viewing permitted user attributes
But neither plaintext passwords nor password hashes are exposed.
Those remain protected inside Cognito.
Why Use Cognito?
Beyond simplifying development, Cognito also provides several security advantages.
It offers:
- Secure password storage
- Built-in password policies
- Multi-Factor Authentication (MFA)
- Email verification
- Secure JWT generation
- Refresh token management
- Reduced attack surface
- Standards-based authentication
Rather than building these capabilities from scratch, applications can rely on a managed service designed specifically for identity management.
Final Thoughts
Before learning AWS Cognito, I viewed authentication mainly as checking usernames and passwords.
Working through Cognito changed that perspective.
Authentication is much more than credential verification—it involves securely managing identities, issuing trusted tokens, protecting user credentials, and separating authentication concerns from application logic.
Perhaps the biggest takeaway was realizing that good authentication systems don't simply authenticate users.
They minimize how much sensitive information an application is responsible for handling in the first place.
That separation is one of the strongest security advantages of using a managed identity service like AWS Cognito.
Top comments (0)