OAuth 2.0. Nueva autenticación API Business Central con AL - Business Central

Breaking

lunes, 28 de diciembre de 2020

OAuth 2.0. Nueva autenticación API Business Central con AL

 nivel: developer

Manejar OAuth 2.0 desde AL



A estas alturas todos hemos visto la famosa notificación que aparece en la nueva versión 17.2 de Business Central acerca de la próxima desaparición de la autenticación BASIC.

Eso nos va a llevar a refactorizar (otra vez) los accesos API que ya teníamos funcionando con autenticación Basic y cambiarlas a OAuth 2.0.

La versión 17 de Business Central incorpora una nueva codeunit llamada OAuth2 que permite manejar esta nueva autenticación:


¿Qué es la autenticación OAuth?

Se trata de una autenticación que te permite publicar información mediante API, sin compartir totalmente nuestras password (como sí teníamos que hacer con la Basic), dejando que la autorización la suministre otro servidor, en nuestro caso Azure Active Directory.


El flujo para hacer una llamada a una API sería:

1- Solicito las credenciales a Azure Active Directory y éste, si son correctas me devuelve un token (o si prefieres, lo puedes llamar una clave válida temporal)

2- Con ese Token recibido, ya puedo acceder a los datos publicados.

Registrar una aplicación

Para registrar una API a la que luego podamos acceder con autenticación OAuth 2.0, debemos hacerlo en https://portal.azure.com/

Ya hay varios post donde nos indican como hacerlo, por ejemplo el de Olister Rumao por lo que vamos a suponer que ya lo tenemos claro.  Si consideráis que sería mejor tenerlo en Español, lo podéis comentar y lo preparo. 

Una vez registrado, tendremos varias cosas que son imprescindibles:


Nombre de la aplicación: API_BC

clientID : un número que nos genera la aplicación y que la identifica univocamente.

Tenant: el tenant donde está publicada la API (habitualmente será vuestro tenant de Business Central)

ClientSecret.  Se trata de la contraseña que nos habrá generado Azure para acceder a la aplicación.

Con toda esta información ya podrías probar en Postman o en Insomnia, pero nosotros aquí vamos directos a vscode y AL.

Obteniendo el Token desde AL

Voy a crear una página y una codeunit para probar la autenticación OAuth 2.0:



He creado una función en una codeunit para obtener el Token, basándome en la codeunit OAuth y la llamo desde una acción de la página (Solicita Token):


La función recibe como parámetros los que hemos visto antes:

ClientID: El identificador de la aplicación que voy a llamar, obtenido de Azure > Registro de aplicaciones > información general

ClientSecret: La contraseña que nos suministra la aplicación de Azure > Certificados y Secretos

MicrosoftOuth2Url: La dirección URL que nos permitirá autenticar a un usuario de Business Central.  También la podemos obtener del registro de la aplicación de Azure: 


AccessToken: Es una variable pasada por referencia donde guardaremos nuestro token.

AuthError: Es una variable pasada por referencia donde guardaremos si ha habido algún error.

Detalle de la función:

Línea 17: Ponemos la dirección de retorno para cuando ya estemos autenticados: a donde debería ir.

Línea 19: En scopes, almacenamos los permisos que estemos dando a la aplicación dentro de Business Central. 

Línea 21. LLamamos a la función de la codeunit OAuth que permite obtener el token de la cache, en caso de que no hubiese expirado todavía:

 OAuth2.AcquireAuthorizationCodeTokenFromCache

En el caso de que no tengamos Token en la cache, entonces debemos solicitarlo (línea 25) con la llamada a la función AcquireTokenByAuthorizationCode.  Para lo cual, nos abrirará una pantalla de autenticación que será la indicada en MicrosoftOuth2Url.


Al insertar nuestro usuario y contraseña, nos solicitará los permisos necesarios:


Una vez aceptado, Azure nos ha generado el Token que luego usaremos para conectar a la API:


Ahora que ya disponemos del Token, podemos incorporarlo para hacer la llamada a la API.


Línea 66: La URL de la API a la que vamos a llamar.  Recuerda que incluirá el tenant de nuestra aplicación.

Linea 68 y 69.  Incorporamos al mensaje http, tanto el método (en este caso un GET puesto que vamos a obtener información de la API), como la url.

Línea 70.  Aquí incluimos la autorización.  Recuerda que al ser OAuth, tiene que ser Bearer, junto con el token obtenido previamente.

