OAuth2: recuperar access_token y evitar login si es válido
Tenemos un servidor OAuth configurado como proveedor de identidades, y tenemos una aplicación externa (de otro proveedor) que se conecta correctamente con el OAuth.
Por necesidades del proyecto, lo que queremos hacer es lo siguiente:
- Si el usuario no está autenticado, mostrar la página de login del OAuth, que haga el login y que le redirija a la aplicación de terceros --> Esta parte funciona
- Si el usuario ya está autenticado (ya ha iniciado sesión y ya tiene un access_token válido), que exista una cookie con el access_token generado en el login, y al entrar a la URL de la aplicación de terceros, en lugar de mostrar el login del OAuth, si el access_token es válido, redirigirle directamente a la aplicación de terceros --> Esta parte es la que no conseguimos hacer funcionar
Qué tenemos?
- Hemos creado una clase custom "test.oauth.server.Authenticate" que extiende de %OAuth2.Server.Authenticate.
- Hemos añadido el método BeforeAuthenticate. Aquí somos capaces de leer las cookies de la petición, encontrar la que hemos creado, obtener el access_token, validarlo y obtener el token como tal:
Include Ensemble
Class test.oauth.server.Authenticate Extends%OAuth2.Server.Authenticate
{
ClassMethod BeforeAuthenticate(scope As%ArrayOfDataTypes, properties As%OAuth2.Server.Properties) As%Status
{
$$$LOGINFO("Entrando en BeforeAuthenticate")
set currentNS = $NamespaceSet httpRequest = %requestSet tokenCookie = httpRequest.GetCookie("SessionToken")
If tokenCookie '= "" {
$$$LOGINFO("Token encontrado en Cookie: "_tokenCookie)
// Llamar manualmente a GetAccessToken con el token de la cookieIf..GetAccessToken(tokenCookie) {
Set isValid = ##class(%SYS.OAuth2.Validation).ValidateJWT("ValidarToken", tokenCookie, , , .jsonObject, .securityParameters, .sc)
$$$LOGINFO(isValid_" ("_sc_"): "_$System.Status.GetErrorText(sc))
$$$LOGINFO(jsonObject.%ToJSON())
set$Namespace = "%SYS"Set token=##class(OAuth2.Server.AccessToken).OpenByToken(tokenCookie,.sc)
set$Namespace = currentNS
$$$LOGINFO(token_" ("_sc_"): "_$System.Status.GetErrorText(sc))
Quit1// Continuar sin mostrar login
} Else {
$$$LOGINFO("GetAccessToken rechazó el token")
Quit$$$OK
}
}
$$$LOGINFO("No se encontró token en Cookie")
Quit$$$OK
}
ClassMethod GetAccessToken(ByRef AccessToken As%String) As%Boolean
{
$$$LOGINFO("Entrando en GetAccessToken")
// Si ya recibimos un token desde BeforeAuthenticateIf AccessToken '= "" {
// Token recibido en GetAccessToken// Llamar a la función de validación de tokenSet sc = ##class(%SYS.OAuth2.Validation).ValidateJWT("ValidarToken", AccessToken, , , .jsonObject, .securityParameters)
Set user = jsonObject.sub
$$$LOGINFO("Token válido. Usuario: "_user)
If user '= "" {
$$$LOGINFO("Usuario autenticado: "_user)
Quit$$$OK
} Else {
$$$LOGINFO("El usuario está vacío.")
Quit0// Retorna 0 si el usuario es vacío
}
}
Quit0// Asegúrate de retornar 0 si no se obtiene el token
}
}Pero sea como sea, aunque tengamos el access_token, abramos el objeto Token del OAuth, etc, sigue mostrando el login. Creemos que nos falta algo, pero no sabemos el qué...
Qué podemos hacer? Alguna idea?
Gracias!
Comments
¿Es posible que estéis almacenando la cookie en el explorador de internet pero no la estéis enviando al servidor de OAuth en la request?
La cookie llega, conseguimos leerla con esta instrucción:
Set tokenCookie = httpRequest.GetCookie("SessionToken")El nombre es inventado, no sé si quizá esté ahí el problema... O si se debe generar una cabecera o alguna historia para que funcione.
Lo que no sabemos es qué hacer una vez leída la cookie y obtenido el token.
Buenas @Laura Blázquez García, no soy muy experto en temas de OAuth2 pero quizás este artículo os pueda resultar de utilidad:
https://community.intersystems.com/post/oauth-authorization-and-intersy…
Finalmente encontramos una solución. Mi colega @Miguelio lo resolvió. Lo ha documentado, así que aquí dejo el enlace: https://es.community.intersystems.com/post/persistencia-de-sesi%C3%B3n-…