Smart Library Docs

Auth Endpoints

Detailed API reference for authentication endpoints — Setup, Register, Login, Refresh, Logout, and Change Password.

Auth Endpoints

Base path: /api/v1/auth

Rate Limiting

EndpointLimiterLimit
POST /setupIP-based20 req / 15 min
POST /registerIP-based3 req / hour
POST /loginIP + Email5 req / 15 min (email), 20 req / 15 min (IP)
POST /refreshToken-based30 req / min
POST /logoutNone
POST /change-passwordAuthenticatedGlobal API limiter

POST /auth/setup

Creates the initial Super Admin account. Can only be called once — returns 403 if an admin already exists.

Request

POST /api/v1/auth/setup
Content-Type: application/json
{
  "firstName": "System",
  "lastName": "Admin",
  "email": "admin@university.edu",
  "contactNumber": "+1234567890",
  "password": "SecureP@ssw0rd123"
}

Response — 201 Created

{
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "user": {
    "_id": "64b8f3a2e7d1c...",
    "firstName": "System",
    "lastName": "Admin",
    "email": "admin@university.edu",
    "roleId": "64b8f...",
    "status": "ACTIVE"
  }
}

A refreshToken is set as an HttpOnly cookie.

Error Responses

StatusCodeCondition
403Admin already exists
400Admin role not found (roles not seeded)

POST /auth/register

Creates a new Student account.

Request

{
  "firstName": "Aarav",
  "lastName": "Sharma",
  "email": "aarav@university.edu",
  "contactNumber": "+919876543210",
  "rollNumber": "CSE-2024-001",
  "password": "MyP@ssw0rd123"
}

Response — 201 Created

{
  "message": "Registration successful"
}

A welcome email is sent asynchronously.

Error Responses

StatusCondition
400Roll number already exists
400Email already exists
500Student role not found in database
429Rate limited (3/hour per IP)

POST /auth/login

Authenticates a user by email or roll number.

Request

{
  "identifier": "aarav@university.edu",
  "password": "MyP@ssw0rd123"
}

The identifier field accepts either an email address or a roll number.

Response — 200 OK

{
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "user": {
    "_id": "64b8f3a2e7d1c...",
    "firstName": "Aarav",
    "lastName": "Sharma",
    "email": "aarav@university.edu",
    "rollNumber": "CSE-2024-001",
    "status": "ACTIVE",
    "roleId": "64b8f..."
  }
}

A refreshToken is set as an HttpOnly cookie.

Error Responses

StatusCondition
401Invalid credentials (email not found OR wrong password)
403Account is SUSPENDED, PENDING, or DISABLED
403Account is temporarily locked (too many failed attempts)
429Rate limited

Brute Force Protection

  • After 5 failed login attempts, the account is locked for 15 minutes
  • Failed attempts are reset on successful login
  • All attempts are logged to the audit trail

POST /auth/refresh

Rotates the refresh token and issues a new access token.

Request

No body required. The refreshToken is read from the HttpOnly cookie.

Response — 200 OK

{
  "accessToken": "eyJhbGciOiJIUzI1NiIs..."
}

A new refreshToken cookie is set (old one is deleted from the database).

Error Responses

StatusCondition
400No refresh token in cookies
401Invalid token format
401Token not found in database
401Token expired or revoked
401User inactive or deleted

POST /auth/logout

Revokes the current refresh token and clears the cookie.

Request

No body required.

Response — 200 OK

{
  "message": "Successfully logged out"
}

POST /auth/change-password

Changes the authenticated user's password. Requires authenticate middleware.

Request

POST /api/v1/auth/change-password
Authorization: Bearer <accessToken>
Content-Type: application/json
{
  "currentPassword": "OldP@ssw0rd123",
  "newPassword": "NewP@ssw0rd456"
}

Response — 200 OK

{
  "message": "Password updated successfully. All devices have been logged out."
}

Side Effects

  • All refresh tokens for the user are deleted (logs out all devices)
  • tokenVersion is incremented (invalidates all outstanding access tokens)

Error Responses

StatusCondition
401Not authenticated
401Current password is incorrect
404User not found

Security Notes

  • Passwords are hashed with Argon2id (not bcrypt)
  • Refresh tokens are stored as Argon2id hashes — raw tokens never touch the database
  • The passwordHash field is always excluded from API responses
  • Error messages never reveal whether an email exists in the system ("Invalid credentials" for both cases)

On this page