Skip to main content
POST
/
api
/
auth
/
signin
Sign In
curl --request POST \
  --url https://api.example.com/api/auth/signin \
  --header 'Content-Type: application/json' \
  --data '
{
  "email": "<string>",
  "password": "<string>"
}
'
{
  "Location": {},
  "Set-Cookie": {},
  "sb-access-token": {},
  "sb-refresh-token": {},
  "Retry-After": {}
}

Overview

This endpoint authenticates an existing user using their email and password with Supabase Authentication. Upon successful login, the user receives session tokens and is redirected to the homepage.

Authentication

This endpoint does not require prior authentication (it creates the authentication session).

Rate Limiting

This endpoint is protected by rate limiting middleware:
  • Default limit: 100 requests per 60 seconds
  • Returns 429 Too Many Requests when limit is exceeded
  • Prevents brute force attacks

Request Body

This endpoint accepts application/x-www-form-urlencoded form data (typically from an HTML form submission).
email
string
required
User’s registered email address.Example: [email protected]
password
string
required
User’s password.Example: SecurePass123!

Response

Upon successful authentication, this endpoint redirects to the homepage (/) with a 302 Found status code.
The redirect response includes:
Location
header
Redirect URL: /
Session cookies containing authentication tokens

Cookies Set

Upon successful sign-in, the following HTTP-only cookies are automatically set:
sb-access-token
cookie
Attributes: HttpOnly, Secure, SameSite=Lax, Max-Age=7 daysContains the Supabase access token for authenticated requests
sb-refresh-token
cookie
Attributes: HttpOnly, Secure, SameSite=Lax, Max-Age=7 daysContains the Supabase refresh token to maintain the session

Example Request

curl -X POST "https://anidev.vercel.app/api/auth/signin" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "[email protected]&password=SecurePass123!" \
  -L \
  -c cookies.txt

Success Response

Status Code: 302 Found (Redirect) Headers:
Location: /
Set-Cookie: sb-access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...; HttpOnly; Secure; SameSite=Lax; Max-Age=604800; Path=/
Set-Cookie: sb-refresh-token=v1.MRjyg-VNJ8H7zN...; HttpOnly; Secure; SameSite=Lax; Max-Age=604800; Path=/

Error Responses

Missing Credentials

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

Invalid Credentials

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

Account Not Found

Status Code: 401 Unauthorized
{
  "error": "No user found with this email",
  "type": "unauthorized"
}

Rate Limit Exceeded

Status Code: 429 Too Many Requests
{
  "error": "Too many requests, please try again later",
  "type": "tooManyRequests"
}
Retry-After
header
Number of seconds to wait before making another request

Server Error

Status Code: 500 Internal Server Error
{
  "error": "Internal server error"
}

Security Features

Important Security Notes:
  • Passwords are never stored in plain text - Supabase uses secure bcrypt hashing
  • Session tokens are stored in HTTP-only cookies to prevent XSS attacks
  • Cookies use the Secure flag (HTTPS only) in production
  • SameSite=Lax prevents CSRF attacks
  • Rate limiting prevents brute force login attempts
  • Failed login attempts do not reveal whether the email exists

Session Management

Once signed in:
  • Access Token: Valid for 1 hour by default
  • Refresh Token: Valid for 7 days (matches cookie max-age)
  • Auto-Refresh: The client should implement token refresh logic before expiration
  • Cookie Expiry: Cookies expire after 7 days, requiring re-authentication

Handling Authentication State

// Check if user is authenticated
const checkAuth = async () => {
  try {
    const response = await fetch('/api/auth/session', {
      credentials: 'include'
    });
    
    if (response.ok) {
      const session = await response.json();
      return session.user;
    }
  } catch (err) {
    console.error('Not authenticated');
  }
  return null;
};

// Use in your app
const user = await checkAuth();
if (!user) {
  // Redirect to sign in page
  window.location.href = '/signin';
}

Redirect Behavior

Default Redirect: After successful sign-in, users are redirected to / (homepage).To customize the redirect destination, you can:
  1. Add a redirect query parameter to the form action
  2. Modify the endpoint to accept a returnTo parameter
  3. Store the intended destination in session storage before redirecting to sign-in

Form Integration Example

---
// signin.astro
const error = Astro.url.searchParams.get('error');
---

<form action="/api/auth/signin" method="POST">
  <input 
    type="email" 
    name="email" 
    placeholder="Email" 
    required 
  />
  <input 
    type="password" 
    name="password" 
    placeholder="Password" 
    required 
  />
  
  {error && <p class="error">{error}</p>}
  
  <button type="submit">Sign In</button>
  
  <p>
    Don't have an account? 
    <a href="/signup">Sign up</a>
  </p>
</form>
  • Sign Up - Create a new user account
  • Sign Out - End the current session
  • Session - Check current authentication status
  • Get Profile - Retrieve authenticated user’s profile

Build docs developers (and LLMs) love