All Articles
AWSJanuary 10, 202510 min read

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%.

AWSSecurityAuthenticationSpring BootMigration
Migrating Authentication from Firebase to AWS Cognito: A Practical Guide

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:

java
@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

  1. Don't force password resets: Use migration triggers for seamless transitions
  2. Don't skip shadow mode: You will find bugs you didn't expect
  3. Don't migrate all at once: Feature flags and gradual rollout saved us twice
  4. Don't forget token refresh: Existing sessions need a graceful transition plan
  5. Test with real enterprise IdPs early: Every SAML implementation has quirks