Overview
The login endpoint authenticates users and returns a JWT token that must be included in subsequent requests to protected endpoints. The authentication process validates credentials against BCrypt-hashed passwords stored in the database.
Login Endpoint
cURL
JavaScript/Axios
Python/Requests
Java
curl -X POST "https://api.example.com/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"username": "johndoe",
"password": "SecurePass123!"
}'
Endpoint Details
URL : /api/v1/auth/login
Method : POST
Content-Type : application/json
Authentication : Not required (public endpoint)
Request Body Schema
The request body must conform to the AuthLoginRequest DTO:
Request Body
AuthLoginRequest.java
{
"username" : "string" ,
"password" : "string"
}
Field Requirements
Field Type Required Validation Description usernameString Yes Not blank The username associated with the account passwordString Yes Not blank The password for authentication
Both fields are mandatory. The API will return a validation error if either field is missing or empty.
Success Response (201 Created)
Response Body
AuthLoginResponse.java
{
"username" : "johndoe" ,
"message" : "User logged in correctly" ,
"jwt" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJsaWJyYXJ5LWFwaSIsInN1YiI6ImpvaG5kb2UiLCJhdXRob3JpdGllcyI6IiIsImlhdCI6MTcwOTY0MDAwMCwiZXhwIjoxNzA5NjQxODAwLCJqdGkiOiIxMjM0NTY3OC0xMjM0LTEyMzQtMTIzNC0xMjM0NTY3ODkwYWIiLCJuYmYiOjE3MDk2NDAwMDB9.signature" ,
"status" : true
}
Response Fields
Field Type Description usernameString The authenticated username messageString Success message (“User logged in correctly”) jwtString JWT access token for authenticated requests statusBoolean Always true for successful login
The JWT token is the most critical part of the response. Store it securely and include it in all subsequent API requests to protected endpoints.
Authentication Process
The login process follows these steps:
Validate Request
The API validates that both username and password are provided and not blank
Load User Details
The system retrieves the user from the database using the provided username AuthUser user = authUserRepository . findAuthUserByUsername (username)
. orElseThrow (() -> new UsernameNotFoundException (
"The user " + username + " doesn't exist" ));
Verify Password
BCrypt is used to compare the provided password with the stored hash if ( ! passwordEncoder . matches (password, userDetails . getPassword ())) {
throw new BadCredentialsException ( "Invalid password" );
}
Create Authentication Object
A Spring Security Authentication object is created with user details Authentication authentication = new UsernamePasswordAuthenticationToken (
userDetails . getUsername (),
userDetails . getPassword (),
userDetails . getAuthorities ()
);
Generate JWT Token
A JWT token is created using the JwtUtils utility String accessToken = jwtUtils . createToken (authentication);
Return Response
The API returns the username, success message, JWT token, and status return new AuthLoginResponse (
username,
"User logged in correctly" ,
accessToken,
true
);
JWT Token Details
The JWT token returned upon successful login contains the following information:
Token Structure
Token Claims
Claim Description Example issIssuer of the token Configured in security.jwt.user.generator subSubject (username) "johndoe"authoritiesUser authorities/roles "" (empty in current implementation)iatIssued at timestamp 1709640000expExpiration timestamp 1709641800 (30 minutes after iat)jtiUnique token ID "12345678-1234-1234-1234-1234567890ab"nbfNot before timestamp 1709640000
JWT tokens expire 30 minutes (1,800,000 milliseconds) after issuance. You must re-authenticate to obtain a new token after expiration.
Using the JWT Token
After successful login, include the JWT token in the Authorization header of all requests to protected endpoints:
cURL
JavaScript/Axios
Python/Requests
Java
curl -X GET "https://api.example.com/api/v1/books" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Always include the Bearer prefix before the token in the Authorization header. The format must be: Authorization: Bearer <token>
Error Responses
Invalid Credentials (401 Unauthorized)
Returned when username doesn’t exist or password is incorrect:
{
"message" : "Invalid password" ,
"timestamp" : "2024-03-06T10:30:00" ,
"details" : []
}
or
{
"message" : "The user johndoe doesn't exist" ,
"timestamp" : "2024-03-06T10:30:00" ,
"details" : []
}
Validation Error (400 Bad Request)
Returned when required fields are missing:
{
"message" : "Validation failed" ,
"timestamp" : "2024-03-06T10:30:00" ,
"details" : [
"The username is obligatory" ,
"The password is obligatory"
]
}
Complete Login Flow Example
Full Authentication Workflow
Collect Credentials
Gather username and password from user input const username = document . getElementById ( 'username' ). value ;
const password = document . getElementById ( 'password' ). value ;
Send Login Request
POST credentials to the login endpoint const response = await fetch ( 'https://api.example.com/api/v1/auth/login' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ username , password })
});
Handle Response
Check response status and extract JWT token if ( response . status === 201 ) {
const data = await response . json ();
const token = data . jwt ;
// Store token securely
localStorage . setItem ( 'authToken' , token );
localStorage . setItem ( 'username' , data . username );
// Redirect to main application
window . location . href = '/dashboard' ;
} else {
const error = await response . json ();
showError ( error . message );
}
Use Token in Requests
Include token in subsequent API calls const token = localStorage . getItem ( 'authToken' );
const apiResponse = await fetch ( 'https://api.example.com/api/v1/books' , {
headers: {
'Authorization' : `Bearer ${ token } `
}
});
Handle Token Expiration
Detect expired tokens and re-authenticate if ( apiResponse . status === 401 ) {
// Token expired
localStorage . removeItem ( 'authToken' );
localStorage . removeItem ( 'username' );
window . location . href = '/login' ;
}
Token Storage Best Practices
Client-Side Storage Options
Storage Method Security Persistence Use Case Memory High Session only High-security applications SessionStorage Medium Session only Single-tab applications LocalStorage Low-Medium Persistent General web applications Cookies (HttpOnly) High Persistent Server-rendered applications
Recommendations
Choose Appropriate Storage
Use memory or sessionStorage for sensitive applications
LocalStorage is acceptable for general-purpose apps
Consider HttpOnly cookies for server-side rendering
Implement Token Refresh
Monitor token expiration time
Prompt user to re-authenticate before expiration
Clear stored token immediately upon logout
Secure Communication
Always use HTTPS in production
Never log or expose tokens in console
Don’t include tokens in URLs or query parameters
Never expose JWT tokens in client-side logs, error messages, or browser console. Treat tokens as sensitive credentials.
Token Expiration Handling
Client-Side Expiration Detection
Decode and Check Expiration
Automatic Refresh Before Expiration
function isTokenExpired ( token ) {
try {
// Decode JWT (without verification - just reading claims)
const payload = JSON . parse ( atob ( token . split ( '.' )[ 1 ]));
const expirationTime = payload . exp * 1000 ; // Convert to milliseconds
const currentTime = Date . now ();
return currentTime > expirationTime ;
} catch ( error ) {
return true ; // Treat invalid tokens as expired
}
}
// Usage
const token = localStorage . getItem ( 'authToken' );
if ( isTokenExpired ( token )) {
// Redirect to login
window . location . href = '/login' ;
}
Handling 401 Responses
// Global axios interceptor for handling expired tokens
axios . interceptors . response . use (
response => response ,
error => {
if ( error . response && error . response . status === 401 ) {
// Clear stored token
localStorage . removeItem ( 'authToken' );
localStorage . removeItem ( 'username' );
// Redirect to login
window . location . href = '/login?sessionExpired=true' ;
}
return Promise . reject ( error );
}
);
Password Security
BCrypt Verification
The API uses BCrypt to securely verify passwords:
// During login
if ( ! passwordEncoder . matches (password, userDetails . getPassword ())) {
throw new BadCredentialsException ( "Invalid password" );
}
Security Features
Constant-Time Comparison : Prevents timing attacks
Salt Integration : Each password has unique salt
Adaptive Cost : Configurable computational complexity
One-Way Hash : Cannot reverse hash to get original password
BCrypt automatically handles salting and verification. The passwordEncoder.matches() method extracts the salt from the stored hash and performs the comparison.
Testing Login
Valid Login Test
curl -X POST "http://localhost:8080/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"username": "johndoe",
"password": "SecurePass123!"
}'
Expected Response
{
"username" : "johndoe" ,
"message" : "User logged in correctly" ,
"jwt" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"status" : true
}
Testing Protected Endpoint
# Extract token from login response
TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
# Use token to access protected endpoint
curl -X GET "http://localhost:8080/api/v1/books" \
-H "Authorization: Bearer $TOKEN "
Common Issues and Solutions
Issue Possible Cause Solution 401 Unauthorized Invalid username or password Verify credentials are correct 401 Unauthorized Token expired Re-authenticate to get new token 400 Bad Request Missing required fields Include both username and password 403 Forbidden Account disabled Contact administrator Missing Bearer prefix Token format incorrect Ensure header is Bearer <token>
Security Considerations
For API Consumers
Store tokens securely and never expose them
Implement proper logout to clear tokens
Use HTTPS for all API communication
Handle token expiration gracefully
Never hardcode credentials in source code
For API Developers
Keep the JWT signing key (security.jwt.key.private) secure
Use environment variables for sensitive configuration
Implement rate limiting on login endpoint
Log failed authentication attempts
Consider implementing account lockout after failed attempts
JWT Tokens Deep dive into JWT token structure and validation
Registration Create a new account before logging in
Authentication Overview Understand the complete authentication system
API Reference Detailed API endpoint specifications