My App
Auth

Sign In

Authenticate existing users

Sign In

Authenticate an existing user and receive authentication tokens.

Endpoint

POST /v1/signin

Request Headers

HeaderTypeRequiredDescription
x-api-keystringYesYour API key
Content-TypestringYesMust be application/json

Request Body

FieldTypeRequiredDescription
emailstringYesUser's email address (valid email format)
passwordstringYesUser's password (minimum 8 characters)

Response

Success Response (200)

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": "user_123",
    "name": "John Doe",
    "email": "[email protected]",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}

Error Responses

CodeDescription
401Invalid or missing API key
422Invalid input data (invalid email format or password too short)
500Server error

Examples

interface SignInRequest {
  email: string;
  password: string;
}

interface SignInResponse {
  token: string;
  user: {
    id: string;
    name: string;
    email: string;
    createdAt: string;
  };
}

async function signIn(credentials: SignInRequest): Promise<SignInResponse> {
  const response = await fetch('https://api.yourstore.com/v1/signin', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.NEXT_PUBLIC_API_KEY!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(credentials),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message || 'Sign in failed');
  }

  return response.json();
}

// Usage
try {
  const result = await signIn({
    email: '[email protected]',
    password: 'SecurePass123',
  });
  
  console.log('Logged in:', result.user.name);
  // Store token and user data in cookies/localStorage
} catch (error) {
  console.error('Sign in error:', error);
}
async function signIn(credentials) {
  const response = await fetch('https://api.yourstore.com/v1/signin', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.NEXT_PUBLIC_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(credentials),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message || 'Sign in failed');
  }

  return response.json();
}

// Usage
signIn({
  email: '[email protected]',
  password: 'SecurePass123',
})
  .then(result => {
    console.log('Logged in:', result.user.name);
    // Store token and user data
  })
  .catch(error => {
    console.error('Sign in error:', error);
  });
'use server'

import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

export async function signInAction(formData: FormData) {
  const email = formData.get('email') as string;
  const password = formData.get('password') as string;

  try {
    const response = await fetch('https://api.yourstore.com/v1/signin', {
      method: 'POST',
      headers: {
        'x-api-key': process.env.BACKEND_API_KEY!,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ email, password }),
    });

    if (!response.ok) {
      return { error: 'Invalid credentials' };
    }

    const data = await response.json();
    
    // Store auth token
    const cookieStore = await cookies();
    cookieStore.set('auth_token', data.token, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      maxAge: 60 * 60 * 24 * 90, // 90 days
    });

    // Store user data
    cookieStore.set('user_data', JSON.stringify(data.user), {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      maxAge: 60 * 60 * 24 * 90,
    });

    // Clear guest token if exists
    cookieStore.delete('guest_token');

  } catch (error) {
    return { error: 'Something went wrong' };
  }

  redirect('/dashboard');
}

If you're using the provided CookieManager utility:

'use server'

import { cookieManager } from '@/lib/auth-tools';

export async function signInAction(email: string, password: string) {
  const response = await fetch('https://api.yourstore.com/v1/signin', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.BACKEND_API_KEY!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ email, password }),
  });

  if (!response.ok) {
    throw new Error('Sign in failed');
  }

  const loginResponse = await response.json();
  
  // This automatically stores tokens and clears guest token
  await cookieManager.setAuthenticatedUser(loginResponse);
  
  return loginResponse.user;
}

After successful sign-in, remember to call the Merge Guest Data endpoint if the user had items in their cart or wishlist before logging in.

Client-Side Form Example

'use client'

import { useState } from 'react';
import { signInAction } from '@/actions/auth';

export default function SignInForm() {
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setLoading(true);
    setError('');

    const formData = new FormData(e.currentTarget);
    const result = await signInAction(formData);

    if (result?.error) {
      setError(result.error);
      setLoading(false);
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        name="email"
        placeholder="Email"
        required
      />
      <input
        type="password"
        name="password"
        placeholder="Password"
        minLength={8}
        required
      />
      {error && <p className="error">{error}</p>}
      <button type="submit" disabled={loading}>
        {loading ? 'Signing in...' : 'Sign In'}
      </button>
    </form>
  );
}

Best Practices

Security Considerations:

  • Always use HTTPS in production
  • Store tokens in httpOnly cookies, never in localStorage
  • Implement rate limiting on the client side
  • Clear sensitive form data after submission

Validation

Always validate input on the client side before making the request:

function validateSignIn(email: string, password: string) {
  const errors: string[] = [];
  
  if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    errors.push('Valid email is required');
  }
  
  if (!password || password.length < 8) {
    errors.push('Password must be at least 8 characters');
  }
  
  return errors;
}

Next Steps

After signing in:

  1. Merge guest data to transfer cart and wishlist items
  2. Redirect user to their dashboard or previous page
  3. Update UI to show authenticated state