Enviar datos desde Arduino con nuestra API en Laravel y OAuth2

El objetivo de este post es compartir un experimento que estamos realizando en Charrúa para enviar datos con nuestro dispositivo IOT (internet of things) a una aplicación realizada con Laravel.

En primer lugar debes estar familiarizado con Laravel y el protocolo OAuth2 que será el utilizado para realizar las solicitudes de manera autenticada a nuestra API. El dispositivo que utilizaremos para este experimento será un Arduino MKR1000 y el entorno Arduino Web Editor.
Por si no conoces el entorno Arduino Web Editor, es lo que se utiliza con los nuevos modelos como el MKR1000 para programar y enviar el código al dispositivo mediante un ordenador.

El tipo de credencial que utilizaremos para enviar datos desde el dispositivo será «Client Credentials Grant Token». Es un tipo de credencial que normalmente se utiliza para autenticar una máquina con otra máquina (machine-to-machine). En este caso una de las máquinas sera nuestro dispositivo MKR1000 y la otrá será nuestra API.

Tabla de contenidos:

1- Crear aplicación Laravel
2- Conectar la base de datos
3- Instalar Laravel Passport
4- Crear cliente para acceder a la API mediante «Client Credentials Grant Tokens»
5- Crear y proteger ruta
6- Probar la API localmente
7- Cargar código a nuestro dispositivo MKR1000
8- Probar API y Arduino MKR en producción
9- Conclusión

1- Comenzaremos por crear nuestra aplicación Laravel:

laravel new IOTAuth

Hemos escogido «IOTAuth» para el nombre de nuestra aplicación, esto lo dejamos a tu criterio. Si tienes problemas para instalar Laravel puedes consultar la documentación: https://laravel.com/docs/5.8/installation#installation

2- Conecta la base de datos

Deberás ir al archivo .env en la raíz de tu aplicación y agregar las credenciales de tu base de datos. Recuerda sustituir los valores <nombre_bd>, <usuario_bd> y <contraseña_bd> por los que hayas creado.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nombre_bd
DB_USERNAME=usuario_bd
DB_PASSWORD=contraseña_bd

3- Instalaremos el paquete de autenticación OAuth2 para API’s – Passport

Laravel Passport es un paquete utilizado para añadir fácilmente autenticación a nuestra API. Este paquete provee una implementación total de OAuth2.

Para realizar la instalación seguiremos los pasos de la documentación:

a. Utilizaremos composer para la instalación del paquete, con el comando:

composer require laravel/passport

b. Realizaremos la migración:

php artisan migrate

La migración generará las tablas necesarias para que nuestra aplicación Laravel quede operativa. Entre ellas creará las tablas de passport y la tabla de usuarios.

c. Generación de claves e instalación:

Tendrás que ejecutar un comando encargado de crear las llaves de encriptación necesarias para generar los tokens de acceso. Este comando también generará dos clientes uno del tipo «personal access» y otro del tipo «password grant». Ignoraremos por el momento estas credenciales ya que ninguna nos interesa, recordemos la que queremos utilizar es para la comunicación de máquina a máquina (Client Credentials Grant Token).

php artisan passport:install

4- Generación del cliente para el tipo de credencial deseada: Client Credentials Grant Tokens

Antes de que nuestra aplicación pueda generar tokens, debemos generar el cliente. Pues bien, ahora debemos ejecutar el siguiente comando:

php artisan passport:client --client

Este comando nos preguntará el nombre para nuestro nuevo cliente, nosotros utilizamos «mkr1000_01» y al confirmar el nombre, nos dará como resultado en la propia consola el ID del cliente y una clave secreta.

What should we name the client? [Access ClientCredentials Grant Client]:
 > mkr1000_01

New client created successfully.
Client ID: 3
Client secret: qV524tNf2ofA6VsQCaqyBAPVayXCj0i4nIup1b

