Docs

Sign In API

Authentication endpoints for logging in users via credentials or OAuth

Sign In API

Authenticate existing users with email/password credentials or OAuth providers. Returns a session token for authenticated requests.

Endpoint

POST /api/auth/sign-in

Email/Password Authentication

Request

{
  "email": "user@example.com",
  "password": "securePassword123!",
  "rememberMe": true // Optional: extend session duration
}

Request Parameters

FieldTypeRequiredDescription
emailstringYesUser's registered email
passwordstringYesUser's password
rememberMebooleanNoExtend session to 30 days (default: 7 days)

Success Response (200)

{
  "success": true,
  "data": {
    "user": {
      "id": "usr_123456",
      "email": "user@example.com",
      "name": "John Doe",
      "emailVerified": true,
      "image": "https://cdn.example.com/avatars/usr_123456.jpg",
      "organizations": [
        {
          "id": "org_789",
          "name": "Acme Inc",
          "role": "owner"
        }
      ]
    },
    "session": {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
      "expiresAt": "2024-01-22T10:30:00Z",
      "refreshToken": "rt_abc123..." // For token refresh
    }
  },
  "message": "Signed in successfully"
}

Error Responses

Invalid Credentials (401)

{
  "success": false,
  "error": {
    "code": "INVALID_CREDENTIALS",
    "message": "Invalid email or password"
  }
}

Email Not Verified (403)

{
  "success": false,
  "error": {
    "code": "EMAIL_NOT_VERIFIED",
    "message": "Please verify your email before signing in",
    "resendUrl": "/api/auth/resend-verification"
  }
}

Account Locked (423)

{
  "success": false,
  "error": {
    "code": "ACCOUNT_LOCKED",
    "message": "Account temporarily locked due to too many failed attempts",
    "unlockAt": "2024-01-15T11:30:00Z"
  }
}

OAuth Authentication

Initiate OAuth sign-in flow for existing users.

Request

{
  "provider": "google",
  "callbackUrl": "/dashboard",
  "organizationId": "org_789" // Optional: for SSO context
}

Response (200)

{
  "success": true,
  "data": {
    "authorizationUrl": "https://accounts.google.com/o/oauth2/v2/auth?..."
  }
}

Sign in via passwordless email link.

{
  "email": "user@example.com",
  "callbackUrl": "/dashboard"
}

Response (200)

{
  "success": true,
  "data": {
    "sent": true,
    "expiresIn": 3600
  },
  "message": "Magic link sent to your email"
}
GET /api/auth/sign-in/magic?token=xyz123&callbackUrl=/dashboard

Redirects to callback URL with session cookie on success.

Code Examples

cURL

curl -X POST https://api.yourdomain.com/api/auth/sign-in \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securePassword123!",
    "rememberMe": true
  }'

JavaScript/TypeScript

interface SignInCredentials {
  email: string;
  password: string;
  rememberMe?: boolean;
}

interface SignInResponse {
  success: boolean;
  data?: {
    user: User;
    session: Session;
  };
  error?: {
    code: string;
    message: string;
  };
}

async function signIn(credentials: SignInCredentials): Promise<SignInResponse> {
  const response = await fetch('/api/auth/sign-in', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(credentials)
  });

  return response.json();
}

// Usage
const result = await signIn({
  email: 'user@example.com',
  password: 'securePassword123!',
  rememberMe: true
});

if (result.success) {
  // Session cookie is automatically set
  window.location.href = '/dashboard';
} else {
  console.error(result.error?.message);
}

React Component Example

import { useState } from 'react';

export function SignInForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [rememberMe, setRememberMe] = useState(false);
  const [error, setError] = useState('');
  const [isLoading, setIsLoading] = useState(false);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError('');
    setIsLoading(true);

    try {
      const response = await fetch('/api/auth/sign-in', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, password, rememberMe })
      });

      const result = await response.json();

      if (!result.success) {
        setError(result.error.message);
        return;
      }

      window.location.href = '/dashboard';
    } catch {
      setError('An unexpected error occurred');
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {error && <div className="error">{error}</div>}
      
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
        required
      />
      
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password"
        required
      />
      
      <label>
        <input
          type="checkbox"
          checked={rememberMe}
          onChange={(e) => setRememberMe(e.target.checked)}
        />
        Remember me
      </label>
      
      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Signing in...' : 'Sign In'}
      </button>
    </form>
  );
}

Provider-Specific Behavior

BetterAuth

  • Validates against local database
  • Supports 2FA challenge after password verification
  • Session stored in database with configurable expiry

NextAuth

  • Uses configured credentials provider
  • Supports JWT or database session strategies
  • Automatic session refresh

Clerk

  • Delegates to Clerk's sign-in API
  • Supports MFA/2FA flows
  • Session managed by Clerk SDK

AuthKit

  • Uses WorkOS authentication
  • Supports SSO via organization context
  • Enterprise directory authentication

Security Features

FeatureDescription
Brute Force ProtectionAccount locks after 5 failed attempts
Secure CookiesHttpOnly, Secure, SameSite=Strict
CSRF ProtectionToken validation on all requests
Rate LimitingIP-based throttling
Suspicious Activity DetectionAlerts on unusual login patterns

Session Durations

TypeDurationUse Case
Standard7 daysRegular usage
Remember Me30 daysPersonal devices
OAuth7 daysSocial login
Magic Link1 hourOne-time access

Webhook Events

EventTrigger
user.signed_inSuccessful authentication
user.sign_in_failedFailed attempt (with reason)
user.lockedAccount locked due to failures

Rate Limits

  • Email/Password: 10 attempts per IP per 15 minutes
  • Magic Link requests: 3 per email per hour
  • OAuth: 20 initiations per IP per hour

On this page