php - por - seguridad api rest
Autorización y autenticación de la API REST(web+móvil) (1)
Como siempre, la mejor manera de proteger una clave es no transmitirla.
Dicho esto, normalmente utilizamos un esquema, donde cada "clave de API" tiene dos partes: una ID no secreta (por ejemplo, 1234) y una clave secreta (por ejemplo, byte [64]).
- Si entrega una clave API, guárdela (salada y hash) en la base de datos de su servicio.
- Si regala cuentas de usuario (protegidas por contraseña), almacene las contraseñas (salados y hash) en la base de datos de su servicio
Ahora cuando un consumidor primero accede a su API, para conectarse, tenerlo
- Enviar un parámetro de "nombre de usuario" ("john.doe" no es secreto)
- Envíe un parámetro "APIkeyID" ("1234", no en secreto)
y devolverlo
- las sales de su base de datos (en caso de que uno de los parámetros sea incorrecto, simplemente devuelva una sal repetible, por ejemplo, sha1 (username + "notverysecret").
- La marca de tiempo del servidor
El consumidor debe almacenar la sal por la duración de la sesión para mantener las cosas rápidas y sin problemas, y debe calcular y mantener la diferencia horaria entre el cliente y el servidor.
El consumidor ahora debe calcular los valores hash salados de la clave API y la contraseña. De esta forma, el consumidor tiene exactamente los mismos valores hash para la contraseña y la clave API, como lo que se almacena en su base de datos, pero sin nada que pueda pasar por alto.
Ahora cuando un consumidor accede subsecuentemente a su API, para hacer un trabajo real, tenerlo
- Enviar un parámetro de "nombre de usuario" ("john.doe" no es secreto)
- Envíe un parámetro "APIkeyID" ("1234", no en secreto)
- Enviar un parámetro "RequestSalt" (byte [64], aleatorio, no secreto)
- Enviar un parámetro "RequestTimestamp" (calculado a partir de la hora del cliente y el desplazamiento conocido)
- Enviar un parámetro "RequestToken" (hash (passwordhash + request_salt + request_timestamp + apikeyhash))
El servidor no debería aceptar marcas de tiempo más que en 2 segundos en el pasado, para que esto sea seguro contra un ataque de repetición.
El servidor ahora puede calcular el mismo hash (passwordhash + request_salt + request_timestamp + apikeyhash) como cliente, y asegúrese de que
- el cliente conoce la clave API,
- el cliente conoce la contraseña correcta
He leído sobre oAuth, API de REST de Amazon, HTTP Basic / Digest, etc., pero no puedo obtener todo en "una sola pieza". Esta es probablemente la situación más cercana - Crear una API para aplicaciones móviles - Autenticación y autorización
Me gustaría construir un sitio web centrado en API: servicio. Entonces (al principio) tendría una API en el centro y el sitio web (PHP + MySQL) se conectaría a través de cURL , Android y iPhone a través de sus interfaces de red. Entonces 3 clientes principales: 3 claves de API. Y cualquier otro desarrollador también podría desarrollar a través de la interfaz API y obtendría su propia clave API. Las acciones de API serían aceptadas / rechazadas según el estado de UserLevel, si soy administrador, puedo eliminar cualquier cosa, etc., todas las demás pueden manipular solo sus datos locales (de cuenta).
En primer lugar, autorización: ¿debo usar oAuth + xAuth o alguna implementación de mi tipo (ver http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/RESTAuthentication.html?r=9197 )? Según entiendo, en Amazon el usuario del servicio es == usuario de API (tiene clave de API) . En mi servicio, debo separar usuarios / cuenta estándar (el que se registró en el sitio web) y cuentas de desarrollador (que deben tener su clave API).
Entonces, primero necesitaría autorizar la clave API y luego autenticar al usuario . Si utilizo el esquema de Amazon para verificar las claves de la API del desarrollador (autorizo su aplicación), ¿qué sheme debería usar para la autenticación del usuario?
Leí acerca de obtener un token a través de api.example.org/auth
después (a través de HTTPS , HTTP Basic) publicando mi nombre de usuario y contraseña y luego reenviarlo en cada solicitud siguiente. ¿Cómo administro tokens si estoy conectado simultáneamente en Android y un sitio web ? ¿Qué pasa con man-in-the-middle-attack si estoy utilizando SSL solo en la primera solicitud (cuando se transmiten el nombre de usuario y la contraseña) y solo HTTP en todos los demás? ¿No es un problema en este ejemplo la contraseña que protege un servicio REST?