Desde la documentación de Laravel (https://laravel.com/docs/5.8/passport#client-credentials-grant-tokens) nos dicen que para que esto funcione correctamente, debemos agregar el CheckClientCredentials middleware a $routeMiddleware en app/Http/Kernel.php.

use Laravel\Passport\Http\Middleware\CheckClientCredentials;

protected $routeMiddleware = [
    'client' => CheckClientCredentials::class,
];

Para proteger una ruta, agregaremos el middleware «client», lo verás en el siguiente punto.

5- Creación y protección de la ruta/s

Iremos a nuestro archivo api.php, es el encargado de gestionar y resolver las rutas de nuestra API. El archivo podemos encontrarlo en routes/api.php.

Vamos a crear nuestra ruta de prueba, agregamos al archivo api.php:

Route::middleware('client')->get('/protected-route', function (Request $request) {
    return "Este texto certifica que has ingresado correctamente";
}

Lo que sucederá aquí será que cuando intentemos ir a la URL http://127.0.0.1/api/protected-route el sistema nos obligue a estar autenticados y podamos ver la frase configurada «Este texto certifica que has ingresado correctamente».

6- Probar la API localmente

Para probar las rutas utilizaremos Postman, un software utilizado para interactuar con API’s.

a. Iniciar nuestro servidor con el comando:

php artisan serve

Podemos probar que nuestra aplicación funciona correctamente escribiendo en el navegador http://127.0.0.1:8080

b. Solicitar token de acceso:

Luego, debemos solicitarle a nuestra API un token de acceso, y de esta manera acceder a los recursos de manera autenticada. Para ello ejecutamos Postman, y vamos a configurar un nuevo request:

Tal como dice la documentación de passport, debemos agregar ciertos parámetros a nuestro request. El ejemplo a continuación es para solicitar el token con PHP, pero veremos que campos son necesarios para esta solicitud.

$guzzle = new GuzzleHttp\Client;

$response = $guzzle->post('http://127.0.0.1:8080/oauth/token', [
    'form_params' => [
        'grant_type' => 'client_credentials',
        'client_id' => 'client-id',
        'client_secret' => 'client-secret',
        'scope' => '*',
    ],
]);

return json_decode((string) $response->getBody(), true)['access_token'];

Antes que nada, en Postman, haremos una prueba de nuestra URL protegida, simplemente haremos una solicitud GET a http://127.0.0.1:8080/api/protected-route y veremos que el resultado será un error de búsqueda de ruta (no nos esta mostrando la frase que esperábamos, vamos por buen camino)

En postman, configuraremos un POST request a la URL http://127.0.0.1:8080/oauth/token, adjuntando los parametros de formulario necesarios (grant_type, client_id, client_secret y scope).

Para nuestro ejemplo los valores serían:

'grant_type' => 'client_credentials',
'client_id' => '3',
'client_secret' => 'qV524tNf5ofA6VsQCaqyBAPVayXCj0y4nIup1b',
'scope' => '*',

El resultado de esta solicitud es una respuesta en JSON desde nuestra API con el token de acceso, el tipo de token y el tiempo de vida o validez.

Un ejemplo de la respuesta podría ser:

{"token_type":"Bearer","expires_in":31622400,"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjVhOWIzZjk5MTk4NWViOTRmZTFkZDk5NTZiNmU1NjI4MjhlMTI5MTkyOTAxMGI5ZjdiYTBjNDQ1ODk2OTVkOGIwYTVjMjA5NTBhMDhiMTljIn0.eyJhdWQiOiIzIiwianRpIjoiNWEasd32324r32fqeaf5NGZlMWRkOTk1NmI2ZTU2MjgyOGUxMjkxOTI5MDEwYjlmN2JhMGM0NDU4OTY5NWQ4YjBhNWMyMDk1MGEwOGIxOWMiLCJpYXQiOjE1NTkzNzMzNTAsIm5iZiI6MTU1OTM3MzM1MCwiZXhwIjoxNTkwOTk1NzUwLCJzdWIiOiIiLCJzY29wZXMiOlsiKiJdfQ.erCdhJQP4pn-f28YA4mlZNUQca4B1JQTBO7T8AddqfkFJL_de-zFc_yyKnZoNioi6kqYiV8FkYg4QUtKT096d7ypB0UF_ii4ews15J95a_-asdasddG1tfw4F_98QaroKMH0YsPCma-KoR3St2Sz7Awu-tCLG_PGbpgGL_NsSCxeioFnwq8tKOASj7wTSnwaErUbSRQaf6MHGxLvqRrCsu_xoKHQyJHyYdt4Mwoh-z9d3ECKyEZjAQnPb9oCgZzHYFevtYq120llExdpxJqndtxt0CEh6y_tUBL3SlRwrsCOlcVBa83_YEiSL5PFonZ93X2o6fcTi__2VfhqJES2d1eh7YCBr8RfBxk_ll6HeFoafNZxqv9VZVLPmmcpcggg9dhKJtVXG7Tejib0mXMQFuUd3F065f29RYCGM6UuTyc4qgsrASUmLrHDH9QdlfItIqQGbjfI1U0I1_4CY9bUQll8asloqxpwtqSr6OP1q1s-P1Z65hGHWW79gPypnV1QFz31QTPhNG3db7R5XfE0v_dGNK_uPpqKsL3W5FC41cM6aBpeiOP8z1gyK697MTIHwXJTDDFvaXf65kOhbODKptDV6_1Wx2o1sKTWysqQbGMMGJnB2na613wCRd2ckL4pmrd6vwMdwyw0_Ds1ula5kl-QoQ9N8s1B7P0X1Jic"}

En este punto hemos hecho la solicitud mediante el protocolo POST y tenemos en nuestro poder el token deseado para realizar la solicitud a nuestra ruta protegida.

c. Acceder a la ruta protegida:

Crearemos una nueva solicitud en Postman, esta vez una del tipo GET a la ruta protegida: http://127.0.0.1:8080/api/protected-route y agregaremos una cabecera (header) «Autorization» con el valor «Bearer <aquí el token>».

Si has seguido todos los pasos anteriores, al ejecutar esta solicitud deberías ver la frase deseada «Este texto certifica que has ingresado correctamente».

7- Cargar código a nuestro dispositivo MKR1000

Para esta sección vamos a utilizar el Arduino MKR1000, la librería WiFi101 y subiremos el código mediante el Arduino Web Editor.

Arduino MKR1000 – https://store.arduino.cc/arduino-mkr1000
WiFi101 – https://www.arduino.cc/en/Reference/WiFi101
Arduino Web Editor – https://create.arduino.cc

Hemos modificado levemente el ejemplo de la librería llamado «WiFiWebClient.ino»:

Deberás modificar algunas lineas para que esto te funcione correctamente:

Línea 4 y 5 – completa con el nombre y la contraseña de tu red WiFi.
Línea 10 – completa con el dominio de tu API.
Línea 11 – completa con la ruta protegida a la que queremos acceder.
Línea 14 – completa con el token de acceso previamente solicitado con Postman.

8- Probar API y Arduino MKR en producción

Llegados a este punto, llevaremos nuestra aplicación Laravel a un servidor público. Esto lo debemos hacer ya que el Arduino ejecutará un cliente web, imaginemos como un dispositivo que se conecta a internet y se comunicará con nuestra API.

a. Sube tu aplicación Laravel:

Sube los archivos a un servidor, para seguir el ejemplo supongamos que subes tu aplicación Laravel a example.com. Instala los paquetes de composer, conecta la base de datos, corre las migraciones, instala Passport, genera las claves y genera el cliente nuevo (el mismo proceso que has hecho localmente).

composer install
php artisan migrate
php artisan passport:install
php artisan passport:client --client

Si introduces la URL en tu navegador deberías ver la pantalla inicial de Laravel, eso es buena señal, significa que nuestra aplicación está funcionando correctamente.

b. Prueba la API con Postman:

Hagamos una breve prueba con Postman para asegurar que nuestra API está funcionando correctamente. Solicita un token como lo hemos hecho en el paso 5.b.

Una vez tengas el nuevo token de acceso, lo vamos a cargar en nuestro código para el Arduino MKR1000.

c. Prueba la comunicación desde el Arduino con la API:

Hemos llegado al último paso, subir el código al Arduino y ver el resultado por el puerto serial del mismo. Debemos ver entre las líneas de respuesta de nuestro request, la frase objetivo que introdujimos en la ruta protegida.

Attempting to connect to SSID: myNetwork
Connected to wifi
SSID: myNetwork
IP Address: 192.168.2.92
signal strength (RSSI):-82 dBm

Starting connection to server...
connected to server
HTTP/1.1 200 OK
Date: Wed, 05 Jun 2019 11:08:00 GMT
Content-Type: text/html; charset=UTF-8

52
Este texto certifica que has ingresado correctamente
0

disconnecting from server.

9- Conclusión

Hemos creado una comunicación desde un Arduino MKR1000 de manera inalámbrica (WiFi) y autenticada con nuestra API en una aplicación Laravel.

Con esto podríamos enviar datos de manera segura y autenticada desde sensores directamente a nuestra aplicación Laravel.

Mejoras futuras:
– Realizaremos las solicitudes con el protocolo https:// en vez de con http://
– Crearemos el proceso completo desde el Arduino (solicitar token y utilizar el mismo en los requests).

Si tienes comentarios o ideas, puedes comentarlos debajo del artículo.