Migrating Authentication from Firebase to AWS Cognito: A Practical Guide
Lessons learned from migrating a SaaS platform's auth system to AWS Cognito with MFA and SSO, reducing onboarding support tickets by 20%.

Why We Migrated
At Penguin Benefits, we started with Firebase Auth -- it was fast to set up and worked well for our early stage. But as we onboarded Fortune 500 clients, the requirements changed:
- Enterprise SSO: Clients needed SAML/OIDC integration with their identity providers
- MFA enforcement: Regulatory requirements demanded multi-factor authentication
- AWS ecosystem: Our entire infrastructure was on AWS; Firebase Auth was the odd one out
- Fine-grained access control: We needed custom claims and group-based permissions
The Migration Strategy
Migrating auth is one of the most dangerous operations you can perform on a production system. Users can't log in = business stops. Here's how we approached it:
Phase 1: Dual-Write Setup (Week 1-2)
We ran both Firebase and Cognito simultaneously. Every new user registration wrote to both systems. Every login was validated against Firebase but also verified in Cognito.
Phase 2: Shadow Authentication (Week 3-4)
We started authenticating against Cognito in shadow mode -- comparing results with Firebase but not using Cognito's response for actual auth decisions. This caught edge cases like:
- Password hash migration issues
- Token format differences
- Custom claim mapping errors
Phase 3: Gradual Cutover (Week 5-6)
Using feature flags, we migrated users in batches:
- Internal users first (10% traffic)
- Then small-client users (40% traffic)
- Finally, enterprise clients (100% traffic)
Phase 4: Firebase Decommission (Week 7-8)
After two weeks with zero fallbacks to Firebase, we decommissioned the old auth system.
Key Technical Decisions
Password Migration
Firebase uses a modified scrypt hash. Rather than forcing password resets, we implemented a custom migration trigger in Cognito:
@Override
public UserMigrationResult migrateUser(UserMigrationEvent event) {
FirebaseUser fbUser = firebaseAuth
.getUserByEmail(event.getUserName());
if (fbUser != null) {
return UserMigrationResult.builder()
.userAttributes(mapAttributes(fbUser))
.finalUserStatus("CONFIRMED")
.build();
}
throw new UserNotFoundException();
}On first login with Cognito, the Lambda trigger verified the password against Firebase, and if valid, created the Cognito user. Seamless for the end user.
MFA Implementation
We chose TOTP-based MFA (Google Authenticator compatible) over SMS because:
- More secure (no SIM swapping risk)
- No per-message costs
- Works offline
SSO with SAML
For enterprise clients, we configured Cognito User Pool identity providers for each client's IdP. The key challenge was attribute mapping -- every enterprise IdP sends claims differently.
Results
- 20% reduction in onboarding-related support tickets
- Zero-downtime migration for 100K+ existing users
- MFA adoption: 85% of enterprise users enrolled within 30 days
- SSO integration: Reduced enterprise onboarding time from 2 weeks to 2 days
Mistakes to Avoid
- Don't force password resets: Use migration triggers for seamless transitions
- Don't skip shadow mode: You will find bugs you didn't expect
- Don't migrate all at once: Feature flags and gradual rollout saved us twice
- Don't forget token refresh: Existing sessions need a graceful transition plan
- Test with real enterprise IdPs early: Every SAML implementation has quirks