Ejemplo de Authorization Code Flow de OAuth 2.0
Actualizado el 25/04/2021
Después de la explicación, viene el ejemplo
Ahora que ya sabes todos los flujos que existen a día de hoy, ahora quiero ver contigo cada uno de los flujos a través de un ejemplo.
No he querido utilizar ninguna librería para estos artículos. Como el objetivo es saber cómo funcionan, he querido evitar todo aquello que me oculte lo que está pasando realmente. La idea es basarme en los conceptos que te conté en el artículo anterior. Hoy vamos a ver el flujo Authorization Code y, para ello, vamos a trabajar con los siguientes componentes:
- Recurso protegido (Protected Resource): Microsoft Graph API
- Cliente (Client): aplicación en Node.js con Express de back end.
- Usuario (Resource Owner): yo misma
- Servidor de autorización: Azure Active Directory
Configuración del servidor de autorización
Antes de que nuestro cliente sea capaz de pedir un token, para llamar al recurso protegido, primero es necesario registrar nuestro cliente en el servidor de autorización, en este caso Azure Active Directory.
Entra en el portal de Microsoft Azure, accede a Azure Active Directory y haz clic en la sección App registrations.
Ahora haz clic en el botón New registration del menú, para registrar nuestra futura aplicación cliente. Los valores que debes introducir son los siguientes:
- Name: se trata de un nombre identificativo del cliente dentro de Azure Active Directory.
- Supported account types: Azure Active Directory te permite que los usuarios que se autentiquen, utilizando esta aplicación, sean del directorio activo en el que nos encontramos, de cualquier directorio activo de Azure AD o bien utilizando Microsoft Accounts. Para este ejemplo dejaremos la opción por defecto, que es la primera.
- Redirect URI: tal y como te comenté en el artículo anterior, es necesario registrar una URL de nuestro sitio, para ser redirigidos cuando la autenticación y el consentimiento del usuario hayan concluido de manera satisfactoria. En este caso mi redirect uri será http://localhost:8000/give/me/the/code
Haz clic en Register en la parte inferior de la pantalla. Con esto, ya tenemos la aplicación registrada en el servidor de autorización. Sin embargo, antes de marcharte necesitamos recuperar algunos valores de aquí:
En primer lugar necesitamos recuperar el Client Id que nos ha asignado este servidor de autorización, al registrar nuestra aplicación. Cuando hiciste clic en el botón Register, este nos llevo al apartado Overview del nuevo registro. En él puedes encontrar el Client Id llamado Application (client) ID.
Otra de las cosas que el cliente necesitaba conocer eran los endpoints para la autorización y para la recuperación del token. Estos puedes encontrarlos haciendo clic en Endpoints.
Para OAuth 2.0 necesitamos los dos primeros. Si te fijas, tal y como vimos en el apartado endpoints del artículo anterior, uno de ellos es el de autorización (/authorize) y el otro el que nos dará el token (/token).
Lo siguiente que necesitamos es identificar qué scope queremos para Microsoft Graph, o lo que es lo mismo: qué acciones queremos ejecutar de esta. Estos son propios de cada API, por lo que necesitamos conocer los que ofrece cada una. Los scopes a los que tiene acceso una aplicación se encuentran en la sección API Permissions.
Cuando registras tu aplicación en Azure Active Directory se te asigna uno por defecto que es User.Read de la API de Microsoft Graph. Para este ejemplo es más que suficiente. Si quisieras añadir más puedes hacerlo a través del botón Add a permission.
Para finalizar, necesitamos generar un secreto, ya que en el flujo Authorization Code es necesario a la hora de intercambiar el código de autorización por un token de acceso. En la sección Certificates & secrets haz clic en New client secret. Elige un año como tiempo de expiración del mismo y haz clic en Add.
Ahora ya tenemos todo lo necesario para crear nuestro cliente y llevar a cabo este flujo.
El cliente
Como te decía, he desarrollado la aplicación en Node.js, sin ninguna librería que me ayude con el flujo de OAuth 2.0. He conseguido que todo ocurra en 100 líneas y que sea lo más legible posible
Cada uno de los pasos del flujo lo he ido acompañando de un paso a paso en el lado del cliente, para que puedas ir viendo el resultado. Nunca debes compartir con el lado del cliente el access token, ya que entonces pierde toda la gracia
En este ejemplo lo hago solo por motivos educativos.
Puedes descargar el ejemplo completo desde mi GitHub y lanzar npm start para ejecutarlo en http://localhost:8000.
Para que este ejemplo funcione crea un archivo .env y añade las siguiente variables con los siguiente valores:
Explicación del código fuente
Paso 1: Conseguir el código de autorización
Para obtener el código debemos redirigir al usuario al servidor de autorización, donde tendrá que iniciar sesión y aceptar el consentimiento. Normalmente esta acción se suele hacer con un enlace o un botón, como se ve en la imagen anterior. Al hacer clic en él se ejecuta el paso 1 del servidor:
Lo que hacemos en él es recuperar todos los valores que debemos adjuntar a la redirección que vamos a hacer al servidor de autenticación, en este caso Azure Active Directory. Concatenamos todo y utilizamos res.redirect para redirigir al usuario. Una vez allí, deberás iniciar sesión con un usuario de tu directorio y aceptar los permisos que solicita el cliente.
Cuando el proceso de autenticación finalice, serás redirigido de nuevo a la aplicación utilizando la URL http://localhost:8000/give/me/the/code
Paso 2: Recuperar el código de la URL
Cuando eres redirigido a http://localhost:8000/give/me/the/code, por parte del servidor de autorización, este añade como query string el código de autorización y el state. Es nuestra labor recuperar ambos valores, como se ve en el paso 2:
Lo normal es que el back end cambie este código por un token nada más recibirlo, además de comprobar que el valor de state es el mismo que él envió. Sin embargo, en este ejemplo lo estoy enviando a una vista llamada exchange-code para ver el contenido en la web, siempre con fines educativos:
Paso 3: Cambiar el código por el token de acceso
Cuando haces clic en el botón Exchange the code for an access token lo que ocurre es justo eso:
Creamos el cuerpo de una llamada POST al endpoint /token con todos los valores que indica la especificación: el grant_type es authorization_code, el código de autorización que hemos recuperado, de nuevo la redirect_uri, el client id, el client secret (que en este flujo es obligatorio) y el scope. Si todo está correcto, el servidor nos devolverá un token como este:
Paso 4: Llamar al recurso protegido con el token de acceso
Ya tenemos todo lo que necesitamos para poder llamar al recurso protegido, en este caso a la API de Microsoft Graph. Gracias a OAuth 2.0 esta API tiene bien delimitado qué se puede hacer y qué no gracias a los Scopes, por lo que no podemos llamar a cualquier acción de Microsoft Graph. Con el scope User.Read sólo podemos leer información de nosotros mismos, y eso es lo que hacemos en el paso 4 del código.
Si haces clic en el botón Call Microsoft Graph API podrás ver el resultado de esta llamada.
El código completo lo tienes en mi GitHub.
¡Saludos!