new - Arquitectos de las claves API y tokens de acceso
twitter api secret key (3)
Tengo una pregunta sobre cómo debo diseñar una API REST utilizando el token de acceso y las claves API.
Tengo una API que necesita autenticación. Quiero habilitar dos casos de uso:
El usuario inicia sesión en la interfaz utilizando OAuth2 (concesión de contraseña) y se le otorga un token de acceso temporal. Este token se utiliza para autenticar al usuario. Por lo tanto, la IU, que a su vez utiliza la API, puede obtener datos y mostrarlos.
También quiero que el usuario tenga una clave API para hacer las mismas llamadas, pero en su aplicación. Obviamente, al contrario del token de acceso, quiero que la clave API sea de larga duración. Además, al contrario del token de acceso que está vinculado a un usuario determinado (si introducimos un mecanismo de equipo, cada usuario tendrá un token de acceso diferente, aunque accedan a los mismos recursos), la clave API debe ser única para el proyecto.
Si bien es similar, no estoy seguro de cómo debería estructurar eso. Creo que, internamente, tanto las claves API como los tokens de acceso deben almacenarse en la misma tabla, pero las claves API no tienen fecha de caducidad. Estoy en lo cierto
Una cosa de la que tampoco estoy seguro es el concepto de cliente. Parece que en la especificación, el cliente es más como una aplicación externa. Sin embargo, ¿puedo realmente usar este concepto aquí?
Por ejemplo, cada "proyecto" es en realidad un cliente diferente (aunque el cliente aquí es la misma aplicación, no una aplicación creada por un desarrollador externo).
Por lo tanto, si el usuario A crea una cuenta en el sistema, un cliente A se creará automáticamente, con un token de acceso vinculado al cliente A, con un token de acceso de larga duración (también conocido como clave API). Esto se puede utilizar para realizar llamadas API directamente en su código, por ejemplo.
Luego, si el usuario A inicia sesión en el tablero, se creará un token de acceso temporal, pero esta vez sin aplicación, pero vinculado al usuario, con una vida corta.
¿Suena esto sano? ¿Alguien ya ha implementado tal cosa?
¡Gracias!
Creo que no deberías considerar las "claves API" como un sustituto del token de acceso.
Tendrá que usar un token de acceso de todos modos para soportar la autenticación entre solicitudes, de modo que lo que realmente modela con sus "claves API" no reemplaza al token portador habitual, sino que es un cliente diferente que proporciona otros tipos de concesión para solicitar un token con.
El flujo que yo personalmente implementaría es el siguiente:
- El usuario se autentica con el tipo de concesión de contraseña con un cliente común para cada usuario (es decir, su cliente de "aplicación web", que es público, es decir, no tiene un
client_secret
). - El usuario puede crear su propio cliente. Según las especificaciones de OAuth2, estas no son públicas, por lo que consistirán en un
client_id
y unclient_secret
. Estas son las que llamas "claves API". - Luego, un usuario podrá solicitar un token de acceso a través de su cliente, con cualquier tipo de concesión que quiera admitir (por ejemplo, credenciales directas del cliente, código de autorización, implícito, terceros, etc.). Tendrá que insistir bastante en las prácticas de seguridad adecuadas sobre cómo manejar las credenciales del cliente.
Obviamente, tendrá que implementar su servidor OAuth2 de tal manera que los clientes puedan pertenecer a usuarios específicos y tener diferentes tipos de concesión aceptables (es decir, es posible que no desee permitir el uso de concesión de contraseña con un cliente de usuario, mientras que puede que desee rechazar). cualquier tipo de concesión que no sea la contraseña para su cliente de aplicación web).
A continuación, podrá definir los TTL de tokens, o la falta de ellos, por cliente o por tipo de otorgamiento (por ejemplo, el token de acceso solicitado a través de la concesión de contraseña, que solo podrá utilizar el cliente de la aplicación web, tendrá un TTL corto, mientras que el otorgamiento del código de autorización proporcionar fichas de larga vida).
Sin embargo, desaconsejaría la falta completa de TTL y, más bien, utilizaría el tipo de concesión refresh_token
para renovar los tokens de acceso caducados.
Además, probablemente tendrá que definir un sistema de autorización de algún tipo (ACL, RBAC, lo que sea), para definir qué cliente puede hacer qué. Esto significa que cada token de acceso debe contener una referencia al cliente utilizado para su creación.
Entonces, para resumir, aquí están las relaciones:
El usuario tiene un cliente .
El cliente tiene un usuario .
El cliente tiene muchas fichas .
Token tiene un cliente .
Token tiene un usuario .
YMMV en bidireccionales.
Debería poder implementar todo lo que describí con las implementaciones más comunes de servidores OAuth2 de cualquier plataforma dada.
TL; DR: las "claves API" son en realidad clientes OAuth2.
Escribí una publicación sobre la forma de usar tokens de acceso para aplicaciones RESTful: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/ . Tal vez esto puede dar algunos consejos.
Para responder a sus preguntas, creo que necesitamos tener algo homogéneo. Me refiero a que todos sus mecanismos de autenticación deben basarse en tokens de acceso. Sus claves de API le permitirían obtener un token de acceso que realmente se usaría para la autenticación.
Según tengo entendido, tiene dos tipos de usuarios de sus aplicaciones:
- Usuarios finales que utilizan la interfaz de usuario web (inicio de sesión con contraseña a través de OAuth2)
- Aplicaciones (inicio de sesión con claves API)
Así que implementaría estos dos tipos de usuarios y les daría la posibilidad de obtener tokens de acceso. Los tokens de acceso se utilizarán en ambos casos para acceder a los servicios RESTful.
Además, creo que esta respuesta puede darle algunos otros consejos: Asegurar mi API REST con OAuth y al mismo tiempo permitir la autenticación a través de proveedores de OAuth de terceros (utilizando DotNetOpenAuth) .
Espero que responda a su pregunta. Thierry
Gracias por su respuesta.
De hecho, tengo bastante experiencia con OAuth2, mi pregunta estaba más orientada a las claves API. Me gusta la idea de una clave API que intercambie un token de acceso, pero creo que no funciona. La clave de API es fija y no cambia, mientras que el token de acceso puede caducar.
La pregunta es: cómo puede saber la aplicación si se trata de un token de acceso o claves de API. Quiero decir, está bien, digamos que en mi base de datos, cada usuario tiene una columna "api_key" en su base de datos.
Al contrario de un token de acceso, la api_key no caduca (aunque el usuario puede rotarla). Lo que quiero, como dije, es un manejo homogéneo de la autenticación.
Caso 1: mi propia aplicación web hace llamadas a la API
El flujo de trabajo es el siguiente, utilizando OAuth2:
- El usuario ingresa su correo / contraseña.
- El servidor de autorización devuelve un token de acceso temporal (p. Ej .: "abc").
- En la aplicación web, todas las llamadas a la API se realizan utilizando este token. Por ejemplo: "/ payment / 1" con encabezado de autorización: "Abc de portador".
Agradable y sencillo.
Caso 2: el usuario tiene una clave de API que no caduca y se puede usar de forma privada en su propia aplicación
Obviamente, el mecanismo de autorización debe permanecer igual. Asi que:
- El usuario ingresa a su cuenta y lee que su clave API es "def".
- En su código de servidor, pueden hacer la misma llamada, con el mismo mecanismo de autenticación. Así que puede llamar "/ pagos / 1" con Autorización: "Definición de portador".
Y debe funcionar. Como puede ver, nada ha cambiado en ambos ejemplos. Acceden al mismo recurso, al mismo mecanismo de autorización ... pero en un caso tenemos un token de acceso y en otro caso tenemos una clave API. Y no tengo idea de cómo debería implementarlo tanto desde el punto de vista de la base de datos como en el código de autorización.
Una idea potencial que tuve fue usar diferentes mecanismos de autenticación. Para OAuth, sería "Autorización: acceso de portador de acceso", mientras que para API sería una autenticación básica: "Autorización: apiKey básica".
¿Esto suena bien?