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-inEmail/Password Authentication
Request
{
"email": "user@example.com",
"password": "securePassword123!",
"rememberMe": true // Optional: extend session duration
}Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User's registered email |
password | string | Yes | User's password |
rememberMe | boolean | No | Extend 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?..."
}
}Magic Link Authentication
Sign in via passwordless email link.
Request Magic Link
{
"email": "user@example.com",
"callbackUrl": "/dashboard"
}Response (200)
{
"success": true,
"data": {
"sent": true,
"expiresIn": 3600
},
"message": "Magic link sent to your email"
}Verify Magic Link
GET /api/auth/sign-in/magic?token=xyz123&callbackUrl=/dashboardRedirects 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
| Feature | Description |
|---|---|
| Brute Force Protection | Account locks after 5 failed attempts |
| Secure Cookies | HttpOnly, Secure, SameSite=Strict |
| CSRF Protection | Token validation on all requests |
| Rate Limiting | IP-based throttling |
| Suspicious Activity Detection | Alerts on unusual login patterns |
Session Durations
| Type | Duration | Use Case |
|---|---|---|
| Standard | 7 days | Regular usage |
| Remember Me | 30 days | Personal devices |
| OAuth | 7 days | Social login |
| Magic Link | 1 hour | One-time access |
Webhook Events
| Event | Trigger |
|---|---|
user.signed_in | Successful authentication |
user.sign_in_failed | Failed attempt (with reason) |
user.locked | Account 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