Skip to main content

Authentication

Studley AI uses a dual authentication system combining JWT session tokens with Supabase Auth for secure API access. All authenticated endpoints require a valid session cookie.

Authentication Methods

Studley AI supports multiple authentication methods:
  • Email/Password - Standard email and password authentication
  • Google OAuth - Sign in with Google
  • Clever SSO - Single sign-on for educational institutions
  • Multi-Factor Authentication (MFA) - Optional TOTP-based MFA for enhanced security

Session Tokens

After successful authentication, the API issues a JWT session token stored as an HTTP-only cookie.

Session Token Format

Session tokens are signed JWTs containing:
{
  userId: string      // Unique user identifier
  username: string    // User's username or email
  isAdmin?: boolean   // Admin privilege flag (optional)
  iat: number         // Issued at timestamp
  exp: number         // Expiration timestamp (7 days)
}

Token Expiration

Session tokens expire after 7 days. After expiration, users must re-authenticate.
Session tokens are HTTP-only cookies and cannot be accessed via JavaScript. This protects against XSS attacks.

Authentication Flow

1. Login

Authenticate a user and receive a session cookie:
curl -X POST https://api.studley.ai/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "SecurePassword123!"
  }'
Response (Success):
{
  "success": true,
  "user": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "email": "[email protected]",
    "name": "student"
  }
}
Response (MFA Required): If the user has MFA enabled:
{
  "success": false,
  "mfaRequired": true,
  "challengeId": "challenge_abc123",
  "factorId": "factor_xyz789",
  "message": "MFA code required"
}

2. MFA Verification (If Required)

Complete MFA verification with TOTP code:
curl -X POST https://api.studley.ai/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "SecurePassword123!",
    "mfaCode": "123456",
    "challengeId": "challenge_abc123"
  }'
Response:
{
  "success": true,
  "mfaVerified": true,
  "user": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "email": "[email protected]",
    "name": "student"
  }
}

3. Get Current User

Retrieve the authenticated user’s information:
curl https://api.studley.ai/api/auth/me \
  -H "Cookie: session=YOUR_SESSION_TOKEN"
Response:
{
  "user": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "email": "[email protected]",
    "name": "Jane Student",
    "avatar_url": "https://example.com/avatar.jpg"
  }
}

4. Logout

End the user session:
curl -X POST https://api.studley.ai/api/auth/logout \
  -H "Cookie: session=YOUR_SESSION_TOKEN"
Response:
{
  "success": true,
  "message": "Logged out successfully"
}

Using Session Cookies

In Browser JavaScript

The session cookie is automatically included in requests from the browser:
const response = await fetch('/api/ai-tutor/chat', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  credentials: 'include', // Important: include cookies
  body: JSON.stringify({
    message: 'Explain photosynthesis',
    sessionId: 'session_123'
  })
});

const data = await response.json();

In Server-to-Server Requests

For server-to-server API calls, manually include the session cookie:
curl -X POST https://api.studley.ai/api/generate-quiz \
  -H "Content-Type: application/json" \
  -H "Cookie: session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{
    "topic": "Biology",
    "numQuestions": 5
  }'

Supabase Integration

Studley AI uses Supabase for authentication backend. The API handles session management through Supabase Auth:

Environment Variables

NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SESSION_SECRET=your-jwt-secret-key
Never expose your SESSION_SECRET or Supabase service role key in client-side code. Use environment variables and keep them secure.

Creating Server Client

The API creates Supabase clients for server-side authentication:
import { createClient } from '@/lib/supabase/server';

export async function GET() {
  const supabase = await createClient();
  
  const { data: { user }, error } = await supabase.auth.getUser();
  
  if (error || !user) {
    return NextResponse.json(
      { error: 'Not authenticated' },
      { status: 401 }
    );
  }
  
  // User is authenticated
  return NextResponse.json({ user });
}

Protected Routes

Many API endpoints require authentication. Protected routes will return a 401 Unauthorized error if no valid session is present:
{
  "error": "Not authenticated"
}

Example: Protected Endpoint

curl https://api.studley.ai/api/ai-tutor/sessions \
  -H "Cookie: session=YOUR_SESSION_TOKEN"
Without authentication:
{
  "error": "Not authenticated"
}

Security Best Practices

Follow these security best practices when working with the Studley AI API:

1. Use HTTPS

Always use HTTPS in production to protect session tokens in transit:
// Session cookies are marked secure in production
cookieStore.set('session', token, {
  httpOnly: true,
  secure: process.env.NODE_ENV === 'production', // HTTPS only
  sameSite: 'lax',
  maxAge: 60 * 60 * 24 * 7, // 7 days
  path: '/'
});

2. Store Secrets Securely

  • Never commit secrets to version control
  • Use environment variables for all sensitive configuration
  • Rotate secrets regularly
  • Use different secrets for development and production

3. Handle Session Expiration

Implement proper error handling for expired sessions:
try {
  const response = await fetch('/api/auth/me', {
    credentials: 'include'
  });
  
  if (response.status === 401) {
    // Session expired, redirect to login
    window.location.href = '/login';
  }
  
  const data = await response.json();
} catch (error) {
  console.error('Authentication error:', error);
}

4. Implement Rate Limiting

The API automatically rate limits authentication attempts to prevent brute force attacks. After multiple failed login attempts, temporary lockouts are applied.

5. Enable MFA for Sensitive Operations

Encourage users to enable multi-factor authentication for enhanced security, especially for admin accounts and sensitive operations.

OAuth Integration

Google OAuth

Authenticate using Google:
# Initiate OAuth flow
GET https://api.studley.ai/api/auth/google
The endpoint redirects to Google’s OAuth consent screen. After authorization, users are redirected back with a session token.

Clever SSO

For educational institutions using Clever:
# Initiate Clever SSO flow
GET https://api.studley.ai/api/auth/clever

# Callback endpoint
GET https://api.studley.ai/api/auth/clever/callback

Error Responses

Invalid Credentials

{
  "error": "Invalid email or password"
}
Status Code: 401 Unauthorized

Missing Required Fields

{
  "error": "Email and password are required"
}
Status Code: 400 Bad Request

Session Expired

{
  "error": "Not authenticated"
}
Status Code: 401 Unauthorized

MFA Error

{
  "error": "Invalid MFA code"
}
Status Code: 401 Unauthorized

Next Steps

AI Tutor API

Start building with the AI Tutor API

Content Generation

Generate study materials programmatically

Rate Limits

Understanding rate limits

Error Handling

Handling API errors gracefully

Build docs developers (and LLMs) love