Pregunta
· 25 nov, 2022

Desde un Entorno de INTEGRACION conectar a otro de PREPRODUCCION para acceder al Servidor de Recursos que Valida Token JWT

Buenos días,

Hemos estado indagando de qué manera activar un Servidor para Generar Tokens y un Servidor de Recursos asociado para Validar el Token. Este paso, actualmente lo hemos averiguado con el inestimable apoyo de @Alberto Fuentes de Intersystems.

A continuación la necesidad es la siguiente: Para centralizar en 1 único Entorno ( PREPRODUCCION ) y en 1 único Namespace el Servidor de Recursos ( por ejemplo en un NAMESPACE dedicado llamado AUTHSERVER ) ; necesitaríamos de alguna manera "llamar", "invocar", "comunicar" desde los otros entornos ( por ejemplo INTEGRACION ) con el Servidor de Recursos de PREPRODUCCION con el fin de Validar el Token.  ¿Por favor, ustedes nos podrían orientar, guiar, pautar, instruir al respecto?

📍¿Qué vía existe para "llamar", "invocar", "comunicar" desde los otros entornos ( por ejemplo INTEGRACION ) con el Servidor de Recursos de PREPRODUCCION con el fin de Validar el Token?

En concreto, disponemos en Integracion de un Servicio REST llamado "Servicios.REST.Radiologia.CConcertadosv01r00", y dentro un método denominado "ResServer". Nuestras pesquisas nos han llevado a profundizar en el siguiente código:

