API REST segura y aplicación de página única mediante el uso de un código de autorización OAuth 2 externo

11

Estoy tratando de entender cómo implementar un flujo de Código de Autorización OAuth 2 cuando tengo una aplicación JS de una sola página y una API REST. El objetivo es garantizar el acceso a la API REST mediante la descarga de la autenticación al proveedor de OAuth.

Actualmente mi flujo se ve como:

1)

+--------------------+               +----------------+
| JS Single Page App | - redirect -> | OAuth Provider | - user enters credentials
+--------------------+               +----------------+

2)

+----------------+                                   +----------+
| OAuth Provider | - redirect with temporary code -> | REST API |
+----------------+                                   +----------+

3)

+----------+                                      +----------------+
| REST API | - request access token using code -> | OAuth Provider |
+----------+ <- return access token ------------- +----------------+

¿Qué debo hacer ahora? Mi entendimiento actual es que debo redirigir al usuario al recibir el token de acceso a una página que cargará la aplicación de una sola página JS nuevamente. ¿Pero debo compartir el token de acceso con la aplicación de una sola página y usar su presencia para autenticar cualquier solicitud que llegue a mi API REST, o es mejor crear un identificador separado y mantener una asignación del lado del servidor entre new-identifier->access_token ? De cualquier manera, ¿cuál sería la mejor manera de transferir el identificador al cliente? Preferiría no mantener ninguna sesión y no mostrar el identificador en la barra de URL de la página redirigida. Lo único que puedo pensar en este momento es crear una cookie temporal que la aplicación de una sola página pueda leer y luego borrar, pero de alguna manera eso se siente un poco torpe.

    
pregunta Anvar Karimson 13.09.2014 - 11:40
fuente

2 respuestas

11

En primer lugar, y para ser muy claros, OAuth 2 no es un protocolo de autenticación. Si desea conocer la identidad del usuario, hay otros protocolos diseñados para resolver este problema, como OpenID Connect . Si pretende utilizar OAuth 2 con el fin de autorizar el acceso a sus recursos protegidos, continúe leyendo.

Para responder a su pregunta directa: parece que está usando el Subvención del código de autorización :

 +----------+
 | Resource |
 |   Owner  |
 |          |
 +----------+
      ^
      |
     (B)
 +----|-----+          Client Identifier      +---------------+
 |         -+----(A)-- & Redirection URI ---->|               |
 |  User-   |                                 | Authorization |
 |  Agent  -+----(B)-- User authenticates --->|     Server    |
 |          |                                 |               |
 |         -+----(C)-- Authorization Code ---<|               |
 +-|----|---+                                 +---------------+
   |    |                                         ^      v
  (A)  (C)                                        |      |
   |    |                                         |      |
   ^    v                                         |      |
 +---------+                                      |      |
 |         |>---(D)-- Authorization Code ---------'      |
 |  Client |          & Redirection URI                  |
 |         |                                             |
 |         |<---(E)----- Access Token -------------------'
 +---------+       (w/ Optional Refresh Token)

Este flujo está optimizado para clientes confidenciales : clientes que pueden mantener un secreto del usuario final y de cualquier tercero que intente obtener acceso a los recursos protegidos. En el caso de que una aplicación javascript se ejecute en el navegador del cliente, no puede guardar un secreto: todo el código está allí y simplemente entrar en él con el depurador del navegador revela todos los secretos.

En cambio, existe el flujo de subvención implícita , específicamente optimizado para clientes como el suyo. El RFC incluso utiliza JavaScript que se ejecuta en un navegador como ejemplo de un cliente destinado a usar este flujo.

 +----------+
 | Resource |
 |  Owner   |
 |          |
 +----------+
      ^
      |
     (B)
 +----|-----+          Client Identifier     +---------------+
 |         -+----(A)-- & Redirection URI --->|               |
 |  User-   |                                | Authorization |
 |  Agent  -|----(B)-- User authenticates -->|     Server    |
 |          |                                |               |
 |          |<---(C)--- Redirection URI ----<|               |
 |          |          with Access Token     +---------------+
 |          |            in Fragment
 |          |                                +---------------+
 |          |----(D)--- Redirection URI ---->|   Web-Hosted  |
 |          |          without Fragment      |     Client    |
 |          |                                |    Resource   |
 |     (F)  |<---(E)------- Script ---------<|               |
 |          |                                +---------------+
 +-|--------+
   |    |
  (A)  (G) Access Token
   |    |
   ^    v
 +---------+
 |         |
 |  Client |
 |         |
 +---------+

Debe leer el RFC para obtener detalles sobre cómo funciona este flujo, pero el concepto general de flujo ya no requiere el uso de un código de autorización; en su lugar, al cliente se le asigna directamente el código de acceso.

Esto conlleva el inconveniente de que cuando el código ya no es válido, el cliente debe solicitar el recurso nuevamente; no hay manera de "recordar" la concesión de autorización para un cliente que no puede mantener un secreto. Esta es una decisión intencional tomada por los autores de OAuth para mejorar la seguridad de los clientes de esta naturaleza.

    
respondido por el Paul Turner 17.09.2014 - 15:34
fuente
0

No estoy seguro si entiendo tu situación correcta. Si solo desea asegurar sus llamadas a la API RESTful desde un cliente javascript con OAuth, entonces la respuesta de Tragedian sobre el tipo de concesión implícita es absolutamente correcta. Esto significa que tiene una clara segregación de IU y datos:

  • La interfaz de usuario (es decir, la aplicación de página única JS) se puede cargar sin ningún tipo de autenticación / autorización
  • Los datos (es decir, las llamadas a la API RESTful) se protegen con tokens de acceso DESPUÉS de que el servidor de autorización lo haya autorizado

Si tiene un escenario diferente, descríbalo de manera más precisa. Usted menciona algo de una parte de back-end de la aplicación que también se basa en OAuth y que es capaz de almacenar datos confidenciales. Esto significaría que tiene, además de la aplicación de página única JS, un cliente DIFERENTE (en el idioma OAuth) ...

    
respondido por el pfust75 22.09.2014 - 09:29
fuente

Lea otras preguntas en las etiquetas