Authenticate an existing user with email and password. Public access without authentication. Returns JWT access token and refresh token.
- Invalid credentials always return the same generic error to prevent user enumeration.
- Access token expires after 15 minutes; refresh token expires after 14 days.
- Tokens are stored in localStorage on the frontend.
sequenceDiagram
actor User
User->>+FE: fills login form
FE->>FE: validate form
alt form is invalid
FE-->>User: show error messages <br> disable submit button
end
User->>+FE: submits login form
FE->>+BE: POST /api/v1/auth/login <br> LoginRequest
BE->>BE: validate request
alt request is invalid
BE-->>FE: 400 Bad Request <br> ErrorResponse
end
BE->>DB: find user by email
alt user not found
BE-->>FE: 401 Unauthorized <br> ErrorResponse
end
BE->>BE: verify password hash
alt password does not match
BE-->>FE: 401 Unauthorized <br> ErrorResponse
end
BE->>BE: generate access token
BE->>BE: generate refresh token
BE->>DB: store refresh token
BE->>-FE: 200 OK <br> AuthResponse
FE->>FE: store tokens in localStorage
FE->>-User: redirect to homepage
POST /api/v1/auth/login LoginRequest:
{
"email": "jane.doe@example.com",
"password": "secret123"
}
200 OK AuthResponse:
{
"data": {
"accessToken": "*****",
"refreshToken": "*****"
}
}
400 Bad Request (validation) ErrorResponse:
{
"status": 400,
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"errors": [
{ "field": "email", "message": "must be a valid email address" }
]
}
401 Unauthorized (invalid credentials) ErrorResponse:
{
"status": 401,
"code": "AUTHENTICATION_FAILED",
"message": "Invalid email or password"
}
Frontend
Validations
| Field | Constraints | Size | Pattern | Note |
|---|---|---|---|---|
| not_blank | ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ | |||
| password | not_blank |
Backend
Validations
| Field | Constraints | Size | Pattern | Note |
|---|---|---|---|---|
| not_blank, email | ||||
| password | not_blank |
Test Cases
| GIVEN | WHEN | THEN |
|---|---|---|
| valid email and password | login is called | 200 OK with access and refresh tokens returned |
| user with email not found | login is called | 401 AUTHENTICATION_FAILED error response is returned |
| password does not match | login is called | 401 AUTHENTICATION_FAILED error response is returned |
| invalid email format | login is called | 400 VALIDATION_ERROR error response is returned |
| password is blank | login is called | 400 VALIDATION_ERROR error response is returned |
| invalid request (empty body) | login is called | 400 VALIDATION_ERROR error response is returned |
Was this page helpful?
Thanks for the feedback.