ClassMethod ResServer(accessToken As %String(MAXLEN="")) As %Status
{
$$$LOGINFO("Entra en método ResServer")
    // This is a dummy resource server which just gets the access token from the request
    // and uses the introspection endpoint to ensure that the access token is valid.
    // Normally the response would not be security related, but would contain some interesting
    // data based on the request parameters.
    
    // retrieve access token from HTTP request
    ;set accessToken = ##class(%SYS.OAuth2.AccessToken).GetAccessTokenFromRequest(.status) /*
    if $$$ISERR(status) {
        set %response.Status = ..#HTTP401UNAUTHORIZED
        write "[Error] GetAccessTokenFromRequest: "_$system.Status.GetErrorText(status),!
        quit $$$OK
    }
    */ $$$LOGALERT("Antes de set isJWTValid = ##class(%SYS.OAuth2.Validation).ValidateJWT('resserver',accessToken,'','',.jwtPayload ,.securityParameters,.sc)")
    // validate token
    ;set isJWTValid = ##class(%SYS.OAuth2.Validation).ValidateJWT("resserver",accessToken,"","",.jwtPayload ,.securityParameters,.sc)
    set isJWTValid = ##class(%SYS.OAuth2.Validation).ValidateJWT("https://[Servidor de PRE]:57773/resserver/",accessToken,"","",.jwtPayload ,.securityParameters,.sc)
    $$$LOGALERT("Despues de isJWTValid ... apuntando a https://[Servidor de PRE]:57773/resserver/")
            
    $$$LOGINFO("Antes de if (('isJWTValid) || ($$$ISERR(sc))) {")
    $$$LOGINFO("Imprimir ('isJWTValid): "_('isJWTValid))
    $$$LOGINFO("Imprimir ($$$ISERR(sc): "_($$$ISERR(sc)))
    $$$LOGINFO("Imprimir $system.Status.GetErrorText(sc): "_$system.Status.GetErrorText(sc))
    if (('isJWTValid) || ($$$ISERR(sc))) {
    /*
        set %response.Status = ..#HTTP401UNAUTHORIZED
        write "Error Getting Access Token="_$system.Status.GetErrorText(sc),!
        */
        quit '$$$OK
    } $$$LOGINFO("Antes de set sc = ##class(%SYS.OAuth2.AccessToken).GetIntrospection('resserver', accessToken, .jsonObject)")
    // introspection
    set sc = ##class(%SYS.OAuth2.AccessToken).GetIntrospection("resserver", accessToken, .jsonObject)
    if $$$ISERR(sc) {
    /*
        set %response.Status = ..#HTTP401UNAUTHORIZED
        write "Introspection Error="_..EscapeHTML($system.Status.GetErrorText(sc)),!
        */
        quit '$$$OK
    }
    
$$$LOGINFO("Antes de write 'OAuth 2.0 access token used to authorize resource server (RFC 6749)<br>'")
/*
    write "OAuth 2.0 access token used to authorize resource server (RFC 6749)<br>"
    write "Access token validated using introspection endpoint (RFC 7662)<br>"
    write " scope='"_jsonObject.scope_"'<br>"
    write " user='"_jsonObject.username_"'",!
    */
    
    $$$LOGINFO("Antes del final quit $$$OK")
    quit $$$OK
}

Seguidamente nuestras indagaciones nos llevan a:

Ésta línea si llama desde PREPRODUCCION al Servidor de Recursos de PREPRODUCCION y Valida el Token de manera correcta:

set isJWTValid = ##class(%SYS.OAuth2.Validation).ValidateJWT("resserver",accessToken,"","",.jwtPayload ,.securityParameters,.sc)

Sin embargo si nosotros tratamos invocar desde INTEGRACION al Servidor de Recursos de PREPRODUCCION calificando el primer parámetro, el "client" con la Dirección completa del Servidor de Recursos de PRE ; da Excepción:

set isJWTValid = ##class(%SYS.OAuth2.Validation).ValidateJWT("https://[DNS de PRE]:57773/resserver/",accessToken,"","",.jwtPayload ,.securityParameters,.sc)

En particular la Excepción que observamos en los LOGS del Servicio REST es:

ERROR #5002: Error de cache: <UNDEFINED>zValidateJWT+22^%SYS.OAuth2.Validation.1 *client

Lo cual parece que se debe al hecho de que en la función interna de la clase: "%SYS.OAuth2.Validation" titulada: "ValidateJWT" ; en la llamada "Set client=##class(OAuth2.Client).Open(applicationName,.sc)"

 

Se genera una Excepción basada en el hecho de que le cuesta abrir el Servidor de Recursos; en la clase: OAuth2.Client en el método Open en la línea Set client=##class(OAuth2.Client).%OpenId(applicationName,,.sc)

¿Por favor, ustedes nos podrían orientar, guiar, pautar, instruir al respecto?

📍 La cuestión es ¿Qué vía existe para "llamar", "invocar", "comunicar" desde los otros entornos ( por ejemplo INTEGRACION ) con el Servidor de Recursos de PREPRODUCCION con el fin de Validar el Token?

 

Muchísimas gracias de antemano a ustedes por su tiempo, apoyo y auxilio.

 

 

Un saludo

Product version: IRIS 2020.1
$ZV: IRIS for UNIX (Red Hat Enterprise Linux for x86-64) 2020.1.1 (Build 408U) Sun Mar 21 2021 22:21:14 EDT
Comentarios (3)2
Inicie sesión o regístrese para continuar

Adicionalmente hemos leído con atención:

https://docs.intersystems.com/healthconnectlatest/csp/docbook/DocBook.UI...

https://docs.intersystems.com/healthconnectlatest/csp/docbook/DocBook.UI...

https://docs.intersystems.com/healthconnectlatest/csp/docbook/DocBook.UI...

https://docs.intersystems.com/healthconnectlatest/csp/docbook/DocBook.UI...

https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI...

https://community.intersystems.com/post/making-jwtoauth20

Sin embargo, sí seguimos con la misma cuestión:

¿Qué vía existe para "llamar", "invocar", "comunicar" desde los otros entornos ( por ejemplo INTEGRACION ) con el Servidor de Recursos de PREPRODUCCION con el fin de Validar el Token?

Es decir la pregunta de otra forma sería:

¿Qué mecanismo existe para desde un Entorno A (Integración) se comunique con un Entorno B (Preproducción) con la misión de Validar el Token desde el Entorno A empleando el Servidor de Recursos centralizados disponible en el Entorno B?

Muchísimas gracias por su atención, y gracias por sus respuestas.

Un saludo
 

Hola Yone,

Entiendo que quieres montar lo siguiente:

  • Cliente externo (e.g. Postman) que solicite token a servidor de autorización.
  • Servidor de autorización en PREPRODUCCIÓN.
  • Servicio REST en INTEGRACIÓN que actúe como servidor de recursos, que reciba y valide el token.

En principio estás en un escenario como el de Client Credentials del workshop-iris-oauth2.

En resumen, tendrías que configurar lo siguiente:

  • Definir servidor autorización OAuth en PREPRODUCCIÓN.
  • Registrar cliente en servidor de autorización en PREPRODUCCIÓN: tendrás ClientID y ClientSecret. Lo necesitarás para solicitar token.
  • Definir servidor de recursos en INTEGRACIÓN como se hacía en este paso.
    • Cuando defines el servidor de recursos, tienes que indicar cuál es el endpoint del servidor de autorización.
    • Tienes que asignarle un nombre, e.g. "resserver"
    • En el código del servidor de recursos, en INTEGRACIÓN, en el método ValidateJWT sólo necesitas referirte al nombre que le hayas puesto al servidor de recursos (e.g. "resserver").
    • El método ValidateJWT ya se encarga de utilizar tu definición de servidor de recursos "resserver", donde tenías el endpoint del servidor de autorización, y validar el token que le pases.