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.
JWT — SimpleJWT
Usa djangorestframework-simplejwt. El access token se envía en el header Authorization: Bearer <token>.
Obtener tokens
| Propiedad | Valor |
|---|---|
| Método | POST |
| Ruta | /home/api/token/login |
| Autenticación | No requerida |
| Campo | Tipo | Descripción |
|---|---|---|
username | string | Nombre de usuario Django |
password | string | Contraseñ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
| Propiedad | Valor |
|---|---|
| Método | POST |
| Ruta | /home/api/token/refresh |
| Autenticación | No 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.
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
| Propiedad | Valor |
|---|---|
| Método | POST |
| Ruta | /home/api/auth/login/ |
| Autenticación | No 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
| Propiedad | Valor |
|---|---|
| Método | POST |
| Ruta | /home/api/auth/logout/ |
| Autenticación | Knox 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
| Propiedad | Valor |
|---|---|
| Método | POST |
| Ruta | /home/api/auth/logoutall/ |
| Autenticación | Knox 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ística | JWT (SimpleJWT) | Knox |
|---|---|---|
| Tipo de token | Firmado (stateless) | Opaco (almacenado en BD) |
| Renovación | Via refresh token | No expira (configurable) |
| Revocación | No (hasta expiración) | Sí (logout invalida) |
| Header | Authorization: Bearer <token> | Authorization: Token <token> |
| Uso recomendado | Integraciones API | Aplicaciones de larga sesión |
mecaractizo supports two independent authentication mechanisms: JWT (SimpleJWT) for most REST API endpoints, and Knox as an alternative with long-lived opaque tokens.
JWT — SimpleJWT
Uses djangorestframework-simplejwt. The access token is sent in the Authorization: Bearer <token> header.
Obtain tokens
| Property | Value |
|---|---|
| Method | POST |
| Path | /home/api/token/login |
| Authentication | Not required |
| Field | Type | Description |
|---|---|---|
username | string | Django username |
password | string | Password |
POST /home/api/token/login
Content-Type: application/json
{
"username": "pedro",
"password": "my_password"
}
import requests
resp = requests.post(
"https://YOUR-DOMAIN/home/api/token/login",
json={"username": "pedro", "password": "my_password"}
)
data = resp.json()
access = data["token"]["access"]
refresh = data["token"]["refresh"]
const { data } = await axios.post(
'https://YOUR-DOMAIN/home/api/token/login',
{ username: 'pedro', password: 'my_password' }
);
const { access, refresh } = data.token;
using var client = new HttpClient();
var body = new StringContent(
JsonSerializer.Serialize(new { username = "pedro", password = "my_password" }),
Encoding.UTF8, "application/json"
);
var response = await client.PostAsync("https://YOUR-DOMAIN/home/api/token/login", body);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://YOUR-DOMAIN/home/api/token/login"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"username\":\"pedro\",\"password\":\"my_password\"}"
))
.build();
Response 200:
{
"token": {
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
"msg": "Login success"
}
Response 404 — invalid credentials:
{
"errors": {
"non_fields_errors": ["User or Password is not Valid"]
}
}
Refresh access token
| Property | Value |
|---|---|
| Method | POST |
| Path | /home/api/token/refresh |
| Authentication | Not required |
POST /home/api/token/refresh
Content-Type: application/json
{ "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }
resp = requests.post(
"https://YOUR-DOMAIN/home/api/token/refresh",
json={"refresh": refresh_token}
)
access = resp.json()["access"]
const { data } = await axios.post(
'https://YOUR-DOMAIN/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://YOUR-DOMAIN/home/api/token/refresh", body);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://YOUR-DOMAIN/home/api/token/refresh"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"refresh\":\"" + refreshToken + "\"}"
))
.build();
Response 200:
{ "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }
Using the access token
GET /home/api/getInformacion
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
headers = {"Authorization": f"Bearer {access_token}"}
resp = requests.get("https://YOUR-DOMAIN/home/api/getInformacion", headers=headers)
const response = await axios.get(
'https://YOUR-DOMAIN/home/api/getInformacion',
{ headers: { 'Authorization': `Bearer ${accessToken}` } }
);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
var response = await client.GetAsync("https://YOUR-DOMAIN/home/api/getInformacion");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://YOUR-DOMAIN/home/api/getInformacion"))
.header("Authorization", "Bearer " + accessToken)
.GET()
.build();
Knox — Opaque tokens
Alternative for clients that prefer long-lived opaque tokens without refresh management. Uses the django-rest-knox library.
IsAuthenticated, which accepts both JWT and Knox. However, auth/logout/ and auth/logoutall/ are Knox-exclusive.
Knox login
| Property | Value |
|---|---|
| Method | POST |
| Path | /home/api/auth/login/ |
| Authentication | Not required |
POST /home/api/auth/login/
Content-Type: application/json
{
"username": "pedro",
"password": "my_password"
}
resp = requests.post(
"https://YOUR-DOMAIN/home/api/auth/login/",
json={"username": "pedro", "password": "my_password"}
)
token = resp.json()["token"]
const { data } = await axios.post(
'https://YOUR-DOMAIN/home/api/auth/login/',
{ username: 'pedro', password: 'my_password' }
);
const knoxToken = data.token;
var body = new StringContent(
JsonSerializer.Serialize(new { username = "pedro", password = "my_password" }),
Encoding.UTF8, "application/json"
);
var response = await client.PostAsync("https://YOUR-DOMAIN/home/api/auth/login/", body);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://YOUR-DOMAIN/home/api/auth/login/"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"username\":\"pedro\",\"password\":\"my_password\"}"
))
.build();
Response 200:
{ "token": "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b..." }
Response 401 — invalid credentials:
{ "error": "Credenciales inválidas" }
Knox logout
| Property | Value |
|---|---|
| Method | POST |
| Path | /home/api/auth/logout/ |
| Authentication | Knox token (header Authorization: Token <token>) |
POST /home/api/auth/logout/
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
requests.post(
"https://YOUR-DOMAIN/home/api/auth/logout/",
headers={"Authorization": f"Token {knox_token}"}
)
await axios.post(
'https://YOUR-DOMAIN/home/api/auth/logout/',
{},
{ headers: { 'Authorization': `Token ${knoxToken}` } }
);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Token", knoxToken);
await client.PostAsync("https://YOUR-DOMAIN/home/api/auth/logout/",
new StringContent(""));
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://YOUR-DOMAIN/home/api/auth/logout/"))
.header("Authorization", "Token " + knoxToken)
.POST(HttpRequest.BodyPublishers.noBody())
.build();
Logout all Knox sessions
| Property | Value |
|---|---|
| Method | POST |
| Path | /home/api/auth/logoutall/ |
| Authentication | Knox token |
POST /home/api/auth/logoutall/
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
requests.post(
"https://YOUR-DOMAIN/home/api/auth/logoutall/",
headers={"Authorization": f"Token {knox_token}"}
)
await axios.post(
'https://YOUR-DOMAIN/home/api/auth/logoutall/',
{},
{ headers: { 'Authorization': `Token ${knoxToken}` } }
);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Token", knoxToken);
await client.PostAsync("https://YOUR-DOMAIN/home/api/auth/logoutall/",
new StringContent(""));
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://YOUR-DOMAIN/home/api/auth/logoutall/"))
.header("Authorization", "Token " + knoxToken)
.POST(HttpRequest.BodyPublishers.noBody())
.build();
Mechanism comparison
| Feature | JWT (SimpleJWT) | Knox |
|---|---|---|
| Token type | Signed (stateless) | Opaque (stored in DB) |
| Renewal | Via refresh token | Does not expire (configurable) |
| Revocation | No (until expiration) | Yes (logout invalidates) |
| Header | Authorization: Bearer <token> | Authorization: Token <token> |
| Recommended use | API integrations | Long-session applications |