How to fix auth/invalid-continue-uri: Continue URL is not valid in Firebase

FirebaseINTERMEDIATEMEDIUMUpdated Dec 12, 2025· 299 views

This Firebase Authentication error occurs when the continue URL provided for email actions (password reset, email verification) is invalid, malformed, or not authorized. The continue URL must be a properly formatted URL with an authorized domain that matches your Firebase project configuration.

Quick fix

Fixes auth/invalid-continue-uri: Continue URL is not valid

// ✅ Valid URL formats
'https://yourapp.com/reset-password-complete'
'https://yourapp.com/verify-email?userId=123'
'http://localhost:3000/auth-callback'  // Only for development
'https://yourapp.page.link/reset'      // For Firebase Dynamic Links

// ❌ Invalid URL formats
'/reset-password'                      // Missing protocol and domain
'yourapp.com/reset-password'           // Missing protocol
'https://yourapp.com/#/reset'          // Contains fragment (#)
'http://yourapp.com/reset'             // HTTP in production (needs HTTPS)
'https://unauthorized.com/reset'       // Domain not authorized
'https://sub.yourapp.com/reset'        // Subdomain not authorized if only root domain is
  1. Verify your continue URL format and protocol
  2. Check and update authorized domains in Firebase Console
  3. Fix protocol issues (HTTP vs HTTPS)
  4. Configure Firebase Dynamic Links for mobile apps
firebase — error
// ✅ Valid URL formats
'https://yourapp.com/reset-password-complete'
'https://yourapp.com/verify-email?userId=123'
'http://localhost:3000/auth-callback' // Only for development
'https://yourapp.page.link/reset' // For Firebase Dynamic Links
// ❌ Invalid URL formats
'/reset-password' // Missing protocol and domain
'yourapp.com/reset-password' // Missing protocol
'https://yourapp.com/#/reset' // Contains fragment (#)
'http://yourapp.com/reset' // HTTP in production (needs HTTPS)
'https://unauthorized.com/reset' // Domain not authorized
'https://sub.yourapp.com/reset' // Subdomain not authorized if only root domain is
auth/invalid-continue-uri: Continue URL is not valid

What this error means

The "auth/invalid-continue-uri" error is a Firebase Authentication error that occurs when you provide a continue URL for email actions (password reset, email verification, email change) that Firebase cannot accept. This error is more specific than the "missing-continue-uri" error - it means you HAVE provided a continue URL, but Firebase has determined it's invalid. Common reasons include: 1. **Malformed URL**: The URL doesn't follow proper URL syntax (missing protocol, invalid characters, etc.) 2. **Unauthorized domain**: The domain in the URL is not listed in your Firebase project's authorized domains 3. **Invalid protocol**: Using http:// in a production environment that requires https:// 4. **Localhost in production**: Using localhost URLs in a production Firebase project 5. **URL contains fragments**: URLs with #hash fragments are not allowed 6. **Dynamic link misconfiguration**: For mobile apps, the dynamic link domain isn't properly configured The continue URL is critical because it's where users are redirected after completing email actions. Firebase validates this URL strictly for security reasons to prevent phishing attacks and ensure users return to your legitimate application.

Typical symptoms

  • Firebase Authentication methods throw 'auth/invalid-continue-uri' error
  • Password reset emails fail with 'Continue URL is not valid' message
  • Email verification links don't work despite providing a continue URL
  • Error occurs when calling sendPasswordResetEmail(), sendEmailVerification(), or similar methods with actionCodeSettings
  • Firebase Admin SDK operations fail with invalid continue URL error
  • Error appears even though you're providing a continue URL parameter
  • Different from 'auth/missing-continue-uri' - this error means URL exists but is invalid

