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

# Access Tokens

Retrieve session credentials to authenticate requests to your backend.

When a user logs in to your app and becomes **authenticated**, MoonKey issues the user session credentials. These credentials allow your backend to verify that the requesting user is truly authenticated.

## Session Credentials

MoonKey provides two types of session credentials:

### Session Token

An opaque token that can be verified through the MoonKey API:

```
session_vy9YGpubKjVn98cw1nT25Msj7jaIpHBinUfD45KLdAOgn9NqEuE4qGHOEchEG5Ue
```

* Must be verified via `/sessions/verify` API endpoint
* Can be instantly revoked
* No user information exposed in the token itself

### Session JWT

A JSON Web Token (JWT) signed with RS256 that can be verified independently:

```
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
```

* Can be verified using public keys without API call
* Contains session information in claims
* Expires after 5 minutes but can be refreshed

<Info>
  Learn more about the differences in the [Session Token vs JWT](/get-started/sessions/session-token-vs-jwt) guide.
</Info>

## Getting Session Credentials

To retrieve the current user's session credentials, use the `getSessionTokens` method from the `useMoonKey` hook:

```typescript theme={null}
getSessionTokens: () => Promise<{ 
  sessionToken: string; 
  sessionJwt: string 
} | null>
```

### Import

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

### Basic Usage

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

function MyComponent() {
  const { getSessionTokens } = useMoonKey();

  const fetchProtectedData = async () => {
    // Get session credentials
    const credentials = await getSessionTokens();
    
    if (!credentials) {
      console.error('User is not authenticated');
      return;
    }

    const { sessionToken, sessionJwt } = credentials;
    
    // Use credentials to authenticate backend request
    // (see examples below)
  };

  return (
    <button onClick={fetchProtectedData}>
      Fetch Data
    </button>
  );
}
```

### Return Value

The `getSessionTokens` method returns:

* An object with `sessionToken` and `sessionJwt` if the user is authenticated
* `null` if the user is not authenticated

```typescript theme={null}
// When authenticated
{
  sessionToken: "session_abc123...",
  sessionJwt: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}

// When not authenticated
null
```

## Sending Session Credentials

When making requests to your backend, include the session credentials in the request headers.

### With fetch

Using the session token (recommended for most use cases):

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

export default function DataFetcher() {
  const { getSessionTokens } = useMoonKey();

  const fetchData = async () => {
    const credentials = await getSessionTokens();
    
    if (!credentials) {
      throw new Error('Not authenticated');
    }

    const response = await fetch('https://your-api.com/protected', {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${credentials.sessionToken}`,
        'Content-Type': 'application/json'
      }
    });

    return response.json();
  };

  return <button onClick={fetchData}>Load Data</button>;
}
```

Using the session JWT (for offline verification):

```tsx theme={null}
const credentials = await getSessionTokens();

if (!credentials) {
  throw new Error('Not authenticated');
}

const response = await fetch('https://your-api.com/protected', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${credentials.sessionJwt}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
});
```

### With axios

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

export default function DataManager() {
  const { getSessionTokens } = useMoonKey();

  const postData = async (data: any) => {
    const credentials = await getSessionTokens();
    
    if (!credentials) {
      throw new Error('Not authenticated');
    }

    const response = await axios({
      method: 'post',
      url: 'https://your-api.com/protected',
      headers: {
        'Authorization': `Bearer ${credentials.sessionToken}`
      },
      data: data
    });

    return response.data;
  };

  return (
    <button onClick={() => postData({ foo: 'bar' })}>
      Submit
    </button>
  );
}
```

### With custom hooks

Create a reusable hook for authenticated requests:

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

export function useAuthenticatedFetch() {
  const { getSessionTokens, isAuthenticated } = useMoonKey();

  const authenticatedFetch = useCallback(
    async (url: string, options: RequestInit = {}) => {
      if (!isAuthenticated) {
        throw new Error('User is not authenticated');
      }

      const credentials = await getSessionTokens();
      
      if (!credentials) {
        throw new Error('Failed to get session credentials');
      }

      const response = await fetch(url, {
        ...options,
        headers: {
          ...options.headers,
          'Authorization': `Bearer ${credentials.sessionToken}`,
          'Content-Type': 'application/json'
        }
      });

      if (response.status === 401) {
        throw new Error('Session expired');
      }

      return response;
    },
    [getSessionTokens, isAuthenticated]
  );

  return authenticatedFetch;
}

// Usage
function MyComponent() {
  const authenticatedFetch = useAuthenticatedFetch();

  const loadData = async () => {
    try {
      const response = await authenticatedFetch('https://your-api.com/data');
      const data = await response.json();
      console.log(data);
    } catch (error) {
      console.error('Failed to fetch:', error);
    }
  };

  return <button onClick={loadData}>Load Data</button>;
}
```

## Common Patterns

### API Client Wrapper

Create an API client that automatically includes session credentials:

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

class APIClient {
  constructor(private getSessionTokens: () => Promise<any>) {}

  async get(endpoint: string) {
    return this.request('GET', endpoint);
  }

  async post(endpoint: string, data: any) {
    return this.request('POST', endpoint, data);
  }

  async request(method: string, endpoint: string, data?: any) {
    const credentials = await this.getSessionTokens();
    
    if (!credentials) {
      throw new Error('Not authenticated');
    }

    const response = await fetch(`https://your-api.com${endpoint}`, {
      method,
      headers: {
        'Authorization': `Bearer ${credentials.sessionToken}`,
        'Content-Type': 'application/json'
      },
      body: data ? JSON.stringify(data) : undefined
    });

    if (!response.ok) {
      throw new Error(`API error: ${response.status}`);
    }

    return response.json();
  }
}

