# Authentication API Documentation

Base URL: `http://your-domain.com/api/auth`

---

## 1. Register User

Creates a new user account.

### Endpoint

```
POST /register
```

### Headers

```
Content-Type: multipart/form-data
```

### Request Body (Form Data)

| Field           | Type         | Required | Description                             |
| --------------- | ------------ | -------- | --------------------------------------- |
| firstName       | String       | No       | User's first name                       |
| lastName        | String       | No       | User's last name                        |
| username        | String       | Yes      | Unique username                         |
| email           | String       | Yes      | User's email address                    |
| password        | String       | Yes      | User's password                         |
| shortBio        | String       | No       | Short biography                         |
| occupation      | String       | No       | User's occupation                       |
| favouriteGenres | String/Array | No       | JSON string or array of genre ObjectIds |
| role            | String       | Yes      | User role: "user" or "admin"            |
| pfp             | File         | No       | Profile picture (image file)            |

### Example Request (JavaScript with axios)

```javascript
const formData = new FormData();
formData.append("firstName", "John");
formData.append("lastName", "Doe");
formData.append("username", "johndoe");
formData.append("email", "john@example.com");
formData.append("password", "securePassword123");
formData.append("shortBio", "Book lover and avid reader");
formData.append("occupation", "Teacher");
formData.append(
  "favouriteGenres",
  JSON.stringify(["64a1b2c3d4e5f6g7h8i9j0k1", "64a1b2c3d4e5f6g7h8i9j0k2"])
);
formData.append("role", "user");
formData.append("pfp", fileInput.files[0]);

const response = await axios.post("/api/auth/register", formData, {
  headers: { "Content-Type": "multipart/form-data" },
});
```

### Success Response (201 Created)

```json
{
  "success": true,
  "message": "User Registered Successfully. Please log in."
}
```

### Error Responses

**400 Bad Request** - Missing required fields

```json
{
  "message": "Fill all required fields"
}
```

**400 Bad Request** - Email already exists

```json
{
  "message": "User with this email already exists"
}
```

**400 Bad Request** - Username already exists

```json
{
  "message": "User with this username already exists"
}
```

**400 Bad Request** - Invalid genre format

```json
{
  "message": "Invalid favouriteGenres data"
}
```

---

## 2. Login

Authenticates a user and returns a JWT token or sets a cookie.

### Endpoint

```
POST /login
```

### Headers

```
Content-Type: application/json
```

### Request Body (JSON)

| Field           | Type   | Required | Description                                               |
| --------------- | ------ | -------- | --------------------------------------------------------- |
| emailOrUsername | String | Yes      | User's email or username                                  |
| password        | String | Yes      | User's password                                           |
| from            | String | No       | "web" for API response, omit for admin cookie-based login |

### Example Request (Web/API Login)

```javascript
const response = await axios.post("/api/auth/login", {
  emailOrUsername: "johndoe",
  password: "securePassword123",
  from: "web",
});
```

### Success Response (200 OK) - Web Login

```json
{
  "success": true,
  "message": "User Logged In Successfully",
  "authtoken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

### Success Response (200 OK) - Admin Login

```
Redirects to: /admin?message=User Logged In Successfully
Sets Cookie: authtoken (httpOnly, secure in production)
```

### Error Responses

**400 Bad Request** - Missing fields

```json
{
  "message": "Fill all fields"
}
```

**400 Bad Request** - Invalid credentials

```json
{
  "message": "Invalid Credentials"
}
```

---

## 3. Logout

Logs out the user by clearing the authentication cookie.

### Endpoint

```
POST /logout
```

### Headers

```
Content-Type: application/json
Authorization: Bearer <token>
```

OR

```
Cookie: authtoken=<token>
```

### Request Body

None

### Example Request

```javascript
const response = await axios.post(
  "/api/auth/logout",
  {},
  {
    headers: {
      Authorization: `Bearer ${authToken}`,
    },
  }
);
```

### Success Response (200 OK)

```json
{
  "success": true,
  "message": "Logged out successfully"
}
```

### Error Responses

**401 Unauthorized** - Missing or invalid token

```json
{
  "message": "Not authorized, no token"
}
```

---

## 4. Forgot Password

Sends a password reset email to the user.

### Endpoint

```
POST /forgot-password
```

### Headers

```
Content-Type: application/json
```

### Request Body (JSON)

| Field | Type   | Required | Description          |
| ----- | ------ | -------- | -------------------- |
| email | String | Yes      | User's email address |

### Example Request

```javascript
const response = await axios.post("/api/auth/forgot-password", {
  email: "john@example.com",
});
```

### Success Response (200 OK)

```json
{
  "success": true,
  "message": "Password reset link has been sent to your email."
}
```

**Note:** For security reasons, this endpoint returns the same success message whether or not the email exists in the system.

### Error Responses

**400 Bad Request** - Missing email

```json
{
  "message": "Email is required"
}
```

**500 Internal Server Error** - Email sending failed

```json
{
  "message": "Failed to send password reset email. Please try again later."
}
```

---

## 5. Reset Password

Resets the user's password using the token from the email.

### Endpoint

```
POST /reset-password/:token
```

### URL Parameters

| Parameter | Type   | Required | Description                |
| --------- | ------ | -------- | -------------------------- |
| token     | String | Yes      | Reset token from email URL |

### Headers

```
Content-Type: application/json
```

### Request Body (JSON)

| Field    | Type   | Required | Description                         |
| -------- | ------ | -------- | ----------------------------------- |
| password | String | Yes      | New password (minimum 6 characters) |

### Example Request

```javascript
const token = "abc123def456..."; // From email URL
const response = await axios.post(`/api/auth/reset-password/${token}`, {
  password: "newSecurePassword123",
});
```

### Success Response (200 OK)

```json
{
  "success": true,
  "message": "Password reset successful. You can now login with your new password."
}
```

### Error Responses

**400 Bad Request** - Missing password

```json
{
  "message": "Password is required"
}
```

**400 Bad Request** - Password too short

```json
{
  "message": "Password must be at least 6 characters long"
}
```

**400 Bad Request** - Invalid or expired token

```json
{
  "message": "Invalid or expired reset token"
}
```

---

## Authentication Flow

### Web Application Flow

1. **Register**: `POST /register` → Returns success message
2. **Login**: `POST /login` with `from: "web"` → Returns JWT token
3. **Store Token**: Save token in localStorage/state
4. **Authenticated Requests**: Include token in `Authorization: Bearer <token>` header
5. **Logout**: `POST /logout` → Clear token from client

### Admin Dashboard Flow

1. **Register**: `POST /register` → Returns success message
2. **Login**: `POST /login` (without `from` field) → Sets httpOnly cookie, redirects to `/admin`
3. **Authenticated Requests**: Cookie automatically sent with requests
4. **Logout**: `POST /logout` → Clears cookie

### Password Reset Flow

1. **Request Reset**: `POST /forgot-password` → User receives email
2. **Click Link**: User clicks reset link in email (valid for 1 hour)
3. **Reset Password**: `POST /reset-password/:token` → Password updated
4. **Login**: `POST /login` with new password

---

## Error Handling

All endpoints follow this error response format:

```json
{
  "message": "Error description"
}
```

### Common HTTP Status Codes

- `200 OK` - Request successful
- `201 Created` - Resource created successfully
- `400 Bad Request` - Invalid input or validation error
- `401 Unauthorized` - Missing or invalid authentication
- `500 Internal Server Error` - Server error

---

## Security Notes

1. **Passwords**: Hashed using bcrypt with salt rounds of 10
2. **JWT Tokens**: Valid for 24 hours (1 day)
3. **Reset Tokens**: Valid for 1 hour, hashed before storage
4. **Cookies**: httpOnly, secure in production, sameSite: 'lax'
5. **Email Privacy**: Forgot password doesn't reveal if email exists

---

## Environment Variables

Required environment variables:

```env
JWT_SECRET=your_jwt_secret_key
EMAIL_USER=info@craigphotoletters.com
EMAIL_PASS=your_email_password
NODE_ENV=production  # Set to 'production' for secure cookies
```

---

## Complete React Example

```javascript
import axios from "axios";

