Autenticación

Authentication

mecaractizo soporta dos mecanismos de autenticación independientes: JWT (SimpleJWT) para la mayoría de los endpoints de la API REST, y Knox como alternativa con tokens opacos de larga duración.

Recomendado para integraciones externas: JWT. El par access/refresh es el mecanismo principal para los endpoints protegidos de formularios, certificados y acciones.

JWT — SimpleJWT

Usa djangorestframework-simplejwt. El access token se envía en el header Authorization: Bearer <token>.

Obtener tokens

PropiedadValor
MétodoPOST
Ruta/home/api/token/login
AutenticaciónNo requerida
CampoTipoDescripción
usernamestringNombre de usuario Django
passwordstringContraseña
POST /home/api/token/login
Content-Type: application/json

{
  "username": "pedro",
  "password": "mi_password"
}
import requests

resp = requests.post(
    "https://TU-DOMINIO/home/api/token/login",
    json={"username": "pedro", "password": "mi_password"}
)
data = resp.json()
access  = data["token"]["access"]
refresh = data["token"]["refresh"]
const { data } = await axios.post(
  'https://TU-DOMINIO/home/api/token/login',
  { username: 'pedro', password: 'mi_password' }
);
const { access, refresh } = data.token;
using var client = new HttpClient();
var body = new StringContent(
    JsonSerializer.Serialize(new { username = "pedro", password = "mi_password" }),
    Encoding.UTF8, "application/json"
);
var response = await client.PostAsync("https://TU-DOMINIO/home/api/token/login", body);
var json = await response.Content.ReadAsStringAsync();
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://TU-DOMINIO/home/api/token/login"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(
        "{\"username\":\"pedro\",\"password\":\"mi_password\"}"
    ))
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

Response 200:

{
  "token": {
    "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "msg": "Login success"
}

Response 404 — credenciales inválidas:

{
  "errors": {
    "non_fields_errors": ["User or Password is not Valid"]
  }
}

Renovar access token

PropiedadValor
MétodoPOST
Ruta/home/api/token/refresh
AutenticaciónNo requerida
POST /home/api/token/refresh
Content-Type: application/json

{
  "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
resp = requests.post(
    "https://TU-DOMINIO/home/api/token/refresh",
    json={"refresh": refresh_token}
)
access = resp.json()["access"]
const { data } = await axios.post(
  'https://TU-DOMINIO/home/api/token/refresh',
  { refresh: refreshToken }
);
const newAccessToken = data.access;
var body = new StringContent(
    JsonSerializer.Serialize(new { refresh = refreshToken }),
    Encoding.UTF8, "application/json"
);
var response = await client.PostAsync("https://TU-DOMINIO/home/api/token/refresh", body);
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://TU-DOMINIO/home/api/token/refresh"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(
        "{\"refresh\":\"" + refreshToken + "\"}"
    ))
    .build();

Response 200:

{ "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }

Usar el access token

GET /home/api/getInformacion
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
headers = {"Authorization": f"Bearer {access_token}"}
resp = requests.get("https://TU-DOMINIO/home/api/getInformacion", headers=headers)
const response = await axios.get(
  'https://TU-DOMINIO/home/api/getInformacion',
  { headers: { 'Authorization': `Bearer ${accessToken}` } }
);
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", accessToken);
var response = await client.GetAsync("https://TU-DOMINIO/home/api/getInformacion");
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://TU-DOMINIO/home/api/getInformacion"))
    .header("Authorization", "Bearer " + accessToken)
    .GET()
    .build();

Knox — Tokens opacos

Alternativa para clientes que prefieren tokens opacos de larga duración sin gestión de refresh. Usa la librería django-rest-knox.

Nota: Los endpoints de formularios, certificados y acciones usan IsAuthenticated de DRF, que acepta tanto JWT como Knox. Sin embargo, los endpoints de auth/logout/ y auth/logoutall/ son exclusivos de Knox.

Login Knox

PropiedadValor
MétodoPOST
Ruta/home/api/auth/login/
AutenticaciónNo requerida
POST /home/api/auth/login/
Content-Type: application/json

{
  "username": "pedro",
  "password": "mi_password"
}
resp = requests.post(
    "https://TU-DOMINIO/home/api/auth/login/",
    json={"username": "pedro", "password": "mi_password"}
)
token = resp.json()["token"]
const { data } = await axios.post(
  'https://TU-DOMINIO/home/api/auth/login/',
  { username: 'pedro', password: 'mi_password' }
);
const knoxToken = data.token;
var body = new StringContent(
    JsonSerializer.Serialize(new { username = "pedro", password = "mi_password" }),
    Encoding.UTF8, "application/json"
);
var response = await client.PostAsync("https://TU-DOMINIO/home/api/auth/login/", body);
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://TU-DOMINIO/home/api/auth/login/"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(
        "{\"username\":\"pedro\",\"password\":\"mi_password\"}"
    ))
    .build();

Response 200:

{ "token": "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b..." }

Response 401 — credenciales inválidas:

{ "error": "Credenciales inválidas" }

Logout Knox

PropiedadValor
MétodoPOST
Ruta/home/api/auth/logout/
AutenticaciónKnox token (header Authorization: Token <token>)
POST /home/api/auth/logout/
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
headers = {"Authorization": f"Token {knox_token}"}
requests.post("https://TU-DOMINIO/home/api/auth/logout/", headers=headers)
await axios.post(
  'https://TU-DOMINIO/home/api/auth/logout/',
  {},
  { headers: { 'Authorization': `Token ${knoxToken}` } }
);
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Token", knoxToken);
await client.PostAsync("https://TU-DOMINIO/home/api/auth/logout/",
    new StringContent(""));
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://TU-DOMINIO/home/api/auth/logout/"))
    .header("Authorization", "Token " + knoxToken)
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();

Logout de todas las sesiones Knox

PropiedadValor
MétodoPOST
Ruta/home/api/auth/logoutall/
AutenticaciónKnox token
POST /home/api/auth/logoutall/
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
headers = {"Authorization": f"Token {knox_token}"}
requests.post("https://TU-DOMINIO/home/api/auth/logoutall/", headers=headers)
await axios.post(
  'https://TU-DOMINIO/home/api/auth/logoutall/',
  {},
  { headers: { 'Authorization': `Token ${knoxToken}` } }
);
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Token", knoxToken);
await client.PostAsync("https://TU-DOMINIO/home/api/auth/logoutall/",
    new StringContent(""));
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://TU-DOMINIO/home/api/auth/logoutall/"))
    .header("Authorization", "Token " + knoxToken)
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();

Comparativa de mecanismos

CaracterísticaJWT (SimpleJWT)Knox
Tipo de tokenFirmado (stateless)Opaco (almacenado en BD)
RenovaciónVia refresh tokenNo expira (configurable)
RevocaciónNo (hasta expiración)Sí (logout invalida)
HeaderAuthorization: Bearer <token>Authorization: Token <token>
Uso recomendadoIntegraciones APIAplicaciones de larga sesión