Línea 71.  Le indicamos que vamos a recibir un JSON como respuesta.

Línea 73.  Hacemos la llamada propiamente, obteniendo la respuesta en la variable ResponseMessage.

Línea 74 a 80.  Gestionamos la respuesta, devolviendo el JSON de respuesta o bien el error obtenido.

Como podemos observar en el campo Respuesta, tenemos el JSON con la información procedente de la API.

Conclusion

Dado que la autenticación Basic va a desaparecer en la próxima versión, debemos de prepararnos para poder trabajar con la autenticación OAuth, cuanto antes mejor.

En este caso he utilizado una autenticación persona - máquina donde al final, alguien debe introducir las credenciales.  En un próximo post trataré como acceder de máquina-máquina sin intervención humana, que mayoritariamente es lo que usamos cuando tratamos de llamar a una API en procesos automáticos.

Cualquier duda, como siempre, dejad un mensaje aquí o bien en los medios habituales.






9 comentarios:

Aitor dijo...

Buenos dias Roberto,

Gran blog, desoués de darle unas vueltas ya voy viendo la luz, al menos en la parte que nos concierne que es BC.

Pero me surge una duda. Lo haces todo de forma interna. Es decir, BC llama a azure, obtiene el token, y BC consume dicho token llamando a un servicio. Pero este entorno no es del todo "real", ya que lo lógico seria que fuera un servicio externe el que quiere consumir un servicio de BC, no? Es decir, la funcion GetAuthorizationCodeToken deberia esta publicada como WS para ser accesible desde fuera.

Muchas gracias

Roberto Corella dijo...

Hola Aitor,

Realmente el próposito aquí era llamar de un BC a otro BC, por lo que es así como funcionaba. Si lo que quieres es llamar desde una aplicación externa, el obtener el token lo tiene que hacer es aplicación. No es necesario publicar esa función, puesto que el que llama (la app externa) es el que tiene que conseguir el token.

Aitor dijo...

Buenos dias Roberto,

Entiendo lo que me comentas. Pero en tal caso, como obtendria la aplicacion externa el token? Yo entiendo que haria 2 llamadas a BC no? La primera para obtener el token, y la segunda para llamar la la funcion que realmente quiere ejecutar. Aunque esto es como la pescadilla que se muerde en la cola, ya que la funcion que devuelve el token, tendria que estar publicada, y para ello, llamarcon el token...
Creo que mi teoria hace aguas, espero poder encontrar algun ejemplo de como lo haria una aplicacion externa...

Muchas gracias!

Roberto Corella dijo...

Buenos días Aitor,

La llamada al token se haría mediante la función correspondiente en el lenguaje utilizado y a la entidad certificadora (en este caso el que suministra el token no es BC es office365 o Azure). A ver si monto un ejemplo con Visual Studio.

Mireia dijo...

Buenos días Roberto,

Me ha resultado muy esclarecedor, genial! después de mirar muchos sitios aquí me ha resuelto dudas, estupendo! Me podrías indicar el link donde está publicado esto que comentas: En un próximo post trataré como acceder de máquina-máquina sin intervención humana... te lo agradecería muchísimo.

Roberto Corella dijo...

Buenos días Mireia,

no me ha dado tiempo de escribir el blog todavía. Lo tengo probado pero no lo he documentado. En cuando lo escriba pondré el link aquí.

gonzalo dijo...

buenas tardes Roberto, entonces..

¿No puedes conseguir el token a menos que registres BC SaaS en el AAD?. O lo que es lo mismo, no se podrá acceder a los OData si no hacemos esto primero.

Un saludo.

gonzalo dijo...

buenos días Roberto...

¿No hay ninguna manera de obtener el token a menos que registres tu BC SaaS en AAD?, me refiero a obtener el token directamente desde BC, y pasarlo a un App externa con el objetivo de la integración mediante APIs.

Un saludo.

Roberto Corella dijo...

Gracias Gonzalo por leer mi blog.

Efectivamente, a partir de la versión del próximo abril, ya no se podrá acceder mediante clave web. Deberá ser por OAuth y para hacerlo, deberás obtener un token registrando tu aplicación y dándole permisos. Aquí puedes ver un ejemplo de como hacerlo https://blog.dynasoft.es/2021/07/OAuth20BusinessCentral.html

Un saludo