--- title: "Implementa JWT en tu aplicación" slug: "implement-jwt-in-your-application" updated: 2026-10-12T08:20:46Z published: 2026-10-12T08:20:46Z canonical: "docs.document360.com/implement-jwt-in-your-application" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.document360.com/llms.txt > Use this file to discover all available pages before exploring further. # Implementa JWT en tu aplicación Tras completar la configuración de JWT en Document360, tu aplicación necesita una ruta backend para gestionar el paso final del flujo de inicio de sesión. Esta ruta: - Valida que el usuario ya está autenticado en tu aplicación - Envía una solicitud segura a la URL de generación de código de Document360 - Recupera un código de autorización de un solo uso - Redirige al usuario al sitio de la base de conocimientos con ese código NOTA Los lectores no requieren una cuenta separada de Document360. La autenticación se gestiona íntegramente a través de tu aplicación. Una cuenta en tu aplicación es suficiente para que un lector acceda a la base de conocimientos. --- ## Ejemplos de código Los ejemplos siguientes muestran cómo implementar la ruta de autenticación backend en C#, Node.js y Java. ### C # ``` /// /// Example endpoint to authenticate a user and retrieve a token from the identity server, /// and redirect the user to the Knowledge Base (KB) using the token code. /// /// Client ID issued for your application /// Client secret associated with the client ID /// Redirects to the KB with the issued code [HttpGet] [Route("authenticate")] public async Task AuthenticateAsync(string clientId, string clientSecret) { if (!HttpContext.User.Identity.IsAuthenticated) { // user is not authenticated, redirect to an error or login page return Unauthorized(new { message = "User not authenticated" }); } // Ensure you have the correct client ID and secret from your Document360 JWT configuration var authToken = Encoding.ASCII.GetBytes($"{clientId}:{clientSecret}"); // Create an HttpClient instance using var httpClient = new HttpClient(); // Set the Authorization header with Basic authentication httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken)); // Prepare the payload with user information var payload = new { username = User.Identity.Name, firstName = "FirstName", // Replace or customize as needed lastName = "LastName", emailId = "user@example.com", // Replace with actual user email readerGroupIds = new List { "group1", "group2" }, // Replace with actual reader group IDs if needed (Optional) tokenValidity = 3600, // Token validity in seconds (Optional, default is 5 minutes) providerName = "app.example.com" // Domain of the matching JWT configuration (Required when multiple JWT configurations are active) }; var payloadContent = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json"); // Identity server token endpoint - replace with your actual URL string identityServerUrl = "codeGeneration endpoint, you can find that in JWT config portal"; // KB login URL to redirect after successful token issuance string kbLoginUrl = "https://{your subdomain}.document360.io"; var response = await httpClient.PostAsync(identityServerUrl, payloadContent); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var tokenJson = JObject.Parse(content); // Extract the code from the response var tokenCode = (string)tokenJson.SelectToken("code"); // Construct the KB login URL with code query parameter string finalRedirectUrl = $"{kbLoginUrl}?code={tokenCode}"; return Redirect(finalRedirectUrl); } else { // Handle error response from the identity server var error = await response.Content.ReadAsStringAsync(); return StatusCode((int)response.StatusCode, new { error = "Token request failed", details = error }); } } ``` ### Node.js ``` const express = require('express'); const https = require('https'); const axios = require('axios'); const app = express(); app.use(express.json()); const clientId = 'your-client-id'; const clientSecret = 'your-client-secret'; const codeGenerationUrl = 'https://identity.document360.net/jwt/generateCode'; const kbLoginUrl = 'https://your-subdomain.document360.net/jwt/authorize'; app.get('/authenticate', async (req, res) => { try { const isAuthenticated = true; // Replace with your actual auth logic if (!isAuthenticated) { return res.status(401).json({ message: 'User not authenticated' }); } const authHeader = Buffer.from(`${clientId}:${clientSecret}`).toString('base64'); const payload = { username: 'john.doe', firstName: 'John', lastName: 'Doe', emailId: 'john.doe@example.com', readerGroupIds: ['group1', 'group2'], tokenValidity: 3600, providerName: 'app.example.com' // Domain of the matching JWT configuration }; const response = await axios.post( codeGenerationUrl, payload, { headers: { 'Authorization': `Basic ${authHeader}`, 'Content-Type': 'application/json', 'Accept': 'application/json' }, httpsAgent: new https.Agent({ maxVersion: 'TLSv1.2' }) } ); const tokenCode = response.data?.code; if (!tokenCode) { return res.status(500).json({ message: 'No code received from Document360' }); } console.log("Redirecting to:", `${kbLoginUrl}?code=${tokenCode}`); return res.redirect(`${kbLoginUrl}?code=${tokenCode}`); } catch (error) { return res.status(500).json({ message: 'JWT SSO failed', details: error.response?.data || error.message }); } }); ``` ### Java ``` import org.springframework.http.*; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; import java.nio.charset.StandardCharsets; import java.util.*; @RestController public class JwtSsoController { private final String clientId = "your-client-id"; private final String clientSecret = "your-client-secret"; private final String codeGenerationUrl = "https://identity.document360.io/api/jwt/generate-code"; private final String kbLoginUrl = "https://your-subdomain.document360.io/jwt/authorize"; @GetMapping("/authenticate") public ResponseEntity authenticate() { // Example: Check if user is authenticated in your system boolean isAuthenticated = true; // Replace with actual logic if (!isAuthenticated) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("User not authenticated"); } // Create Basic Auth header String auth = clientId + ":" + clientSecret; String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8)); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.set("Authorization", "Basic " + encodedAuth); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); // Construct payload Map payload = new HashMap<>(); payload.put("username", "john.doe"); payload.put("firstName", "John"); payload.put("lastName", "Doe"); payload.put("emailId", "john.doe@example.com"); payload.put("readerGroupIds", Arrays.asList("group1", "group2")); payload.put("tokenValidity", 3600); payload.put("providerName", "app.example.com"); // Domain of the matching JWT configuration HttpEntity> request = new HttpEntity<>(payload, headers); RestTemplate restTemplate = new RestTemplate(); try { ResponseEntity response = restTemplate.postForEntity(codeGenerationUrl, request, Map.class); if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) { String tokenCode = (String) response.getBody().get("code"); if (tokenCode == null || tokenCode.isEmpty()) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("No code returned from Document360"); } // Redirect to the KB site with code String redirectUrl = UriComponentsBuilder.fromHttpUrl(kbLoginUrl) .queryParam("code", tokenCode) .toUriString(); HttpHeaders redirectHeaders = new HttpHeaders(); redirectHeaders.setLocation(java.net.URI.create(redirectUrl)); return new ResponseEntity<>(redirectHeaders, HttpStatus.FOUND); } else { return ResponseEntity.status(HttpStatus.BAD_GATEWAY) .body("Failed to get code from Document360: " + response.getStatusCode()); } } catch (Exception ex) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("JWT SSO error: " + ex.getMessage()); } } } ``` --- ## Re-autenticación de lectores con múltiples configuraciones JWT Cuando termina la sesión de un lector, Document360 les envía para iniciar sesión de nuevo. La redirección depende de cuántas configuraciones de JWT estén activas en tu proyecto: - **Una configuración JWT**: Document360 redirige al lector directamente a la URL de inicio de sesión configurada. - **Múltiples configuraciones JWT**: Document360 no puede saber a través de qué configuración inició sesión el lector, por lo que el lector aterriza en una página de inicio de sesión y debe introducir su dominio. Para enviar a los lectores directamente a la URL correcta de inicio de sesión, añade `providerName` a la carga útil que tu backend envía a la URL de generación de código. Establece su valor en **el dominio** de la configuración JWT correspondiente, disponible en **Configuración** > **Usuarios y Permisos** > **JWT**. ``` { "username": "john.doe", "firstName": "John", "lastName": "Doe", "emailId": "john.doe@example.com", "readerGroupIds": ["group1", "group2"], "tokenValidity": 3600, "providerName": "app.example.com" } ``` **Cómo funciona** 1. Tu solicitud se envía `providerName` cuando el lector inicia sesión. 2. Document360 registra la configuración JWT a través de la cual el lector inició sesión. 3. Cuando la sesión expira, Document360 redirige al lector directamente a la URL de inicio de sesión de esa configuración, sin mostrar la página de entrada del dominio. NOTA Si tu proyecto solo tiene una configuración JWT, `providerName` es opcional. Document360 ya redirige a los lectores a la URL de inicio de sesión configurada al expirar la sesión. --- ## Lista de comprobación para desarrolladores Antes de lanzarse, verifica lo siguiente: - Registra la URL de Inicio de Sesión, la URL de Llamada y la URL de generación de código en la configuración de tu JWT. - Guarda el Secreto del Cliente de forma segura. Solo se muestra una vez en el momento de la creación. - Implementa lógica backend para llamar a la URL de generación de código usando HTTP Basic Auth. - Firma el JWT en tu backend usando tu secreto de cliente. Nunca expongas la lógica de firmas en el lado del cliente. - Si tu proyecto tiene varias configuraciones JWT, inclúyelo `providerName` en la carga útil con el dominio de la configuración correspondiente. - Aplica HTTPS en todos los endpoints implicados en el flujo de autenticación. - Prueba el comportamiento de la sesión, la expiración del token y la renovación automática de la sesión antes de lanzarse. - Monitoriza los registros del backend en busca de errores 401, que normalmente indican códigos de autorización caducados o discrepancias de tokens. --- ## Redirigir a una página específica después de iniciar sesión Por defecto, tras iniciar sesión, los lectores son redirigidos a la **página principal** de tu base de conocimiento. - Si tu página principal no está publicada, los lectores son redirigidos a la `/docs` página. - Para redirigir a los lectores a una página diferente de tu base de conocimiento, configura la redirección usando el siguiente patrón de URL. **Patrón de URL** ``` https:///jwt/authorize?code=&redirectUrl= ``` **Parámetros** - `<Knowledge base URL>`: la URL principal de tu sitio de base de conocimiento. - `<code>`: el código generado por el endpoint de generación de código Document360. - `<redirect path>`: la URL a la que quieres que los lectores lleguen tras iniciar sesión. **Ejemplo** ``` https://example.document360.io/jwt/authorize?code=FOTaS_SW6dLGytQXvrG_rRFGhyPvrDDrgxJAZzYvJcY&redirectUrl=/docs/5-basic-things-to-get-started ``` NOTA Document360 enviará la URL de Redirección al `redirectPath` punto final de inicio de sesión. Cuando el punto final de inicio de sesión redirige de nuevo a la base de conocimiento con el código de autenticación, debería devolver la URL de Redirección como `redirectUrl` parámetro. En **KB Site 2.0**, la redirección se gestiona usando cookies en lugar del `redirectUrl` parámetro. Si tu implementación en JWT se basa en la redirección de cadenas de consulta usando el `redirectUrl` parámetro, el enfoque basado en cookies no soporta este parámetro. Puede que necesites actualizar tu implementación o [contactar con soporte](mailto:support@document360.com) para más aclaraciones.