Skip to main content
Authenticate with your credentials to receive a JWT token that grants access to protected API endpoints.

Login Endpoint

POST /api/auth/login

Required Fields

FieldTypeValidationDescription
emailstringValid email formatRegistered user email
passwordstringMinimum 8 charactersUser password

Example Request

curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "securePassword123"
  }'

Success Response

When authentication succeeds, you receive a JWT token:
{
  "message": "Inicio de sesión exitoso",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IlBBVElFTlQiLCJpYXQiOjE3MDk1NjQ4MDAsImV4cCI6MTcwOTU2ODQwMH0.example_signature"
}
Status Code: 200 OK
The token in the response is a complete JWT that you must include in the Authorization header for subsequent API requests.

Login Process Flow

The authentication flow (src/services/authService.js:34-47) works as follows:
1

Find User

The system looks up the user by email in the database.
2

Verify Password

Uses bcrypt to compare the provided password with the stored hash.
3

Generate Token

Creates a JWT token containing user ID and role, valid for 1 hour.
4

Log Audit

Records the login event in the audit log.
5

Return Token

Sends the token to the client for use in future requests.

Using the Token

Once you have the token, include it in the Authorization header using the Bearer scheme:
curl http://localhost:3000/api/users/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
The token format is Bearer <token>. Make sure to include the word “Bearer” followed by a space before the actual token.

Token Payload

The JWT token contains the following claims:
// From src/services/authService.js:40-44
const token = jwt.sign(
    { id: user.id, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: '1h' }
);
ClaimDescription
idUser’s unique identifier
roleUser’s role (PATIENT, DOCTOR, or ADMIN)
iatIssued at timestamp
expExpiration timestamp (1 hour from issue)

Error Responses

Invalid Credentials

When email or password is incorrect: Status Code: 401 Unauthorized
{
  "error": "Usuario y/o contraseña incorrecta"
}
The error message is intentionally generic to prevent user enumeration attacks. You cannot determine whether the email or password was incorrect.

Missing Fields

When required fields are not provided: Status Code: 401 Unauthorized
{
  "error": "Usuario y/o contraseña incorrecta"
}

Invalid Email Format

Status Code: 400 Bad Request
{
  "error": "\"email\" must be a valid email"
}

Complete Example: Login and Access Protected Resource

Here’s a complete workflow showing login and accessing a protected endpoint:
# Step 1: Login
TOKEN=$(curl -s -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "securePassword123"
  }' | jq -r '.token')

echo "Token: $TOKEN"

# Step 2: Access protected route
curl http://localhost:3000/api/auth/protected-route \
  -H "Authorization: Bearer $TOKEN"

Security Implementation

Password Comparison

The system uses bcrypt’s secure comparison to prevent timing attacks:
// From src/services/authService.js:35-36
const user = await prisma.user.findUnique({ where: { email } });
const isPasswordValid = user ? await bcrypt.compare(password, user.password) : false;

Constant-Time Response

The system performs password comparison even if the user doesn’t exist, preventing attackers from determining valid email addresses through timing analysis.

Audit Logging

Every successful login is recorded in the audit log with the user ID and action type (login).

Token Expiration

Tokens expire after 1 hour. When a token expires, you will receive a 403 Forbidden error and must login again.
The API does not currently support token refresh. You must re-authenticate to obtain a new token.

Next Steps

JWT Token Details

Learn about token structure, validation, and error handling

Protected Endpoints

Explore API endpoints that require authentication

Build docs developers (and LLMs) love