Credenciales M2M (Client Credentials)
La autenticación máquina a máquina (M2M) se utiliza cuando un servicio backend o proceso automatizado necesita llamar a una API sin que haya un usuario humano presente. Auris implementa el grant OAuth2 client_credentials (RFC 6749 Sección 4.4), emitiendo access tokens directamente a clientes confidenciales.
Casos de uso comunes:
- Un job en segundo plano que necesita leer datos de usuarios de la API de gestión de Auris
- Un microservicio que valida permisos para solicitudes de API
- Un pipeline CI/CD que gestiona roles y configuración de aplicaciones
- Un servicio backend llamando a otro servicio que valida tokens de Auris
Cómo Funciona
El flujo client_credentials no implica un usuario, una página de inicio de sesión ni una redirección. El cliente envía sus credenciales directamente al endpoint de tokens y recibe un access token:
- El cliente envía
client_id,client_secret,grant_type=client_credentialsyscopeopcional al endpoint de tokens - Auris valida las credenciales y comprueba que los scopes solicitados están permitidos para la aplicación
- Auris emite un JWT access token con
type: 'm2m'y los scopes concedidos en el claimscope - El cliente presenta el access token como token Bearer en las llamadas a APIs posteriores
Los tokens tienen corta duración (predeterminado: 60 minutos) y deben almacenarse en caché y reutilizarse hasta su expiración.
Configuración en la Consola
Crear una Aplicación M2M
En la Consola de Auris, ve a Aplicaciones → Crear Aplicación y selecciona M2M como tipo de aplicación.
Las aplicaciones M2M no tienen URIs de redirección ni páginas de inicio de sesión — solo credenciales y scopes.
Configurar los Scopes Permitidos
En la pestaña Scopes M2M de la página de detalle de la aplicación, selecciona qué scopes tiene permitido solicitar la aplicación. Los scopes disponibles están organizados por recurso (ej. read:users, manage:roles, view:organizations).
Copiar las Credenciales
En la pestaña Credenciales, copia el Client ID y el Client Secret.
Los client secrets se muestran solo una vez en el momento de la creación. Almacena el secret de forma segura (ej. en un gestor de secretos o variable de entorno). Si se pierde el secret, usa el botón Rotar Secret para generar uno nuevo.
Almacenar las Credenciales de Forma Segura
Establece las credenciales como variables de entorno en tu entorno de despliegue. Nunca las codifiques directamente en el código fuente ni las incluyas en el control de versiones.
AURIS_CLIENT_ID=tu-client-id-m2m
AURIS_CLIENT_SECRET=tu-client-secret-m2m
AURIS_DOMAIN=auth.tudominio.comImplementación
JavaScript
import { AurisClient } from '@auris/js'
const auris = new AurisClient({
domain: process.env.AURIS_DOMAIN,
clientId: process.env.AURIS_CLIENT_ID,
})
// Solicitar un access token M2M con scopes específicos
const token = await auris.getM2MToken(
process.env.AURIS_CLIENT_SECRET,
['read:users', 'manage:roles'],
)
console.log('Access token:', token.accessToken)
console.log('Expira en:', token.expiresIn, 'segundos')
// Usar el token para llamar a la API de gestión de Auris
const respuestaUsuarios = await fetch('https://auth.tudominio.com/api/users', {
headers: { Authorization: `Bearer ${token.accessToken}` },
})
const usuarios = await respuestaUsuarios.json()Formato del Token
Los access tokens M2M son JWTs con los siguientes claims:
{
"iss": "https://auth.tudominio.com",
"sub": "tu-client-id",
"aud": "https://auth.tudominio.com",
"exp": 1735000000,
"iat": 1734996400,
"type": "m2m",
"scope": "read:users manage:roles",
"clientId": "tu-client-id"
}El claim type: 'm2m' distingue estos tokens de los tokens de usuario (type: 'user'). Tus APIs pueden usar este claim para diferenciar entre solicitudes de usuarios y de servicios.
Caché de Tokens
Los tokens M2M deben almacenarse en caché durante todo su período de validez para evitar llamadas innecesarias al endpoint de tokens:
class CacheTokens {
#token = null
#expiresAt = 0
async getToken(auris, clientSecret, scopes) {
// Devolver token en caché si aún es válido (con margen de 60s)
if (this.#token && Date.now() < this.#expiresAt - 60_000) {
return this.#token
}
const resultado = await auris.getM2MToken(clientSecret, scopes)
this.#token = resultado.accessToken
this.#expiresAt = Date.now() + resultado.expiresIn * 1000
return this.#token
}
}
const cache = new CacheTokens()
// En tus llamadas a la API:
const token = await cache.getToken(auris, clientSecret, ['read:users'])Vinculación de Tokens DPoP
Para entornos que requieren tokens vinculados al remitente, Auris admite DPoP (Demonstrating Proof of Possession, RFC 9449). DPoP vincula el access token a la clave pública de un cliente específico — un token robado no puede ser usado por un cliente diferente sin la clave privada correspondiente.
Habilitar DPoP para aplicaciones M2M:
- Habilita DPoP en la aplicación M2M en Consola → Aplicaciones → [Aplicación] → Configuración → Requerir DPoP
- Genera un par de claves en tu servicio e incluye una cabecera de prueba DPoP con cada solicitud de token y llamada a la API
import { createDpopProof } from '@auris/js'
// Generar un par de claves DPoP (hacer esto una vez al iniciar el servicio)
const dpopKeyPair = await crypto.subtle.generateKey(
{ name: 'ECDSA', namedCurve: 'P-256' },
false, // no extraíble
['sign', 'verify'],
)
// Solicitar un token con DPoP
const dpopProof = await createDpopProof(dpopKeyPair, 'POST', urlEndpointToken)
const respuestaToken = await fetch(urlEndpointToken, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'DPoP': dpopProof,
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
}),
})Proteger tus Propias APIs con Tokens M2M
Si tus APIs backend aceptan tokens M2M de Auris de otros servicios, valida la firma del token usando el endpoint JWKS de Auris:
import { verifyToken } from '@auris/js/jwt-verify'
export async function authMiddleware(req, res, next) {
const authHeader = req.headers.authorization
if (!authHeader?.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Falta la cabecera Authorization' })
}
const token = authHeader.slice(7)
try {
const payload = await verifyToken(token, {
jwksUrl: 'https://auth.tudominio.com/.well-known/jwks.json',
issuer: 'https://auth.tudominio.com',
})
// Verificar que es un token M2M (no un token de usuario)
if (payload.type !== 'm2m') {
return res.status(403).json({ error: 'Los tokens de usuario no están permitidos en este endpoint' })
}
// Verificar los scopes requeridos
const scopes = payload.scope?.split(' ') ?? []
if (!scopes.includes('call:tu-servicio')) {
return res.status(403).json({ error: 'Scope insuficiente' })
}
req.clientId = payload.sub
next()
} catch (err) {
return res.status(401).json({ error: 'Token inválido' })
}
}Endpoints de la API
/api/auth/tokenEndpoint de tokens. Establece grant_type=client_credentials, client_id, client_secret y scope opcional. Devuelve un access token y su expiración.
/api/applications/:id/m2m-scopesRequires: manage:applicationsLista los scopes permitidos para una aplicación M2M.
/api/applications/:id/m2m-scopesRequires: manage:applicationsActualiza los scopes permitidos para una aplicación M2M.
Guías Relacionadas
- Hosted Login (PKCE) — Autenticación de usuario interactiva
- Roles y Permisos (RBAC) — Controlar qué pueden hacer los clientes M2M
- Autorización de Grano Fino — Control de acceso a nivel de objeto para servicios M2M