or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication-lifecycle.mddevice-management.mdindex.mdmulti-factor-authentication.mdoauth-social-authentication.mdpassword-management.mdserver-side-apis.mdsession-management.mduser-management.mdwebauthn-credentials.md
tile.json

oauth-social-authentication.mddocs/

OAuth & Social Authentication

OAuth/OIDC integration for social and enterprise identity providers including Google, Facebook, Amazon, Apple, and SAML/OIDC providers.

Enable OAuth Listener

Enable automatic handling of OAuth callback flows in your application. This is a side-effect import that sets up event listeners for OAuth completion.

// Import to enable OAuth callback handling
import "@aws-amplify/auth/enable-oauth-listener";

This import should be done once in your application, typically in your main application file or in a module that loads early. It automatically handles the OAuth redirect callback and completes the authentication flow.

Sign In With Redirect

Initiate OAuth/OIDC authentication flow using browser redirect.

function signInWithRedirect(input?: SignInWithRedirectInput): Promise<void>;

interface SignInWithRedirectInput {
  provider?: AuthProvider | {
    custom: string;
  };
  customState?: string;
  options?: {
    preferPrivateSession?: boolean;
  };
}

type AuthProvider = 'Google' | 'Facebook' | 'Amazon' | 'Apple';

Usage Example

import { signInWithRedirect } from "@aws-amplify/auth";

// Sign in with Google
await signInWithRedirect({
  provider: 'Google'
});

// Sign in with Facebook
await signInWithRedirect({
  provider: 'Facebook'
});

// Sign in with custom OIDC provider
await signInWithRedirect({
  provider: { custom: 'MyOIDCProvider' }
});

// Sign in with custom state for tracking
await signInWithRedirect({
  provider: 'Google',
  customState: 'user-journey-tracking-id'
});

Handle OAuth Callback

After OAuth redirect, handle the authentication result:

import { signInWithRedirect, getCurrentUser } from "@aws-amplify/auth";

// Check if user is signed in after OAuth redirect
async function handleOAuthCallback() {
  try {
    const user = await getCurrentUser();
    console.log("OAuth sign in successful:", user.username);
    return user;
  } catch (error) {
    console.log("OAuth sign in failed or user not signed in");
    throw error;
  }
}

// Call this after OAuth redirect
handleOAuthCallback().then(user => {
  // Redirect to app dashboard or handle success
  window.location.href = '/dashboard';
}).catch(error => {
  // Handle OAuth error or show sign-in form again
  console.error('OAuth authentication failed:', error);
});

OAuth Provider Configuration

Social Providers

Configure social providers in your Cognito User Pool:

// Provider configurations (set in AWS Console or CDK/CloudFormation)
const socialProviders = {
  Google: {
    client_id: 'your-google-client-id.apps.googleusercontent.com',
    client_secret: 'your-google-client-secret', // Server-side only
    authorize_scopes: ['email', 'profile', 'openid'],
    redirect_uri: 'https://yourapp.com/auth/callback'
  },
  
  Facebook: {
    client_id: 'your-facebook-app-id',
    client_secret: 'your-facebook-app-secret', // Server-side only
    authorize_scopes: ['email', 'public_profile'],
    redirect_uri: 'https://yourapp.com/auth/callback'
  },
  
  Amazon: {
    client_id: 'amzn1.application-oa2-client.your-client-id',
    client_secret: 'your-amazon-client-secret', // Server-side only
    authorize_scopes: ['profile'],
    redirect_uri: 'https://yourapp.com/auth/callback'
  },
  
  Apple: {
    client_id: 'com.yourcompany.yourapp',
    key_id: 'your-apple-key-id',
    private_key: 'your-apple-private-key', // Server-side only
    team_id: 'your-apple-team-id',
    authorize_scopes: ['email', 'name'],
    redirect_uri: 'https://yourapp.com/auth/callback'
  }
};

Custom OIDC Provider

For enterprise OIDC providers:

// Custom OIDC provider configuration
const customOIDCProvider = {
  provider_name: 'MyOIDCProvider',
  provider_type: 'OIDC',
  issuer_url: 'https://auth.company.com',
  client_id: 'your-oidc-client-id',
  client_secret: 'your-oidc-client-secret', // Server-side only
  authorize_scopes: ['openid', 'email', 'profile'],
  redirect_uri: 'https://yourapp.com/auth/callback',
  // Optional mappings
  attribute_mapping: {
    email: 'email',
    given_name: 'first_name',
    family_name: 'last_name',
    name: 'full_name'
  }
};

