Ejemplo de Implicit Flow de OAuth 2.0

Si tu aplicación no es capaz de guardar un secreto, porque esta se ejecuta completamente en el lado del cliente, Implicit Flow es lo que necesitas. En este artículo vamos a ver un ejemplo práctico, al igual que vimos con Authorization Code Flow. De hecho, vamos a llamar al mismo recurso protegido, pero esta vez utilizando este flujo.

Configuración del servidor de autorización

Al igual que en el flujo anterior, antes de poder recuperar un token, necesitas registrar tu aplicación cliente en el servidor de autorización. En este ejemplo también usaré Azure Active Directory.

Entra en el portal de Microsoft Azure, accede a Azure Active Directory y haz clic en la sección App registrations (Preview).

Azure Active Directory – App registrations – preview

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 dentro de Azure Active Directory. Dejaremos el tipo de cuentas soportadas por defecto, que son las del propio directorio y, como Redirect URI, añadiremos la siguiente: http://localhost:8000/give/me/the/access/token

También necesitamos recuperar el Application (client) ID y el Directory (tenant) ID.

Y sólo el endpoint de autorización, ya que en este caso es él el que nos devolverá el token. Puedes recuperarlo en el apartado Endpoints, justo encima de donde conseguiste el client ID.

En este ejemplo, vamos a utilizar el mismo scope que usamos para el Authorization Code Flow: https://graph.microsoft.com/User.Read. Este puedes encontrarlo en API permissions.

Ya que este flujo está pensado para clientes públicos, es decir que no son capaces de almacenar un secreto sin que este sea “descubierto”, no necesitamos generar ninguna clave. Sin embargo, lo que sí necesitamos es habilitar el Implicit Flow en el apartado Authentication.

Por ahora sólo estamos trabajando con access tokens, no con id_tokens, que pertenecen a OpenID Connect. Por lo que selecciona solo el primer check para habilitar Implicit Flow para nuestra aplicación.

Ya tienes todo lo que necesitas para solicitar un token de acceso desde tu cliente y llamar a la API protegida.

El cliente

En Implicit Flow, como es normal, la parte de servidor se reduce notablemente:

//Modules
const express = require('express');

const app = express();

app.use(express.static('public'));

app.set('view engine', 'ejs');

app.get('/', (req, res) => {
    res.render('index');
});

app.get('/give/me/the/access/token', (req, res) => {
    res.render('access-token');
});

app.listen(8000);

Como puedes ver, sólo la necesito para tener un servidor local en el puerto 8000, pero toda la lógica está en el lado del navegador.

Página index

Al igual que en el otro ejemplo, he intentado no utilizar ninguna librería que me oculte los pasos que necesito para recuperar el token de acceso en este flujo. En la página de inicio, tengo un enlace con forma de botón, que me va a permitir ir al servidor de autorización para iniciar sesión y aceptar el consentimiento.

El enlace tiene el siguiente aspecto:

<a href="https://login.microsoftonline.com/TENANT_ID/oauth2/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=http://localhost:8000/give/me/the/access/token&scope=https://graph.microsoft.com/User.Read&resource=https://graph.microsoft.com/&state=ThisIsMyStateValue" class="btn btn-primary">Go to the authorization server</a>

Si recuerdas, el endpoint que recuperamos al inicio era el de autorización. A este debemos añadirle los siguientes parámetros al query string:

  • response_type: En este flujo debe ser del tipo token.
  • client_id: El id de la aplicación registrada, en este caso en Azure Active Directory.
  • redirect_uri: La URL que registraste en Azure AD, que en nuestro caso fue http://localhost:8000/give/me/the/access/token
  • scope: Al igual que en el ejemplo anterior, utilizamos el scope que se asigna por defecto al registrar la aplicación, que es https://graph.microsoft.com/User.Read
  • resource: en Implicit Flow, además de indicar cuál es el scope, debemos especificar el recurso al que queremos acceder, que en este caso es https://graph.microsoft.com/
  • state: como vimos en el artículo de introducción a OAuth 2.0, el valor de state se utiliza para comprobar que no se ha visto comprometida la respuesta del servidor. No es obligatorio, pero es recomendado.

En el servidor de autorización deberás de iniciar sesión y aceptar los permisos que la aplicación está pidiendo.

Azure AD – Implicit Flow – Permissions requested

Una vez hecho esto, se te redirigirá a la URL que indicaste en Redirect URI, en este caso http://localhost:8000/give/me/the/access/token, con el access token de vuelta.

Página access token

Al llegar a esta página, verás que en la URL de la misma se encuentra el access token que el servidor de autorización te ha dado:

Ahora lo único que te queda es recuperar el token de la URL y hacer la llamada a la API protegida, en este caso Microsoft Graph API.

<script>
        function getParameterByName(name) {
            var match = RegExp('[#&]' + name + '=([^&]*)').exec(window.location.hash);
            return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
        }

        $(function () {
            var access_token = getParameterByName('access_token');

            document.getElementById('access_token').innerText = access_token;

            // Use the Access Token to make API calls

            $("#btnCallAPI").click(async () => {

                var result = document.getElementById('result');

                const Microsoft_Graph_Endpoint = 'https://graph.microsoft.com/beta';
                const Acction_That_I_Have_Access_Because_Of_My_Scope = '/me';

                fetch(`${Microsoft_Graph_Endpoint}${Acction_That_I_Have_Access_Because_Of_My_Scope}`, {
                    headers: {
                        'Authorization': `Bearer ${access_token}`
                    }
                }).then(async response => {

                    let json = await response.json();
                    console.log(json);
                    result.innerHTML = JSON.stringify(json, undefined, 2);

                }).catch(error => {
                    result.innerHTML = JSON.stringify(json, undefined, 2);
                    console.error(error);
                });

                result.style.display = 'block';

            });
        });

    </script>

Al hacer clic en el botón Call Microsoft Graph API llamará a la misma API que vimos en Authorization Code Flow, pasándole el token recuperado de la URL.

Llamada a Microsoft Graph con el token de la URL

El código completo lo tienes en mi GitHub.

¡Saludos!