> ## Documentation Index
> Fetch the complete documentation index at: https://docs.streambird.io/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth (Social Login)

> Enable users to sign in with Google, Apple, and other OAuth providers

# OAuth Authentication

MoonKey enables users to sign in using familiar OAuth providers like Google and Apple. OAuth authentication provides a seamless login experience that users are already comfortable with, integrated into your application in just a few lines of code.

<Tip>
  Enable OAuth login methods in the [MoonKey Dashboard](https://dashboard.moonkey.fun) under **Login Methods** before implementing this feature.
</Tip>

<Warning>
  Google OAuth login may not work in in-app browsers (IABs), such as those embedded in social apps, due to Google's restrictions in these environments. Apple OAuth and other providers are generally unaffected.
</Warning>

## Supported OAuth Providers

MoonKey currently supports the following OAuth providers:

* **Google** - Sign in with Google accounts
* **Apple** - Sign in with Apple ID

<Info>
  Additional OAuth providers (Microsoft, Discord, GitHub, etc.) are coming soon. Contact us if you need support for a specific provider.
</Info>

## Configuration

### Dashboard Setup

Before implementing OAuth authentication, you must configure your OAuth credentials for each provider:

1. Log in to the [MoonKey Dashboard](https://dashboard.moonkey.fun)
2. Navigate to **Login Methods** → **OAuth**
3. Select the provider you want to enable (Google or Apple)
4. Enter your OAuth Client ID and Client Secret
5. Configure your redirect URLs
6. Save your changes

<Warning>
  MoonKey does not provide default OAuth credentials. You must configure your own OAuth app credentials for each provider you want to support.
</Warning>

### Getting OAuth Credentials

#### Google OAuth

1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select an existing one
3. Enable the Google+ API
4. Go to **Credentials** → **Create Credentials** → **OAuth 2.0 Client ID**
5. Configure the consent screen
6. Add authorized redirect URIs provided by MoonKey
7. Copy the Client ID and Client Secret to the MoonKey Dashboard

#### Apple OAuth

1. Go to [Apple Developer](https://developer.apple.com/)
2. Navigate to **Certificates, Identifiers & Profiles**
3. Create a new **Services ID**
4. Enable **Sign in with Apple**
5. Configure the redirect URLs
6. Generate a private key
7. Copy the credentials to the MoonKey Dashboard

## Using the React SDK

MoonKey provides two ways to implement OAuth authentication:

1. **`useMoonKey` hook with `start()`** - Unified authentication flow with all login methods
2. **`useLoginWithOAuth` hook** - Dedicated OAuth hook for more control

### Import

```typescript theme={null}
import { useMoonKey } from '@moon-key/react-auth';
// or for dedicated OAuth flow
import { useLoginWithOAuth } from '@moon-key/react-auth';
```

## Method 1: Using useMoonKey

The `useMoonKey` hook provides a unified way to trigger authentication with multiple methods.

### Basic Usage

Open the authentication modal with OAuth providers:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';

export default function OAuthLogin() {
  const { start, isAuthenticated, user } = useMoonKey();

  if (isAuthenticated) {
    return <div>Welcome, {user.email || user.google?.email}!</div>;
  }

  return (
    <button onClick={() => start()}>
      Login
    </button>
  );
}
```

### Google-only Login

Show only Google authentication:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';

export default function GoogleLogin() {
  const { start } = useMoonKey();

  return (
    <button onClick={() => start({ loginMethods: ['google'] })}>
      Sign in with Google
    </button>
  );
}
```

### Apple-only Login

Show only Apple authentication:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';

export default function AppleLogin() {
  const { start } = useMoonKey();

  return (
    <button onClick={() => start({ loginMethods: ['apple'] })}>
      Sign in with Apple
    </button>
  );
}
```

### Multiple OAuth Providers

Show multiple OAuth options:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';

export default function SocialLogin() {
  const { start } = useMoonKey();

  return (
    <button onClick={() => start({ loginMethods: ['google', 'apple'] })}>
      Continue with Social Login
    </button>
  );
}
```

### Combined with Other Methods

Combine OAuth with email and wallet authentication:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';

export default function AllLoginMethods() {
  const { start } = useMoonKey();

  return (
    <button onClick={() => start({ 
      loginMethods: ['email', 'google', 'apple', 'wallet'],
      walletChainType: 'ethereum-or-solana'
    })}>
      Login or Sign Up
    </button>
  );
}
```

### Login-only (Disable Signup)

Prevent new user signups via OAuth:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';

export default function ExistingUsersOnly() {
  const { start } = useMoonKey();

  return (
    <button onClick={() => start({ 
      loginMethods: ['google', 'apple'],
      disableSignup: true
    })}>
      Sign in (Existing Users)
    </button>
  );
}
```

## Method 2: Using useLoginWithOAuth

The `useLoginWithOAuth` hook provides dedicated OAuth functionality with more control over the authentication flow.

### Import and Usage

```typescript theme={null}
import { useLoginWithOAuth } from '@moon-key/react-auth';

export default function LoginWithOAuth() {
  const { loginWithOAuth, state } = useLoginWithOAuth();

  const handleGoogleLogin = async () => {
    try {
      await loginWithOAuth({ provider: 'google' });
      // User is now authenticated
    } catch (error) {
      console.error('Login failed:', error);
    }
  };

  return (
    <button onClick={handleGoogleLogin} disabled={state.status === 'loading'}>
      {state.status === 'loading' ? 'Logging in...' : 'Sign in with Google'}
    </button>
  );
}
```

### loginWithOAuth Method

Initiates the OAuth authentication flow for a specific provider:

```typescript theme={null}
loginWithOAuth: ({ 
  provider: 'google' | 'apple',
  disableSignup?: boolean 
}) => Promise<void>
```

#### Parameters

<ParamField path="provider" type="string" required>
  The OAuth provider to use. Options: `'google'` or `'apple'`.
</ParamField>

<ParamField path="disableSignup" type="boolean">
  If true, prevents new user signups and only allows existing users to login.
</ParamField>

### Tracking Flow State

Track the OAuth authentication state:

```typescript theme={null}
state:
  | { status: 'initial' }
  | { status: 'loading' }
  | { status: 'done' }
  | { status: 'error'; error: Error | null }
```

<ResponseField name="status" type="'initial' | 'loading' | 'done' | 'error'">
  The current state of the OAuth flow.
</ResponseField>

<ResponseField name="error" type="Error | null">
  The error that occurred during the OAuth flow (only present when status is 'error').
</ResponseField>

### Complete Example

```tsx theme={null}
import { useLoginWithOAuth, useMoonKey } from '@moon-key/react-auth';
import { useState } from 'react';

export default function OAuthButtons() {
  const { loginWithOAuth, state } = useLoginWithOAuth();
  const { isAuthenticated, user } = useMoonKey();
  const [error, setError] = useState<string | null>(null);

  const handleLogin = async (provider: 'google' | 'apple') => {
    setError(null);
    try {
      await loginWithOAuth({ provider });
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Login failed');
    }
  };

  if (isAuthenticated) {
    return <div>Welcome, {user.email}!</div>;
  }

  return (
    <div>
      <button 
        onClick={() => handleLogin('google')}
        disabled={state.status === 'loading'}
      >
        {state.status === 'loading' ? 'Signing in...' : 'Sign in with Google'}
      </button>

      <button 
        onClick={() => handleLogin('apple')}
        disabled={state.status === 'loading'}
      >
        {state.status === 'loading' ? 'Signing in...' : 'Sign in with Apple'}
      </button>

      {state.status === 'error' && (
        <p style={{ color: 'red' }}>Error: {state.error?.message}</p>
      )}
      
      {error && <p style={{ color: 'red' }}>{error}</p>}
    </div>
  );
}
```

### With Callbacks

You can pass callbacks to handle success and error cases:

```tsx theme={null}
import { useLoginWithOAuth } from '@moon-key/react-auth';

export default function OAuthWithCallbacks() {
  const { loginWithOAuth } = useLoginWithOAuth({
    onSuccess: ({ user, isNewUser }) => {
      console.log('User logged in:', user);
      if (isNewUser) {
        // Handle new user onboarding
        console.log('Welcome new user!');
      }
    },
    onError: (error) => {
      console.error('OAuth login failed:', error);
      // Show error notification
    }
  });

  return (
    <button onClick={() => loginWithOAuth({ provider: 'google' })}>
      Sign in with Google
    </button>
  );
}
```

### Login-only Mode

Prevent new signups and only allow existing users:

```tsx theme={null}
import { useLoginWithOAuth } from '@moon-key/react-auth';

export default function ExistingUsersOnly() {
  const { loginWithOAuth } = useLoginWithOAuth();

  return (
    <button 
      onClick={() => loginWithOAuth({ 
        provider: 'google',
        disableSignup: true 
      })}
    >
      Sign in (Existing Users Only)
    </button>
  );
}
```

## Provider Configuration

You can configure which OAuth providers are available by default in the `MoonKeyProvider`:

```tsx theme={null}
import { MoonKeyProvider } from '@moon-key/react-auth';

export default function App() {
  return (
    <MoonKeyProvider
      publishableKey="your_publishable_key"
      config={{
        loginMethods: ['google', 'apple', 'email'],
        appearance: {
          logo: 'https://your-app.com/logo.png',
          loginHeaderTitle: 'Welcome back',
          loginHeaderDescription: 'Sign in to continue'
        }
      }}
    >
      {/* Your app */}
    </MoonKeyProvider>
  );
}
```

## Using the REST API

For backend implementations or custom integrations, use the MoonKey REST API.

### Initiate OAuth Flow

Start the OAuth authentication flow:

```bash theme={null}
curl -X GET "https://api.moonkey.fun/v1/auth/oauth/google/begin" \
  -H "Authorization: Bearer sk_test_your_api_key"
```

This returns a redirect URL where you should send the user:

```json theme={null}
{
  "url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...",
  "state": "random_state_value"
}
```

### Verify OAuth Token

After the user completes OAuth authentication and is redirected back to your application, verify the OAuth code:

```bash theme={null}
curl -X POST "https://api.moonkey.fun/v1/auth/oauth/verify" \
  -H "Authorization: Bearer sk_test_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "oauth_authorization_code",
    "state": "random_state_value",
    "session_expires_in": 10080
  }'
```

#### Response

```json theme={null}
{
  "session_token": "session_abc123...",
  "session_jwt": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": "user_xyz789",
    "email": "user@example.com",
    "google": {
      "email": "user@gmail.com",
      "name": "John Doe",
      "subject": "google_user_id"
    },
    "created_at": 1704067200,
    "updated_at": 1704067200
  },
  "session": {
    "id": "session_abc123",
    "user_id": "user_xyz789",
    "expires_at": 1704672000,
    "created_at": 1704067200
  }
}
```

### Backend Implementation Example

```javascript theme={null}
// Express.js example
import express from 'express';

const app = express();

// Initiate OAuth flow
app.get('/auth/google', async (req, res) => {
  try {
    const response = await fetch(
      'https://api.moonkey.fun/v1/auth/oauth/google/begin',
      {
        headers: {
          'Authorization': `Bearer ${process.env.MOONKEY_SECRET_KEY}`
        }
      }
    );

    const data = await response.json();
    
    // Store state in session for verification
    req.session.oauthState = data.state;
    
    // Redirect user to Google
    res.redirect(data.url);
  } catch (error) {
    res.status(500).json({ error: 'Failed to initiate OAuth' });
  }
});

// OAuth callback endpoint
app.get('/auth/callback', async (req, res) => {
  const { code, state } = req.query;
  
  // Verify state matches
  if (state !== req.session.oauthState) {
    return res.status(400).json({ error: 'Invalid state parameter' });
  }

  try {
    const response = await fetch(
      'https://api.moonkey.fun/v1/auth/oauth/verify',
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${process.env.MOONKEY_SECRET_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          code,
          state,
          session_expires_in: 10080 // 7 days
        })
      }
    );

    if (!response.ok) {
      throw new Error('OAuth verification failed');
    }

    const data = await response.json();
    
    // Store session token in cookie or return to client
    res.cookie('session_token', data.session_token, {
      httpOnly: true,
      secure: true,
      maxAge: 7 * 24 * 60 * 60 * 1000 // 7 days
    });

    // Redirect to your app
    res.redirect('/dashboard');
  } catch (error) {
    res.status(500).json({ error: 'OAuth verification failed' });
  }
});
```

## Security Best Practices

### Redirect URL Validation

Configure allowed OAuth redirect URLs in the MoonKey Dashboard to restrict where users can be redirected after authentication:

1. Navigate to **Redirect URLs** in the dashboard
2. Add your application's callback URLs
3. Only whitelisted URLs will be accepted

<Warning>
  Always validate redirect URLs to prevent open redirect vulnerabilities.
</Warning>

### State Parameter

The `state` parameter helps prevent CSRF attacks:

* MoonKey generates a unique state value for each OAuth flow
* Store this value in your session
* Verify it matches when handling the callback
* Reject requests with mismatched state values

### HTTPS Only

* Always use HTTPS in production
* Configure OAuth providers to only accept HTTPS redirect URLs
* Never use HTTP for OAuth flows

### Token Storage

* Store session tokens securely (HttpOnly cookies on web)
* Never expose session tokens in URLs or logs
* Use secure, httpOnly cookies when possible

## User Experience

### Loading States

Show appropriate loading states during OAuth flow:

```tsx theme={null}
import { useMoonKey } from '@moon-key/react-auth';
import { useState } from 'react';

export default function OAuthLoginButton() {
  const { start, isAuthenticated } = useMoonKey();
  const [loading, setLoading] = useState(false);

  const handleLogin = async () => {
    setLoading(true);
    try {
      await start({ loginMethods: ['google'] });
    } finally {
      setLoading(false);
    }
  };

  if (isAuthenticated) {
    return <div>Logged in!</div>;
  }

  return (
    <button onClick={handleLogin} disabled={loading}>
      {loading ? 'Redirecting...' : 'Sign in with Google'}
    </button>
  );
}
```

### Error Handling

The MoonKey SDK automatically handles common OAuth errors:

* **User cancellation** - When users close the OAuth popup or decline
* **Invalid credentials** - When OAuth configuration is incorrect
* **Network errors** - Connection issues during the flow
* **State mismatch** - CSRF protection validation failures

### Popup vs Redirect

MoonKey uses popup windows for OAuth flows by default, which:

* Keep users on your page
* Provide a seamless experience
* Work across all modern browsers

For mobile or in-app browsers, MoonKey automatically falls back to redirect-based flows.

## Testing

### Test Mode

During development, use test API keys to:

* Test OAuth flows without affecting production users
* Validate your integration
* Debug callback handling

### Test with Real Providers

Always test with actual OAuth providers:

* Google test accounts
* Apple test accounts
* Verify the complete flow works end-to-end

### Common Test Scenarios

* First-time user signup via OAuth
* Existing user login via OAuth
* User cancels OAuth flow
* Network errors during OAuth
* Invalid or expired OAuth codes
* Multiple OAuth accounts linked to same user

## Troubleshooting

### OAuth flow doesn't start

**Possible causes:**

* OAuth provider not enabled in dashboard
* Invalid OAuth credentials configured
* Missing redirect URLs in dashboard

**Solutions:**

1. Verify provider is enabled in **Login Methods**
2. Check OAuth Client ID and Secret are correct
3. Add your callback URLs to **Redirect URLs**

### Redirect URL mismatch error

**Cause:** The redirect URL doesn't match what's configured in your OAuth provider.

**Solution:**

1. Check the redirect URL in MoonKey Dashboard
2. Ensure it matches exactly in your OAuth provider settings (Google Cloud Console, Apple Developer)
3. Include the protocol (`https://`) and any path components

### State parameter mismatch

**Cause:** The state value doesn't match between initial request and callback.

**Solutions:**

* Ensure you're storing the state in your session correctly
* Check for session timeout issues
* Verify cookies are enabled

### User information not available

**Cause:** OAuth scopes might not include profile information.

**Solution:**
Check your OAuth provider configuration includes the necessary scopes:

* **Google**: `email`, `profile`, `openid`
* **Apple**: `email`, `name`

## Provider-Specific Notes

### Google OAuth

* Supports email and profile information
* Works on web and most browsers
* May not work in some in-app browsers (Facebook, Instagram apps)
* Requires verified domain for production use

### Apple OAuth

* Requires Apple Developer account
* Email may be hidden/private on first login
* Name is only provided on first authentication
* Works across web, iOS, and macOS