// Use in sign in
await signInWithRedirect({
  provider: { custom: 'MyOIDCProvider' }
});

OAuth Flow Patterns

Basic OAuth Flow

import { signInWithRedirect, getCurrentUser } from "@aws-amplify/auth";

class OAuthManager {
  async initiateOAuth(provider: AuthProvider) {
    // Store current location for post-auth redirect
    localStorage.setItem('preAuthLocation', window.location.pathname);
    
    // Initiate OAuth flow
    await signInWithRedirect({ provider });
  }
  
  async handleOAuthCallback() {
    try {
      // Check if user is now signed in
      const user = await getCurrentUser();
      
      // Get stored location
      const redirectTo = localStorage.getItem('preAuthLocation') || '/dashboard';
      localStorage.removeItem('preAuthLocation');
      
      // Redirect to intended destination
      window.location.href = redirectTo;
      
      return user;
    } catch (error) {
      // OAuth failed, redirect to sign-in
      window.location.href = '/sign-in?error=oauth_failed';
      throw error;
    }
  }
}

// Usage
const oauthManager = new OAuthManager();

// In your sign-in component
const handleGoogleSignIn = () => {
  oauthManager.initiateOAuth('Google');
};

// In your OAuth callback handler (usually on app load)
window.addEventListener('load', () => {
  // Check if this might be an OAuth callback
  const urlParams = new URLSearchParams(window.location.search);
  if (urlParams.has('code') || urlParams.has('state')) {
    oauthManager.handleOAuthCallback();
  }
});

State Parameter Usage

Use custom state for tracking user journey or preventing CSRF:

import { signInWithRedirect } from "@aws-amplify/auth";

// Generate secure state parameter
function generateSecureState() {
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
}

// Store state and context
const state = generateSecureState();
const context = {
  returnUrl: '/premium-signup',
  source: 'pricing-page',
  timestamp: Date.now()
};

localStorage.setItem(`oauth_state_${state}`, JSON.stringify(context));

// Initiate OAuth with custom state
await signInWithRedirect({
  provider: 'Google',
  customState: state
});

// In callback handler, validate state
function validateOAuthState(receivedState: string) {
  const contextKey = `oauth_state_${receivedState}`;
  const storedContext = localStorage.getItem(contextKey);
  
  if (!storedContext) {
    throw new Error('Invalid OAuth state');
  }
  
  const context = JSON.parse(storedContext);
  localStorage.removeItem(contextKey);
  
  // Check timestamp for expiry (e.g., 10 minutes)
  if (Date.now() - context.timestamp > 10 * 60 * 1000) {
    throw new Error('OAuth state expired');
  }
  
  return context;
}

Error Handling

OAuth authentication can fail for various reasons:

import { signInWithRedirect, AuthError } from "@aws-amplify/auth";

async function handleSocialSignIn(provider: AuthProvider) {
  try {
    await signInWithRedirect({ provider });
  } catch (error) {
    if (error instanceof AuthError) {
      switch (error.name) {
        case 'InvalidParameterException':
          console.log('Invalid provider configuration');
          break;
        case 'NotAuthorizedException':
          console.log('OAuth provider not configured');
          break;
        case 'UserNotConfirmedException':
          console.log('User email not confirmed');
          break;
        default:
          console.log('OAuth sign in failed:', error.message);
      }
    }
    
    // Handle OAuth-specific errors from URL parameters
    const urlParams = new URLSearchParams(window.location.search);
    const oauthError = urlParams.get('error');
    
    if (oauthError) {
      switch (oauthError) {
        case 'access_denied':
          console.log('User denied OAuth permission');
          break;
        case 'invalid_request':
          console.log('Invalid OAuth request');
          break;
        case 'server_error':
          console.log('OAuth provider server error');
          break;
        default:
          console.log('OAuth error:', oauthError);
      }
    }
  }
}

Best Practices

Security Considerations

  • Always use HTTPS for OAuth redirects
  • Validate state parameters to prevent CSRF attacks
  • Store sensitive OAuth configuration server-side
  • Use secure random state generation
  • Implement proper error handling and user feedback

User Experience

  • Provide clear loading states during OAuth flow
  • Handle OAuth cancellation gracefully
  • Store intended destination for post-auth redirect
  • Show appropriate error messages for OAuth failures
  • Consider progressive enhancement for browsers without JavaScript

Configuration Management

  • Use environment-specific OAuth configurations
  • Store OAuth secrets securely (environment variables, secrets manager)
  • Configure appropriate OAuth scopes for your application needs
  • Test OAuth flows in both development and production environments