Skip to Content

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:

  1. El cliente envía client_id, client_secret, grant_type=client_credentials y scope opcional al endpoint de tokens
  2. Auris valida las credenciales y comprueba que los scopes solicitados están permitidos para la aplicación
  3. Auris emite un JWT access token con type: 'm2m' y los scopes concedidos en el claim scope
  4. 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.com

Implementación

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:

  1. Habilita DPoP en la aplicación M2M en Consola → Aplicaciones → [Aplicación] → Configuración → Requerir DPoP
  2. 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

POST/api/auth/token

Endpoint de tokens. Establece grant_type=client_credentials, client_id, client_secret y scope opcional. Devuelve un access token y su expiración.

GET/api/applications/:id/m2m-scopesRequires: manage:applications

Lista los scopes permitidos para una aplicación M2M.

POST/api/applications/:id/m2m-scopesRequires: manage:applications

Actualiza los scopes permitidos para una aplicación M2M.


Guías Relacionadas