Skip to main content

Overview

InvestGo uses JWT (JSON Web Token) based authentication to secure API endpoints. The platform implements a stateless authentication mechanism where users receive a token after successful login, which must be included in subsequent requests.

Authentication Flow

1

User Login

Send credentials to the /generate-token endpoint to receive a JWT token.
2

Token Storage

Store the received token securely on the client side (e.g., localStorage, sessionStorage, or memory).
3

Include Token in Requests

Add the token to the Authorization header for all protected API requests.
4

Token Validation

The server validates the token on each request using the JWT filter chain.

Generating a Token

Endpoint

POST /generate-token

Request Body

{
  "username": "jamie",
  "password": "Admin12345"
}

Example: Login Request

const login = async (username, password) => {
  const response = await fetch('http://localhost:8091/generate-token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ username, password })
  });
  
  if (!response.ok) {
    throw new Error('Authentication failed');
  }
  
  const data = await response.json();
  // Store token securely
  localStorage.setItem('token', data.token);
  return data.token;
};

Using the Token

Once you have a token, include it in the Authorization header with the Bearer prefix for all protected endpoints.

Header Format

Authorization: Bearer <your-token-here>

Example: Making Authenticated Requests

const getProtectedData = async () => {
  const token = localStorage.getItem('token');
  
  const response = await fetch('http://localhost:8091/facturas', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });
  
  return response.json();
};

Getting Current User

Retrieve information about the currently authenticated user.

Endpoint

GET /actual-usuario

Request

const getCurrentUser = async () => {
  const token = localStorage.getItem('token');
  
  const response = await fetch('http://localhost:8091/actual-usuario', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });
  
  return response.json();
};

Response Example

{
  "id": 1,
  "username": "jamie",
  "nombre": "Jeimy",
  "apellidoPa": "Apolaya",
  "apellidoMa": "Jurado",
  "correo": "[email protected]",
  "telefono": "938311721",
  "idTipoUsu": 2,
  "enable": "Activo"
}

Token Structure and Configuration

JWT Configuration

The JWT implementation uses the following configuration (from JwtUtils.java:18,48):
  • Secret Key: examportal
  • Signature Algorithm: HS512 (HMAC-SHA512)
  • Token Expiration: 10 hours (36,000,000 milliseconds)
  • Claims: Subject (username) + issued/expiration timestamps

Token Claims

Each JWT token contains:
ClaimDescription
subSubject - the username of the authenticated user
iatIssued At - timestamp when the token was created
expExpiration - timestamp when the token expires (10 hours from issue)
Tokens are valid for 10 hours from the time of generation. After expiration, users must re-authenticate to receive a new token.

Token Validation Process

When a request is received with a token, the following validation occurs (JwtAuthenticationFilter.java:30-64):
1

Extract Token

The filter extracts the token from the Authorization header, expecting format Bearer <token>.
2

Parse Username

The username is extracted from the token’s subject claim.
3

Load User Details

User details are loaded from the database using the extracted username.
4

Validate Token

Token is validated by checking:
  • Username matches user details
  • Token has not expired
5

Set Authentication

If valid, a UsernamePasswordAuthenticationToken is created and set in the SecurityContext.

Error Handling

Common Authentication Errors

Cause: Incorrect username or password.Error Message: "Credenciales ivalidas"Solution: Verify the username and password are correct.
Cause: User account has been disabled.Error Message: "Usuario deshabilitado"Solution: Contact an administrator to enable the account.
Cause: Username does not exist in the system.Error Message: "Usuario no encontrado"Solution: Register a new account or verify the username.
Cause: JWT token has passed its 10-hour expiration time.Console Log: "El token ha expirado"Solution: Re-authenticate to obtain a new token.
Cause: Token doesn’t start with “Bearer ” prefix or is malformed.Console Log: "Token invalido, no empieza con bearer String"Solution: Ensure the Authorization header uses format: Bearer <token>

Best Practices

Security Recommendations:
  • Store tokens securely (avoid localStorage in production; use httpOnly cookies or secure storage)
  • Never expose tokens in URLs or logs
  • Implement token refresh mechanism for better UX
  • Use HTTPS in production to prevent token interception
  • Clear tokens on logout

Token Refresh Strategy

Since tokens expire after 10 hours, implement one of these strategies:
  1. Re-authenticate before expiration: Check token expiration time and prompt user to re-login
  2. Silent refresh: Implement a refresh token mechanism (requires backend enhancement)
  3. Automatic re-login: Store credentials securely and auto-renew token (use with caution)

Handling Expired Tokens

const makeAuthenticatedRequest = async (url, options = {}) => {
  const token = localStorage.getItem('token');
  
  const response = await fetch(url, {
    ...options,
    headers: {
      ...options.headers,
      'Authorization': `Bearer ${token}`
    }
  });
  
  if (response.status === 401) {
    // Token expired or invalid - redirect to login
    localStorage.removeItem('token');
    window.location.href = '/login';
    return;
  }
  
  return response.json();
};
  • JWT Utilities: src/main/java/com/proyecto/integrador/configuraciones/JwtUtils.java
  • Authentication Filter: src/main/java/com/proyecto/integrador/configuraciones/JwtAuthenticationFilter.java
  • Authentication Controller: src/main/java/com/proyecto/integrador/controladores/AuthenticationController.java
  • Request/Response DTOs: src/main/java/com/proyecto/integrador/dto/JwtRequest.java and JwtResponse.java

Next Steps

Build docs developers (and LLMs) love