// Usage in component
export default function DataComponent() {
  const { getSessionTokens } = useMoonKey();
  const api = new APIClient(getSessionTokens);

  const fetchUser = async () => {
    const user = await api.get('/user');
    console.log(user);
  };

  const updateUser = async (userData: any) => {
    const result = await api.post('/user/update', userData);
    console.log(result);
  };

  return (
    <div>
      <button onClick={fetchUser}>Get User</button>
      <button onClick={() => updateUser({ name: 'John' })}>
        Update User
      </button>
    </div>
  );
}
```

### With React Query

Integrate with React Query for data fetching:

```tsx theme={null}
import { useQuery, useMutation } from '@tanstack/react-query';
import { useMoonKey } from '@moon-key/react-auth';

function useAuthenticatedQuery() {
  const { getSessionTokens } = useMoonKey();

  return useQuery({
    queryKey: ['userData'],
    queryFn: async () => {
      const credentials = await getSessionTokens();
      
      if (!credentials) {
        throw new Error('Not authenticated');
      }

      const response = await fetch('https://your-api.com/user', {
        headers: {
          'Authorization': `Bearer ${credentials.sessionToken}`
        }
      });

      if (!response.ok) {
        throw new Error('Failed to fetch user data');
      }

      return response.json();
    }
  });
}

// Usage
export default function UserProfile() {
  const { data, isLoading, error } = useAuthenticatedQuery();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h1>User Profile</h1>
      <p>{data.email}</p>
    </div>
  );
}
```

### Error Handling

Properly handle authentication errors:

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

export default function SecureDataFetcher() {
  const { getSessionTokens, start } = useMoonKey();
  const [error, setError] = useState<string | null>(null);

  const fetchSecureData = async () => {
    setError(null);
    
    try {
      const credentials = await getSessionTokens();
      
      if (!credentials) {
        setError('Please log in to continue');
        return;
      }

      const response = await fetch('https://your-api.com/secure-data', {
        headers: {
          'Authorization': `Bearer ${credentials.sessionToken}`
        }
      });

      if (response.status === 401) {
        setError('Your session has expired. Please log in again.');
        return;
      }

      if (!response.ok) {
        throw new Error(`Server error: ${response.status}`);
      }

      const data = await response.json();
      console.log('Fetched data:', data);
      
    } catch (err) {
      setError(err instanceof Error ? err.message : 'An error occurred');
    }
  };

  return (
    <div>
      <button onClick={fetchSecureData}>Fetch Secure Data</button>
      {error && (
        <div style={{ color: 'red' }}>
          {error}
          {error.includes('log in') && (
            <button onClick={() => start()}>Login</button>
          )}
        </div>
      )}
    </div>
  );
}
```

### With Next.js API Routes

Make authenticated requests to Next.js API routes:

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

export default function ClientComponent() {
  const { getSessionTokens } = useMoonKey();

  const callAPI = async () => {
    const credentials = await getSessionTokens();
    
    if (!credentials) {
      console.error('Not authenticated');
      return;
    }

    const response = await fetch('/api/protected', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${credentials.sessionToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ data: 'example' })
    });

    const result = await response.json();
    console.log(result);
  };

  return <button onClick={callAPI}>Call Protected API</button>;
}
```

```typescript theme={null}
// app/api/protected/route.ts (Next.js App Router)
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const authHeader = request.headers.get('authorization');
  
  if (!authHeader?.startsWith('Bearer ')) {
    return NextResponse.json(
      { error: 'Missing authorization header' },
      { status: 401 }
    );
  }

  const sessionToken = authHeader.substring(7);

  // Verify session with MoonKey API
  const verifyResponse = await fetch(
    'https://api.moonkey.fun/v1/auth/sessions/verify',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.MOONKEY_SECRET_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ session_token: sessionToken })
    }
  );

  if (!verifyResponse.ok) {
    return NextResponse.json(
      { error: 'Invalid session' },
      { status: 401 }
    );
  }

  const { user } = await verifyResponse.json();

  // Process request with authenticated user
  return NextResponse.json({
    message: 'Success',
    userId: user.id
  });
}
```

## Best Practices

### Always Check for Null

The `getSessionTokens` method returns `null` when the user is not authenticated:

```tsx theme={null}
const credentials = await getSessionTokens();

if (!credentials) {
  // Handle unauthenticated state
  console.error('User is not authenticated');
  return;
}

// Safe to use credentials here
const { sessionToken, sessionJwt } = credentials;
```

### Handle Expired Sessions

Session tokens can expire or become invalid:

```tsx theme={null}
const fetchData = async () => {
  const credentials = await getSessionTokens();
  
  if (!credentials) {
    throw new Error('Not authenticated');
  }

  const response = await fetch('https://your-api.com/data', {
    headers: {
      'Authorization': `Bearer ${credentials.sessionToken}`
    }
  });

  if (response.status === 401) {
    // Session expired - redirect to login or refresh
    console.error('Session expired');
    // Optionally trigger re-authentication
    start();
    return;
  }

  return response.json();
};
```

### Choose the Right Credential Type

**Use Session Token when:**

* You need real-time revocation
* Security is the top priority
* You're making requests to your own backend

**Use Session JWT when:**

* You need offline verification
* Performance is critical (no API call needed)
* You're integrating with external JWT-based systems

### Secure Storage

The MoonKey SDK automatically handles secure storage of session credentials in IndexedDB. You don't need to manually store these values.