const API_URL = "http://your-domain.com/api/auth";

// Create axios instance with interceptor
const api = axios.create({
  baseURL: API_URL,
  headers: {
    "Content-Type": "application/json",
  },
});

// Add token to requests automatically
api.interceptors.request.use((config) => {
  const token = localStorage.getItem("authtoken");
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// Register
export const register = async (userData) => {
  const formData = new FormData();
  Object.keys(userData).forEach((key) => {
    if (key === "favouriteGenres") {
      formData.append(key, JSON.stringify(userData[key]));
    } else {
      formData.append(key, userData[key]);
    }
  });

  const response = await axios.post(`${API_URL}/register`, formData, {
    headers: { "Content-Type": "multipart/form-data" },
  });
  return response.data;
};

// Login
export const login = async (emailOrUsername, password) => {
  const response = await api.post("/login", {
    emailOrUsername,
    password,
    from: "web",
  });

  if (response.data.authtoken) {
    localStorage.setItem("authtoken", response.data.authtoken);
  }

  return response.data;
};

// Logout
export const logout = async () => {
  const response = await api.post("/logout");
  localStorage.removeItem("authtoken");
  return response.data;
};

// Forgot Password
export const forgotPassword = async (email) => {
  const response = await api.post("/forgot-password", { email });
  return response.data;
};

// Reset Password
export const resetPassword = async (token, password) => {
  const response = await api.post(`/reset-password/${token}`, { password });
  return response.data;
};
```

---

## Postman Collection

Import this JSON to test all endpoints:

```json
{
  "info": {
    "name": "Reading Hub Auth API",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "Register",
      "request": {
        "method": "POST",
        "header": [],
        "body": {
          "mode": "formdata",
          "formdata": [
            { "key": "username", "value": "testuser" },
            { "key": "email", "value": "test@example.com" },
            { "key": "password", "value": "password123" },
            { "key": "role", "value": "user" }
          ]
        },
        "url": "{{baseUrl}}/register"
      }
    },
    {
      "name": "Login",
      "request": {
        "method": "POST",
        "header": [{ "key": "Content-Type", "value": "application/json" }],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"emailOrUsername\": \"testuser\",\n  \"password\": \"password123\",\n  \"from\": \"web\"\n}"
        },
        "url": "{{baseUrl}}/login"
      }
    },
    {
      "name": "Logout",
      "request": {
        "method": "POST",
        "header": [{ "key": "Authorization", "value": "Bearer {{token}}" }],
        "url": "{{baseUrl}}/logout"
      }
    },
    {
      "name": "Forgot Password",
      "request": {
        "method": "POST",
        "header": [{ "key": "Content-Type", "value": "application/json" }],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"email\": \"test@example.com\"\n}"
        },
        "url": "{{baseUrl}}/forgot-password"
      }
    },
    {
      "name": "Reset Password",
      "request": {
        "method": "POST",
        "header": [{ "key": "Content-Type", "value": "application/json" }],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"password\": \"newPassword123\"\n}"
        },
        "url": "{{baseUrl}}/reset-password/{{resetToken}}"
      }
    }
  ],
  "variable": [
    { "key": "baseUrl", "value": "http://localhost:5000/api/auth" },
    { "key": "token", "value": "" },
    { "key": "resetToken", "value": "" }
  ]
}
```
