javascript - implementar - Flujo implícito de Oauth2 con tokens de acceso de actualización de una sola página
oauth2 java (4)
Estoy usando Thinktecture AuthorizationServer (AS) y está funcionando muy bien.
Me gustaría escribir una aplicación de página única javascript nativa que pueda llamar directamente a una WebAPI, sin embargo, el flujo implícito no proporciona un token de actualización.
Si se realiza una llamada AJAX, si el token ha caducado, la API enviará un redireccionamiento a la página de inicio de sesión, ya que los datos están utilizando ventanas emergentes dinámicas, esto interrumpirá al usuario.
¿Cómo hace esto Facebook o Stackoverflow y aún permite que el javascript que se ejecuta en la página llame a las API?
Solución propuesta
¿El siguiente escenario suena sensato (suponiendo que esto se puede hacer con iframes):
Mi SPA me dirige al AS y obtengo un token de Implicit Flow. Dentro de AS, hago clic en Permitir Read data
alcance de Read data
, y luego en Remember decision
, luego en Allow
.
Desde que hice clic en el botón Remember decision
, cada vez que presiono AS para un token, un token nuevo se devuelve automáticamente sin necesidad de iniciar sesión (puedo ver una cookie FedAuth que recuerda mi decisión y creo que esto permite que esto funcione) .
Con mi SPA (aplicación que no es de confianza), no tengo un token de actualización solo un token de acceso. Así que en vez yo:
- Asegúrese de que el usuario haya iniciado sesión y haya hecho clic en recordar decisión (de lo contrario, iframe no funcionará)
- Llame a WebAPI, si la respuesta del 401 intente y obtenga un nuevo token siguiendo los pasos a continuación ...
- Tener un iframe oculto en la página, que estableceré la URL para obtener un nuevo token de acceso del servidor de autorización.
- Obtenga el nuevo token del fragmento hash del iframe, luego guárdelo en el SPA y utilícelo para todas las futuras solicitudes de WebAPI.
Supongo que todavía estaría en problemas si me roban la cookie de FedAuth.
¿Alguna forma estándar o recomendada para el escenario anterior?
En Google o-Auth, el token de acceso solo será válido durante 1 hora, por lo que debe actualizar su token de acceso de manera programática en cada hora, puede crear una API web para hacerlo, necesita tener un token de actualización y además, ese token de actualización no caducará, utilizando el código c #, he hecho esto.
if (dateTimeDiff > 55)
{
var request = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/oauth2/v3/token");
var postData = "refresh_token=your refresh token";
postData += "&client_id=your client id";
postData += "&client_secret=your client secrent";
postData += "&grant_type=refresh_token";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
request.UseDefaultCredentials = true;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
debe guardar la última fecha de actualización del token de acceso en algún lugar (por ejemplo, en la base de datos), de modo que, siempre que tenga que realizar una solicitud, pueda restarlo a la fecha actual, si es más de 60 minutos, Necesito llamar a los webapi para obtener un nuevo token.
Entiendo que su problema es que el usuario experimentará una interrupción cuando el token de acceso haya caducado, mediante una redirección a la página de inicio de sesión del servidor de autorización. Pero no creo que puedas y debas evitar esto, al menos, al usar la concesión implícita.
Como estoy seguro de que ya sabe, la subvención implícita debe ser utilizada por los consumidores que NO pueden mantener sus credenciales en secreto. Debido a esto, el token de acceso emitido por un servidor de autorización debe tener un ttl limitado. Por ejemplo, Google invalida su token de acceso en 3600 seg . Por supuesto, puede aumentar el ttl, pero nunca debe convertirse en un token de larga vida.
También hay que tener en cuenta que, en mi opinión, la interrupción del usuario es mínima, es decir, si se implementa correctamente, el usuario solo tendrá que autenticarse una vez con el servidor de autorización. Después de hacer eso (por ejemplo, la primera vez que también autoriza el acceso de la aplicación a los recursos que el usuario controla) se establecerá una sesión (basada en cookie o token) y cuando el token de acceso del consumidor (aplicación web utilizando subvención implícita) caduca, se notificará al usuario que el token ha caducado y se requiere autenticación de re con el servidor de autorización. Pero debido a que ya se ha establecido una sesión, el usuario será redirigido inmediatamente a la aplicación web.
Sin embargo, si esto no es lo que quieres, debes, en mi opinión, considerar usar la concesión del código de autorización, en lugar de hacer cosas complicadas con iframes. En ese caso, necesita una aplicación web del lado del servidor porque puede mantener sus credenciales en secreto y usar tokens de actualización.
No estoy seguro si entiendo tu pregunta pero
Me gustaría escribir una aplicación nativa de una sola página de JavaScript que puede llamar a una WebAPI directamente, sin embargo, el flujo implícito no proporciona un token de actualización.
Resumir los hechos,
el token de actualización a veces se usa para formar parte de A: Grant de autorización
https://tools.ietf.org/html/rfc6749#section-1.5
y como dijiste en flujo implícito , no obtienes token de actualización, pero solo en la parte Grant de Autorización
https://tools.ietf.org/html/rfc6749#section-4.2.2
para que pueda obtener el token de actualización al emitir el token de acceso (los tokens de actualización siempre son opcionales)
https://tools.ietf.org/html/rfc6749#section-5.1
Con mi SPA (aplicación que no es de confianza), no tengo un token de actualización solo un token de acceso. Entonces en cambio yo:
1) Asegúrese de que el usuario haya iniciado sesión y haga clic en recordar decisión (de lo contrario, iframe no funcionará)
2) Llamar a WebAPI, si la respuesta 401 prueba y obtener un nuevo token por los pasos a continuación ...
3) Tener un iframe oculto en la página, que estableceré la URL para obtener un nuevo token de acceso del Servidor de autorización.
4) Obtenga el nuevo token del fragmento de hash del iframe, luego almacénelo en el SPA y utilícelo para todas las futuras solicitudes de WebAPI.
1) SPA (usted) no tiene idea si el usuario seleccionado recuerda la decisión. Está en la dirección de AS y debe estar completo blackbox Omita este paso.
2) Puedes intentar usar el token de acceso y esperar el resultado, siempre.
3) Si el token de acceso ha caducado y no tienes el token de actualización, puedes crear un iframe oculto y tratar de obtener un nuevo token de acceso.
4) Supongamos que su AS brinda una opción para recordar la decisión y no la cambiará en el futuro, entonces: su iframe recibirá un nuevo token de acceso sin interacción del usuario, luego obtendrá un resultado en un límite de tiempo desconocido. El resultado puede verificarse mediante setInterval
para lectura de correspondencia específica de cookie o iframe. Si no recupera los datos en el límite de tiempo, se produce uno de los siguientes escenarios:
- lag, AS es lento, la conexión es lenta o el límite de tiempo es demasiado ajustado
- el usuario no seleccionó recordar la decisión
En este caso:
5) mostrar iframe con login
Considero que el escenario anterior es una buena práctica si AS no proporciona tokens de actualización, pero también creo que cada AS como ese no brindará la opción de recordar también.
<---> Escenario de Google (solo puedo adivinar)
1) Inicio de sesión de usuario, solicitud de autorización ocurrida
2) El usuario inicia sesión, SO obtiene el token de acceso
3) SO intenta usar el token de acceso
4) SO recupera el resultado + token de actualización
5) SO guarda token de actualización
6) SO tiene acceso permanente a la cuenta de Google de los usuarios
Parece que necesita hacer una cola de solicitudes en caso de que caduque un token de acceso. Esto es más o menos como Facebook y Google lo hacen. Una forma simple de usar Angular sería agregar un Interceptor HTTP y verificar las respuestas HTTP401. Si se devuelve uno, se vuelve a autenticar y pone en cola cualquier solicitud que ingrese después hasta que se complete la solicitud de autenticación (es decir, una promesa). Una vez hecho esto, puede procesar la cola pendiente con el token de acceso recién devuelto desde su solicitud de autenticación usando su token de actualización.
Feliz Codificación.