Migrating from AWS Cognito to TitaniumVault
Complete guide to moving your authentication from AWS Cognito to TitaniumVault. Escape AWS lock-in with predictable pricing and better UX.
title: "Migrating from AWS Cognito to TitaniumVault" description: "Complete guide to moving your authentication from AWS Cognito to TitaniumVault. Escape AWS lock-in with predictable pricing and better UX." date: "2025-01-08" author: "Zeros and Ones Team" category: "Migration" tags: ["AWS", "Cognito", "Migration", "TitaniumVault", "Cloud", "Identity"]
AWS Cognito is convenient if you're all-in on AWS, but many teams find its complexity and AWS-centric design limiting. This guide walks you through migrating to TitaniumVault for a more flexible, user-friendly identity solution.
Why Teams Leave Cognito
Common frustrations:
- Complex Configuration: Simple tasks require multiple AWS services
- Confusing Pricing: MAU calculations and federation charges surprise teams
- Limited Customization: Email templates and UI are restrictive
- AWS Lock-in: Tight coupling makes multi-cloud difficult
- Poor Admin UX: The console is powerful but overwhelming
Pre-Migration Planning
Document Your Cognito Setup
User Pools:
- User count and attributes
- Custom attributes
- Groups and permissions
- MFA configuration
- Password policies
Identity Pools:
- Federated identities configuration
- IAM role mappings
- Authentication providers
App Clients:
- OAuth/OIDC settings
- Callback URLs
- Token expiration settings
- Hosted UI configuration
Lambda Triggers:
- Pre-signup
- Post-confirmation
- Pre/post-authentication
- Custom message
- Token generation
API Dependencies
Identify where Cognito is used:
# Search codebase for Cognito references
grep -r "cognito" --include="*.js" --include="*.ts" --include="*.py"
grep -r "aws-amplify" --include="*.json"
Migration Approach
Strategy Options
Option 1: Parallel Running (Recommended)
Run both systems simultaneously during transition.
- Lower risk
- Easy rollback
- Gradual user migration
Option 2: Big Bang
Complete switchover in maintenance window.
- Clean cutover
- Shorter transition
- Higher risk
Step-by-Step Migration
Phase 1: TitaniumVault Setup
-
Create your organization
# Via CLI or API curl -X POST "https://api.titanium-vault.com/v1/organizations" \ -H "Authorization: Bearer $TOKEN" \ -d '{"name": "Your Company", "domain": "your-company"}' -
Configure authentication settings
- Match Cognito password policies
- Set up equivalent MFA options
- Configure session settings
-
Set up social/enterprise providers
- Replicate Cognito identity provider settings
- Test each connection
Phase 2: Export Users from Cognito
Cognito doesn't allow password export, but you can export user data:
const AWS = require('aws-sdk');
const cognito = new AWS.CognitoIdentityServiceProvider();
async function exportUsers(userPoolId) {
const users = [];
let paginationToken;
do {
const result = await cognito.listUsers({
UserPoolId: userPoolId,
PaginationToken: paginationToken,
}).promise();
users.push(...result.Users);
paginationToken = result.PaginationToken;
} while (paginationToken);
return users;
}
Phase 3: Import Users to TitaniumVault
Transform Cognito users:
const transformCognitoUser = (cognitoUser) => {
const attrs = {};
cognitoUser.Attributes.forEach(attr => {
attrs[attr.Name] = attr.Value;
});
return {
email: attrs.email,
emailVerified: attrs.email_verified === 'true',
phoneNumber: attrs.phone_number,
firstName: attrs.given_name,
lastName: attrs.family_name,
username: cognitoUser.Username,
status: cognitoUser.UserStatus === 'CONFIRMED' ? 'active' : 'pending',
metadata: {
cognitoSub: attrs.sub,
// Map custom attributes
}
};
};
Import to TitaniumVault:
curl -X POST "https://api.titanium-vault.com/v1/users/bulk" \
-H "Authorization: Bearer $TV_TOKEN" \
-H "Content-Type: application/json" \
-d @transformed_users.json
Phase 4: Password Handling
Since Cognito doesn't export passwords, options:
Option A: Force Password Reset
// Send password reset to all users
for (const user of users) {
await titaniumVault.sendPasswordReset(user.email);
}
Option B: Lazy Migration During a transition period, if TitaniumVault login fails:
- Try authenticating against Cognito
- If successful, set password in TitaniumVault
- User continues seamlessly
Option C: Custom Lambda Bridge Use a Lambda function to verify against Cognito during transition:
// TitaniumVault webhook -> Lambda -> Cognito
exports.handler = async (event) => {
const { username, password } = event;
try {
await cognito.adminInitiateAuth({
AuthFlow: 'ADMIN_USER_PASSWORD_AUTH',
UserPoolId: USER_POOL_ID,
ClientId: CLIENT_ID,
AuthParameters: {
USERNAME: username,
PASSWORD: password,
}
}).promise();
return { verified: true };
} catch (e) {
return { verified: false };
}
};
Phase 5: Update Applications
React with Amplify → TitaniumVault
Before:
import { Amplify, Auth } from 'aws-amplify';
Amplify.configure({
Auth: {
region: 'us-east-1',
userPoolId: 'us-east-1_xxxxx',
userPoolWebClientId: 'xxxxxxxxx',
}
});
// Login
const user = await Auth.signIn(username, password);
After:
import { TitaniumVaultClient } from '@titaniumvault/client';
const auth = new TitaniumVaultClient({
domain: 'your-org.titanium-vault.com',
clientId: 'your-client-id',
});
// Login
const user = await auth.signIn(username, password);
Backend Token Verification
Before (Cognito):
const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');
const client = jwksClient({
jwksUri: `https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxx/.well-known/jwks.json`
});
After (TitaniumVault):
const client = jwksClient({
jwksUri: `https://your-org.titanium-vault.com/.well-known/jwks.json`
});
Phase 6: Migrate Lambda Triggers
Map Cognito triggers to TitaniumVault webhooks:
| Cognito Trigger | TitaniumVault Equivalent |
|-----------------|--------------------------|
| Pre Sign-up | user.pre_signup webhook |
| Post Confirmation | user.confirmed webhook |
| Pre Authentication | auth.pre_login webhook |
| Post Authentication | auth.success webhook |
| Custom Message | Email template customization |
| Pre Token Generation | Token claims configuration |
Example webhook migration:
// Cognito Lambda (before)
exports.handler = async (event) => {
if (event.triggerSource === 'PostConfirmation_ConfirmSignUp') {
await createUserInDatabase(event.request.userAttributes);
}
return event;
};
// TitaniumVault webhook (after)
app.post('/webhooks/user-confirmed', async (req, res) => {
const { user } = req.body;
await createUserInDatabase(user);
res.sendStatus(200);
});
Phase 7: Testing
Comprehensive test plan:
- [ ] User registration
- [ ] Email verification
- [ ] Login (username/email)
- [ ] Social login (Google, Facebook, etc.)
- [ ] MFA setup and verification
- [ ] Password reset
- [ ] Token refresh
- [ ] Logout
- [ ] API authorization
- [ ] Federated login (SAML)
- [ ] Custom attributes
Phase 8: Cutover
- Update DNS/routing
- Monitor authentication metrics
- Keep Cognito running for 30 days (fallback)
- Disable Cognito after successful migration
Cost Comparison
| Users | Cognito Cost | TitaniumVault | |-------|-------------|---------------| | 10,000 MAU | ~$275/mo | Flat rate | | 50,000 MAU | ~$1,275/mo | Flat rate | | 100,000 MAU | ~$2,525/mo | Flat rate | | SAML Federation | +$0.015/MAU | Included | | Advanced Security | +$0.050/MAU | Included |
Common Issues
Issue: SRP Authentication
Cognito uses SRP (Secure Remote Password). TitaniumVault uses standard OAuth/OIDC.
Solution: Update client code to use standard authentication flows.
Issue: Custom Attributes
Cognito custom attributes have specific naming (custom:attribute).
Solution: Map to TitaniumVault user metadata during import.
Issue: Identity Pool IAM Roles
If using identity pools for AWS resource access:
Solution: Use TitaniumVault tokens with AWS STS AssumeRoleWithWebIdentity or implement a token exchange service.
Ready to escape AWS lock-in? Start your free trial and our team will help you plan and execute your Cognito migration.