Common causes

  1. Continue URL uses a domain not authorized in Firebase Console
  2. URL is missing protocol (http:// or https://)
  3. Using http:// in production Firebase project (requires https://)
  4. Localhost URL used in non-development environment
  5. URL contains #fragment identifier which Firebase doesn't allow
  6. Dynamic link domain not configured for mobile app deep links
  7. URL has invalid characters or improper encoding
  8. Firebase project has restrictive domain whitelist that doesn't include your URL
  9. Using relative URLs instead of absolute URLs
  10. Continue URL points to a different subdomain than authorized
  11. Firebase project configured to reject certain URL patterns

How to fix "auth/invalid-continue-uri: Continue URL is not valid"

1Verify your continue URL format and protocol

First, ensure your continue URL follows Firebase's URL requirements:

javascript
// ✅ Valid URL formats
'https://yourapp.com/reset-password-complete'
'https://yourapp.com/verify-email?userId=123'
'http://localhost:3000/auth-callback'  // Only for development
'https://yourapp.page.link/reset'      // For Firebase Dynamic Links

// ❌ Invalid URL formats
'/reset-password'                      // Missing protocol and domain
'yourapp.com/reset-password'           // Missing protocol
'https://yourapp.com/#/reset'          // Contains fragment (#)
'http://yourapp.com/reset'             // HTTP in production (needs HTTPS)
'https://unauthorized.com/reset'       // Domain not authorized
'https://sub.yourapp.com/reset'        // Subdomain not authorized if only root domain is

Key requirements:
1. Must start with http:// or https://
2. Domain must be authorized in Firebase Console
3. No #fragment identifiers allowed
4. HTTPS required for production environments
5. Localhost only allowed in development

2Check and update authorized domains in Firebase Console

Your continue URL's domain MUST be in the authorized domains list:

1. Go to Firebase Console (console.firebase.google.com)
2. Select your project
3. Navigate to Authentication → Settings
4. Under "Authorized domains", check if your domain is listed:

bash
Authorized domains should include:
- yourapp.com                    # Your production domain
- localhost                      # For development
- yourapp.page.link              # For Firebase Dynamic Links (if used)

5. If your domain is missing, click "Add domain" and enter it
6. For subdomains: If using sub.yourapp.com, you may need to add the specific subdomain or configure wildcard authorization
7. Save changes and wait a few minutes for propagation

Note: Changes to authorized domains may take a few minutes to propagate through Firebase's systems.

3Fix protocol issues (HTTP vs HTTPS)

Firebase has strict requirements about HTTP vs HTTPS:

javascript
// Development environment (localhost)
const devActionCodeSettings = {
  url: 'http://localhost:3000/reset-complete',  // HTTP OK for localhost
  handleCodeInApp: false
};

// Production environment
const prodActionCodeSettings = {
  url: 'https://yourapp.com/reset-complete',    // MUST use HTTPS
  handleCodeInApp: false
};

// Dynamic configuration based on environment
const actionCodeSettings = {
  url: process.env.NODE_ENV === 'development'
    ? 'http://localhost:3000/reset-complete'
    : 'https://yourapp.com/reset-complete',
  handleCodeInApp: false
};

Important rules:
- Production: Always use https://
- Localhost development: http:// is acceptable
- Custom domains: Must support HTTPS with valid SSL certificate
- Firebase Hosting: Automatically provides HTTPS

If you're getting this error in production, ensure your URL starts with https:// and your domain has a valid SSL certificate.

4Configure Firebase Dynamic Links for mobile apps

For mobile apps using deep links, you need Firebase Dynamic Links:

javascript
// Mobile app configuration
const actionCodeSettings = {
  url: 'https://yourapp.page.link/reset',      // Dynamic Link URL
  handleCodeInApp: true,                       // Important: true for mobile apps
  dynamicLinkDomain: 'yourapp.page.link',      // Your Dynamic Link domain
  // iOS configuration
  ios: {
    bundleId: 'com.yourapp.ios',
    // appStoreId: '123456789', // Optional App Store ID
    // minimumVersion: '12.0',  // Optional minimum version
  },
  // Android configuration
  android: {
    packageName: 'com.yourapp.android',
    installApp: true,                          // Prompt to install if not installed
    minimumVersion: '12',                      // Minimum app version
  },
};

// Send password reset with Dynamic Links
sendPasswordResetEmail(auth, email, actionCodeSettings);

Setup steps:
1. Enable Firebase Dynamic Links in your project
2. Configure your Dynamic Link domain (yourapp.page.link)
3. Add the domain to authorized domains in Firebase Console
4. Configure your mobile app to handle the deep links
5. Test with handleCodeInApp: true

Without proper Dynamic Links configuration, mobile app continue URLs will fail validation.

5Validate and encode URL parameters properly

If your continue URL has query parameters, they must be properly encoded:

javascript
// ❌ Problematic - unencoded parameters
const badUrl = 'https://yourapp.com/reset?email=user@example.com&token=abc/def';
// The '/' in token breaks URL parsing

// ✅ Properly encoded
const goodUrl = 'https://yourapp.com/reset?email=user%40example.com&token=abc%2Fdef';

// Using URLSearchParams for proper encoding
const params = new URLSearchParams({
  email: 'user@example.com',
  token: 'abc/def',
  redirect: '/dashboard'
});
const baseUrl = 'https://yourapp.com/reset-complete';
const fullUrl = `${baseUrl}?${params.toString()}`;
// Result: https://yourapp.com/reset-complete?email=user%40example.com&token=abc%2Fdef&redirect=%2Fdashboard

// Use in Firebase
const actionCodeSettings = {
  url: fullUrl,
  handleCodeInApp: false
};

Common encoding issues:
- Special characters: @, /, ?, &, =, +, % must be encoded
- Spaces: Should be %20 or +
- Unicode characters: Must be UTF-8 encoded
- JSON in URLs: Use encodeURIComponent(JSON.stringify(data))

Test your URL by pasting it into a browser - it should load without errors.

6Test with Firebase's URL validation

Create a test script to validate your continue URL:

javascript
async function testContinueUrl(url) {
  const auth = getAuth();
  const testEmail = 'test@example.com'; // Use a test email

  try {
    const actionCodeSettings = {
      url: url,
      handleCodeInApp: false
    };

    console.log(`Testing URL: ${url}`);
    console.log(`Domain: ${new URL(url).hostname}`);

    await sendPasswordResetEmail(auth, testEmail, actionCodeSettings);
    console.log('✅ URL accepted by Firebase');

    return { valid: true, message: 'URL accepted' };

  } catch (error) {
    console.error('❌ URL rejected:', error.code, error.message);

    // Diagnostic information
    if (error.code === 'auth/invalid-continue-uri') {
      console.log('Diagnostics:');
      console.log('- Check authorized domains in Firebase Console');
      console.log('- Ensure URL starts with https:// (production)');
      console.log('- Remove any # fragments from URL');
      console.log('- Verify domain matches exactly (no www vs non-www mismatch)');
    }

    return { valid: false, error: error.message, code: error.code };
  }
}

// Test different URLs
await testContinueUrl('https://yourapp.com/reset-complete');
await testContinueUrl('http://localhost:3000/reset-complete');
await testContinueUrl('https://yourapp.page.link/reset');

This helps identify exactly which URL format Firebase accepts. Start with the simplest URL (just domain + path), then add parameters once the base URL works.

7Debug production vs development configuration

Ensure your code handles different environments correctly:

javascript
// Environment configuration
const getContinueUrl = () => {
  const env = process.env.NODE_ENV || 'development';

  switch (env) {
    case 'production':
      return 'https://yourapp.com/auth-callback';

    case 'staging':
      return 'https://staging.yourapp.com/auth-callback';

    case 'development':
    default:
      return 'http://localhost:3000/auth-callback';
  }
};

// Firebase configuration with environment detection
const getFirebaseConfig = () => {
  // Your Firebase config - ensure you're using the right project
  return {
    apiKey: process.env.FIREBASE_API_KEY,
    authDomain: process.env.FIREBASE_AUTH_DOMAIN,
    projectId: process.env.FIREBASE_PROJECT_ID,
    // ... other config
  };
};

// Common mistake: Using development Firebase config with production URLs
// or vice versa. Ensure your Firebase project matches your environment.

// Check your Firebase project ID
console.log('Current Firebase project:', firebase.app().options.projectId);

// Verify the project has your domain authorized
// Different Firebase projects = different authorized domains lists

Key checks:
1. Firebase project ID matches your environment
2. Authorized domains configured for THAT specific project
3. Environment variables point to correct Firebase project
4. No mixing of development and production configurations

Advanced notes

### Understanding Firebase's URL Validation

Firebase validates continue URLs against several criteria:

1. Domain authorization: The domain must be in the authorized domains list
2. Protocol enforcement: HTTPS required for non-localhost domains
3. URL structure: Must be a valid, absolute URL
4. Security checks: Prevents open redirect vulnerabilities

### Subdomain Handling

If you use subdomains (app.yourapp.com, admin.yourapp.com), note that:
- Adding 'yourapp.com' authorizes ALL subdomains in some Firebase configurations
- For stricter control, you may need to add each subdomain individually
- Wildcard domains (*.yourapp.com) are not supported in the Firebase Console UI

### Firebase Hosting Integration

If hosting on Firebase Hosting, your continue URLs should point to your Firebase Hosting domain:

bash
https://your-project-id.web.app/reset-complete
https://your-project-id.firebaseapp.com/reset-complete
https://your-custom-domain.com/reset-complete

These domains are automatically authorized when you set up Firebase Hosting.

### Multiple Environment Strategy

For teams with multiple environments (dev, staging, prod):

1. Separate Firebase projects for each environment
2. Environment-specific authorized domains:
- Dev: localhost, dev.yourapp.com
- Staging: staging.yourapp.com
- Prod: yourapp.com, app.yourapp.com
3. Build-time URL configuration using environment variables
4. Consistent URL patterns across environments

### Security Implications

The strict URL validation prevents:
- Phishing attacks: Attackers can't redirect users to malicious sites
- Open redirects: Your app can't be used as an open redirector
- Domain hijacking: Ensures users return to YOUR legitimate domain

Never disable or work around these security checks. Instead, properly configure your authorized domains.

Frequently asked questions

What does "auth/invalid-continue-uri: Continue URL is not valid" mean?
The "auth/invalid-continue-uri" error is a Firebase Authentication error that occurs when you provide a continue URL for email actions (password reset, email verification, email change) that Firebase cannot accept. This error is more specific than the "missing-continue-uri" error - it means you HAVE provided a continue URL, but Firebase has determined it's invalid. Common reasons include: 1.
How do I fix "auth/invalid-continue-uri: Continue URL is not valid"?
This Firebase Authentication error occurs when the continue URL provided for email actions (password reset, email verification) is invalid, malformed, or not authorized. The continue URL must be a properly formatted URL with an authorized domain that matches your Firebase project configuration.
What causes "auth/invalid-continue-uri: Continue URL is not valid"?
Continue URL uses a domain not authorized in Firebase Console URL is missing protocol (http:// or https://) Using http:// in production Firebase project (requires https://)
Is the "auth/invalid-continue-uri: Continue URL is not valid" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading