Skip to main content

Overview

Integra uses JSON Web Tokens (JWT) with RSA public/private key encryption for secure, stateless authentication. This approach ensures that:
  • No server-side session storage is required
  • Tokens are cryptographically signed and cannot be forged
  • Authentication scales horizontally across multiple server instances
  • Tokens carry user identity and permissions for efficient authorization
Integra implements JWT authentication using the JJWT library (version 0.13.0) with RSA-256 signature algorithm.

Authentication Flow

Obtaining a Token

Login Endpoint

To authenticate and receive a JWT token, send a POST request to the login endpoint:
POST /comialex/api/integra/auth/login
Content-Type: application/json

{
  "username": "your_username",
  "password": "your_password"
}

Request Schema

Based on AccesoRequest.java:
FieldTypeRequiredConstraintsDescription
usernamestringYes3-50 charactersUser’s login username
passwordstringYes1-100 charactersUser’s password
curl -X POST http://localhost:8081/comialex/api/integra/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "jperez",
    "password": "SecurePass123!"
  }'

Response Schema

Based on JWTResponse.java:
{
  "token": "eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MTIzLCJzdXAiOnRydWUsImVtcGxlYWRvSWQiOjQ1Niwi...",
  "employeeName": {
    "id": 456,
    "nombre": "Juan",
    "apellidos": "Pérez García",
    "nip": "1234",
    "activo": true,
    "email": "[email protected]",
    "puesto": "Desarrollador Senior",
    "departamento": "Tecnología"
  },
  "uiPermissions": [
    "asistencia.ver",
    "asistencia.registrar",
    "empleados.ver",
    "reportes.generar"
  ]
}
FieldTypeDescription
tokenstringJWT access token for authentication
employeeNameobjectEmployee details associated with the authenticated user
uiPermissionsstring[]List of permission identifiers for UI access control
Store the token securely on the client side. The token contains encoded user information and is cryptographically signed to prevent tampering.

Using the Token

Authorization Header

Include the JWT token in the Authorization header of all authenticated requests using the Bearer scheme:
GET /comialex/api/integra/empleados
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MTIzLCJzdXAiOnRydWUsImVtcGxlYWRvSWQiOjQ1Niwi...

Implementation Examples

curl -X GET http://localhost:8081/comialex/api/integra/empleados \
  -H "Authorization: Bearer YOUR_TOKEN_HERE"

Token Structure

JWT Claims

Integra’s JWT tokens contain the following claims (from JwtUtil.java):
ClaimTypeDescription
substringUsername (subject)
idintegerUser account ID
empleadoIdintegerAssociated employee ID (if applicable)
supbooleanWhether user is a supervisor
authoritiesstring[]List of role IDs (e.g., ["ROLE_1", "ROLE_2"])
verintegerToken version for invalidation support
iattimestampIssued at time
exptimestampExpiration time
jtistringUnique token ID (UUID)
issstringIssuer (always "integra-auth-server")

Token Validation

The server validates tokens using the JwtRequestFilter (from JwtRequestFilter.java):
  1. Extract Token: Reads the Authorization header and extracts the Bearer token
  2. Verify Signature: Validates the RSA signature using the public key
  3. Check Expiration: Ensures the token hasn’t expired
  4. Validate Version: Confirms the token version matches the current user version
  5. Load Permissions: Expands role IDs to their associated permissions
  6. Set Context: Establishes Spring Security authentication context
// From JwtRequestFilter.java (lines 34-42)
final String authHeader = request.getHeader("Authorization");

if (authHeader == null || !authHeader.startsWith("Bearer ")) {
    filterChain.doFilter(request, response);
    return;
}

final String token = authHeader.substring(7);
Tokens are validated on every request. If a token is invalid, expired, or has a deprecated version, the request will be rejected with a 401 Unauthorized response.

Token Expiration

Default Configuration

From application.yml:
security:
  jwt:
    expiration: 2592000         # 30 days in seconds
    refresh-expiration: 2592000 # 30 days in seconds
  • Access Token Expiration: 30 days (2,592,000 seconds)
  • Refresh Token Expiration: 30 days (2,592,000 seconds)

Handling Expired Tokens

When a token expires, the API returns:
{
  "success": false,
  "message": "Fallo en validación de JWT: Token has expired",
  "timestamp": 1709644800000
}
HTTP Status: 401 Unauthorized
When you receive a 401 error due to token expiration, prompt the user to log in again. Integra currently uses long-lived tokens (30 days) to reduce re-authentication frequency.

Token Versioning & Invalidation

How It Works

Integra implements a token versioning system (from JwtUtil.java lines 81-94) that allows for dynamic token invalidation:
  1. Each user has a version number stored in the database
  2. When a token is generated, it includes the current version in the ver claim
  3. On validation, the token’s version is compared to the current user version
  4. If the token version is less than the current version, it’s rejected
// From JwtUtil.java
private boolean isVersionDeprecated(Claims claims) {
    Integer tokenVersion = claims.get(CLAIM_VER, Integer.class);
    if (tokenVersion == null) return true;
    
    int currentVersion = tokenVersionService.getVersion(claims.getSubject());
    return tokenVersion < currentVersion;
}

Use Cases for Version Invalidation

  • Password Changed: Invalidate all existing tokens when a user changes their password
  • Security Breach: Immediately revoke access by incrementing the user’s version
  • Permission Changes: Force token refresh after role/permission updates
  • Account Disabled: Prevent access even with a valid, non-expired token

Public Endpoints

The following endpoints do NOT require authentication (from SecurityConfig.java):

Authentication Endpoints

POST /auth/login
POST /auth/refresh
POST /auth/forgot-password
POST /auth/validate-reset-token
POST /auth/reset-password
POST /auth/register-request
POST /auth/validate-registration-token
POST /auth/register-confirm
GET  /auth/public/**

Other Public Endpoints

GET  /estados/**
GET  /unidades/**
GET  /asistencia/**
GET  /kioscos
GET  /kioscos/{id}
POST /kioscos/{id}/codigos/{codigo}/usar
PATCH /kioscos/{id}/requiere-codigo

Documentation & Monitoring

GET /swagger-ui/**
GET /v3/api-docs/**
GET /swagger-ui.html
GET /actuator/health
GET /actuator/prometheus
All other endpoints require a valid JWT token in the Authorization header.

Security Best Practices

Token Storage

Never store JWT tokens in:
  • URL parameters
  • Browser local storage (vulnerable to XSS attacks)
  • Unencrypted cookies
Recommended: Use secure, HTTP-only cookies or secure session storage.

HTTPS/TLS

Always use HTTPS in production. JWT tokens transmitted over HTTP can be intercepted and used by attackers.

Password Security

Integra uses BCrypt for password hashing (from SecurityConfig.java):
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}
  • Passwords are never stored in plain text
  • BCrypt automatically salts passwords
  • Computational cost makes brute-force attacks impractical

Token Transmission

// ✅ CORRECT: Use Authorization header
fetch('/api/empleados', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

// ❌ WRONG: Never put tokens in URL
fetch(`/api/empleados?token=${token}`);

Key Management

Protect your RSA private key!
  • Never commit private.pem to version control
  • Use environment variables or secret management services
  • Rotate keys periodically
  • Use different key pairs for development and production

Rate Limiting

Consider implementing rate limiting on authentication endpoints to prevent brute-force attacks:
POST /auth/login - Limit: 5 requests per minute per IP

Error Responses

Invalid Credentials

{
  "success": false,
  "message": "Invalid username or password",
  "timestamp": 1709644800000
}
HTTP Status: 401 Unauthorized

Missing Token

{
  "success": false,
  "message": "Authentication required",
  "timestamp": 1709644800000
}
HTTP Status: 401 Unauthorized

Invalid Token Signature

{
  "success": false,
  "message": "Fallo en validación de JWT: JWT signature does not match",
  "timestamp": 1709644800000
}
HTTP Status: 401 Unauthorized

Deprecated Token Version

{
  "success": false,
  "message": "La versión del token ya no es válida.",
  "timestamp": 1709644800000
}
HTTP Status: 401 Unauthorized

Password Recovery Flow

Integra provides a self-service password recovery system:
1

Request Password Reset

POST /auth/forgot-password
Content-Type: application/json

{
  "email": "[email protected]"
}
The system sends a reset token via email.
2

Validate Reset Token

POST /auth/validate-reset-token
Content-Type: application/json

{
  "token": "reset-token-from-email"
}
Verify the token is valid and not expired.
3

Reset Password

POST /auth/reset-password
Content-Type: application/json

{
  "token": "reset-token-from-email",
  "newPassword": "NewSecurePass123!"
}
Set the new password and invalidate all existing tokens.

Next Steps

API Reference

Explore all available API endpoints

Employee Management

Learn how to manage employee records

Attendance Tracking

Understand attendance registration workflows

Role-Based Access

Configure roles and permissions

Build docs developers (and LLMs) love