Prompt y alcance
Este es un problema de protocolo OAuth y diseño de seguridad. RFC 8628 está dirigido a smart TVs, consolas multimedia, impresoras y dispositivos similares que no pueden ingresar texto cómodamente ni ejecutar un navegador. El dispositivo solicita un device_code y un user_code; el usuario inicia sesión y autoriza en un navegador independiente; el dispositivo original sondea el endpoint de tokens. Dichos dispositivos suelen ser clientes públicos y no pueden ocultar un client secret de larga duración en el firmware. El ejercicio no reemplaza el flujo de código de autorización para aplicaciones nativas que pueden usar el navegador del sistema.
Qué está evaluando el entrevistador
- Distinguir las vidas útiles de los device codes, user codes, URI de verificación, tokens de acceso y tokens de actualización.
- Mapear
authorization_pending,slow_down,expired_tokenyaccess_denieda estados. - Diseñar sondeo acotado, backoff, idempotencia y protección de concurrencia.
- Reconocer el phishing de user codes, la suplantación de dispositivos, la adivinación por fuerza bruta y los riesgos de clientes públicos.
Aclaraciones para hacer primero
Confirma si el dispositivo puede mostrar una URI y un código, realizar solicitudes HTTPS y mantener un reloj confiable, y si el servidor de autorización admite el inicio de sesión con OIDC. Aclara los recursos solicitados, la vinculación del dispositivo, quién establece la vida útil del código y el intervalo de sondeo, y si se requiere la cancelación. Si el dispositivo ya tiene un navegador del sistema, prefiere el flujo de código de autorización de RFC 8252 en lugar de forzar Device Flow.
Una respuesta de 30 segundos
Implementa dos endpoints. El endpoint de autorización de dispositivos devuelve un device_code de corta duración, un user_code ingresado por humanos, verification_uri, expiración y un intervalo mínimo. El endpoint de tokens acepta solo el device code y devuelve tokens o errores estándar. Almacena un hash del device code, el estado, el cliente y la expiración. Sondea en el intervalo proporcionado por el servidor: continúa en authorization_pending, aumenta el intervalo en slow_down y detente ante el éxito, la expiración, la denegación o la invalidez permanente. Muestra información del dispositivo en la página del usuario para reducir el phishing.
Solución paso a paso
1. Modelar los participantes y una sesión de autorización
Los participantes son el dispositivo restringido, el servidor de autorización, el navegador del usuario y el servidor de recursos. El endpoint de autorización de dispositivos crea una sesión con device_code de alta entropía, user_code fácil de ingresar, el cliente, los alcances solicitados, la hora de creación, la expiración y el estado de sondeo. Almacena solo un resumen unidireccional del device code para que una lectura de base de datos no genere directamente un token; indexa el user code por separado y limita los intentos.
2. Diseñar la respuesta de autorización de dispositivos
Devuelve al menos device_code, user_code, verification_uri, expires_in y interval. verification_uri_complete puede ofrecer un enlace conveniente, pero muestra el mismo código corto en el dispositivo y en la página del usuario, y pídele al usuario que confirme el dispositivo frente a él. Protege el código de registros, analíticas y capturas de pantalla. El servidor no debe colocar un token de acceso en esta respuesta.
3. Manejar la interacción y vinculación del usuario
Después de abrir la URI de verificación, el usuario inicia sesión y ve el nombre del cliente, los alcances solicitados y la información del dispositivo. La página de consentimiento debe hacer que el usuario confirme que el dispositivo es suyo, lo que reduce la autorización del dispositivo de un atacante. La aprobación cambia la sesión a AUTHORIZED; no envía un token a través del navegador al dispositivo. Una denegación es un estado terminal DENIED que el siguiente sondeo informa explícitamente.
4. Definir la máquina de estados del endpoint de tokens
El endpoint de tokens maneja el estado del dispositivo con errores estándar:
poll(device_code):
session = lookup(hash(device_code))
if session is missing: return invalid_grant
if now >= session.expiresAt: return expired_token
if session.status == DENIED: return access_denied
if session.status != AUTHORIZED: return authorization_pending
atomically mark CONSUMED
return issueAccessAndRefreshTokens(session)El canje exitoso de un device code debe ser atómico para que dos hilos del dispositivo no puedan recibir dos conjuntos de tokens. Si un código es de un solo uso, una solicitud repetida devuelve invalid_grant o el error de consumo del protocolo; un reintento fallido no debe crear una nueva sesión de autorización.
5. Aplicar backoff de sondeo y protección del servidor
El dispositivo no debe sondear antes del interval de la respuesta. Mantén ese intervalo después de authorization_pending; después de slow_down, auméntalo en al menos 5 segundos. Agrega una fecha límite total, tiempos de espera de red y jitter en el dispositivo. Aplica rate limiting por device code, cliente e IP en el servidor. Las respuestas de tokens deben prohibir el almacenamiento en caché para que los intermediarios no reproduzcan el estado; bajo carga, devuelve un error reintentable en lugar de crear una tarea en segundo plano costosa por cada sondeo.
6. Manejar la expiración, cancelación y recuperación
Trata expired_token, access_denied y el invalid_grant permanente como terminales. Borra el device code local y detén el sondeo. Una acción de cancelación del dispositivo marca la sesión como CANCELLED; solicitudes posteriores no pueden revivirla. Ante una interrupción de red, conserva la fecha límite y reanuda con el mismo código en lugar de crear varias sesiones que puedan autorizar el dispositivo equivocado. Después de un reinicio, vuelve a comenzar e infórmale al usuario si el dispositivo no puede persistir de manera segura el estado de la sesión.
7. Proteger clientes públicos y resistir el phishing
Asume que el dispositivo no puede proteger un client secret. Minimiza los alcances, y rota y revoca los tokens de actualización. Haz que el user code sea lo suficientemente corto para ingresarlo, pero lo suficientemente aleatorio para resistir la adivinación en línea; limita la tasa de intentos fallidos por código e IP. Muestra el nombre del dispositivo, modelo o código de un solo uso y pídele al usuario que lo compare con la pantalla. Los registros contienen solo un ID de sesión, el resultado e identificadores con hash, nunca el device code sin procesar ni los tokens.
8. Instrumentar y probar el flujo
Mide la creación de autorizaciones de dispositivos, la finalización, el tiempo hasta la finalización, los sondeos por sesión, la tasa de slow_down, la expiración y denegación, y las condiciones de carrera en el canje de tokens. Prueba canjes duplicados, tiempos de espera, desfase horario, reintentos de red, adivinación, sondeos concurrentes, denegación del usuario, reinicio del servidor y throttling. Una prueba de extremo a extremo debe demostrar que el dispositivo aprobado y la sesión de token final coinciden; que dos endpoints devuelvan 200 de forma independiente es insuficiente.
Respuesta modelo
Crearía una sesión RFC 8628 de un solo uso. El endpoint del dispositivo devuelve un device_code de alta entropía, un user code corto, una URI de verificación, expiración y un intervalo mínimo de sondeo; el servidor almacena un código con hash y un estado explícito. El usuario inicia sesión en un teléfono, revisa el cliente, los alcances y la información del dispositivo, y aprueba. El endpoint de tokens acepta solo el device code: continúa en authorization_pending, agrega al menos 5 segundos en slow_down y termina por expiración, denegación o invalidez permanente. Consume el código atómicamente para que los sondeos concurrentes no puedan emitir dos conjuntos de tokens. Trata al dispositivo como un cliente público, minimiza los alcances, rota los tokens de actualización, limita la adivinación y pídele al usuario que compare el código en ambas pantallas. Las métricas y pruebas cubren la vinculación del flujo, el backoff, la recuperación y los límites de phishing.
Errores comunes
- Tratar el device code como el código ingresado por humanos y exponer una credencial de alto valor en la interfaz de usuario o los registros.
- Ignorar
slow_downy sondear el endpoint de tokens a una tasa fija y alta. - Reintentar indefinidamente todos los errores, incluidas la expiración y la denegación.
- Pretender que un secret de dispositivo estático convierte a un cliente público en confidencial.
- Enviar un token de acceso directamente a través de una URL del navegador o un script de página después de la aprobación.
- No consumir atómicamente el device code y emitir múltiples tokens de actualización.
- Probar los endpoints de sondeo por separado sin demostrar que el dispositivo aprobado coincide con la sesión del token.
Preguntas de seguimiento
¿Cómo eliges la longitud y la vida útil del user code?
Equilibra la comodidad de entrada, el costo de adivinación en línea y el tiempo de finalización. Evita caracteres ambiguos, limita los intentos fallidos y la tasa agregada, y haz que la vida útil sea lo suficientemente larga para que el usuario tome un teléfono, inicie sesión y confirme el dispositivo sin crear una ventana ilimitada de phishing. Calibra los números con el modelo de amenazas y el tiempo de finalización observado.
¿Cómo evitas que un cliente malicioso llene todas las sesiones?
Aplica rate limiting a la creación por registro de cliente, IP, huella digital del dispositivo y cuenta; limita las sesiones no finalizadas por principal y limpia las sesiones expiradas de forma asíncrona. Valida el cliente y los alcances antes de crear una sesión. No traslades la presión de limpieza de device codes basura al endpoint de tokens.
¿Cómo se recupera un dispositivo fuera de línea después de la aprobación?
Mantén la sesión hasta su expiración para que el dispositivo pueda sondear el mismo código después de reconectarse. Devuelve el conjunto de tokens o un estado terminal. Haz que el manejo del canje sea idempotente para que una respuesta perdida no cause un segundo consumo. Después de la expiración, reinicia con un nuevo código e informa al usuario.
¿Cuáles son los riesgos de verification_uri_complete?
Poner el user code en un enlace reduce la necesidad de escribir, pero aumenta la fuga de enlaces y el riesgo de phishing remoto. Aún así, muestra el código corto y pídele al usuario que lo compare con la pantalla del dispositivo. No expongas el enlace completo a analíticas, encabezados Referer, historial o redirecciones de terceros. Ofrécelo solo cuando la capacidad del dispositivo y el modelo de amenazas lo permitan.
¿Por qué no transferir el token de acceso del teléfono al dispositivo?
La transferencia de tokens entre dispositivos amplía la exposición a través del navegador, código QR, portapapeles y páginas intermedias, y es difícil demostrar que el destinatario es el dispositivo correcto. Device Flow permite que el dispositivo canjee su propio código a través de TLS; la página del usuario cambia solo el estado del servidor. Agrega un canal de campo cercano autenticado por separado si el producto lo requiere.
¿Cómo verificas que el sondeo aplique backoff correctamente?
Registra los recuentos de sondeo a nivel de sesión, las distribuciones de intervalos, los intervalos reales después de slow_down, la latencia terminal y los fallos agregados por cliente. Inyecta sondeos repetidos en pruebas controladas y verifica que slow_down aumente el intervalo del cliente en al menos 5 segundos sin una tormenta sincronizada. Aísla a los clientes abusivos en lugar de relajar el intervalo global.