GuíasSwift

OAuth 2.0 con Swift

Guía paso-a-paso sin librerías de terceros

La seguridad siempre ha sido una parte importante del desarrollo, y de un tiempo a esta parte, en el que nuestros datos se han convertido en el nuevo objeto de deseo de muchas compañías, ha cobrado más importancia si cabe.

Escándalos como el de Cambridge Analytica han hecho ver a la mayoría de la gente lo importante que es saber a quien le damos acceso a nuestros datos y para que.

Desde hace años existe un protocolo de seguridad que permite a los desarrolladores dar, o solicitar, permisos a aplicaciones para que obtengan acceso limitado a un servicio web. Hablamos de OAuth 2.0, un protocolo que según sus autores…

An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.

En esta guía vamos a ver el caso de una app que solicita al usuario que le de permisos para acceder a sus datos en un servicio web. El servicio elegido es Trakt.TV, web de visita obligada para todos los amantes de las series.

Como siempre podéis descargar el código que acompaña al artículo en este repositorio de GitHub.

Alta en Trakt.TV

Como para cualquier servicio web que queramos consumir necesitamos darnos de alta como usuarios/desarrolladores, así que abrimos el navegador y nos dirigimos al formulario de alta de usuarios, o si ya somos usuarios basta con identificarnos.

En cuanto tengamos nuestro usuario y nos hayamos validado, tenemos que crear las credenciales para nuestra app. Esto lo haremos desde en enlace titulado Create An App situado a pie de página.

Al pulsarlo nos llevará a la sección desde la que gestionaremos todas nuestras apps que consuman los servicios de Trakt.TV y allí pulsaremos en el botón New Application, ahora rellenaremos los datos del formulario para dar de alta nuestra app.

Los datos más importantes son Redirect URI y Permissions. El primero forma parte de la especificación OAuth y es donde el servicio web, en este caso Trakt.TV, nos informará de que el usuario de nuestra app es válido y que podemos proceder a obtener un token de acceso. Todo esto lo veremos en detalle cuando lleguemos a la implementación de la app.

El campo Permissions lo que nos pregunta es a qué permisos, o datos,  quiere acceder nuestra app para luego informar al usuario cuando vaya a dar autorización a nuestra app. Para nuestra app sólo necesitamos poder hacer chekin de las series y episodios que el usuario vea.

Tras hacer el submit del formulario de creación veremos la página con los datos de acceso para nuestra app, y es aquí donde veremos el Client ID y el Client Secret  que nos servirán para identificar nuestra app o solicitar los token de acceso.

Un momento ¿acserie es un esquema válido? Sí, creedme, acseries://oauth es donde el servicio web nos devolverá un código que podremos canjear por un token. Para explicarlo vamos a ver en detalle el flujo de obtención de un token desde un dispositivo móvil.

OAuth. Flujo de trabajo.

Me encantan las series, y desde que tengo Netflix y HBO me cuesta saber por cuál episodio voy en tal serie o cuándo van a estrenar la tercera temporada de aquella serie, así que he decido que voy a desarrollar mi propia app para seguir mis series favoritas.

Como Trakt.TV es un sitio seguro, tengo que pedirle al usuario que confíe en mi app y me permita acceder a su cuenta para llevar este seguimiento.

Lo primero que hago es solicitar un código de autorización al servicio mediante una URL en la que le digo quién soy ¿Cómo se lo digo? pasando como parámetro en la URL el clientID de la app que acabamos de crear.

La app abre un SFSafariViewController apuntando a esa URL que acabo de construir. Cuando se carga vemos que es la página de login de usuarios del Trakt.TV. En cuanto el usuario se identifique con su usuario y su contraseña se le preguntará si quiere dar acceso a sus datos a nuestra App.

Como somos unos desarrolladores serios el usuario dirá que sí sin pensarlo y Track.TV nos dará el código de autentificación. ¿Pero cómo sabe Trakt.TV dónde tiene que devolver ese código? Lo va a devolver en la URL que le especificacmos en el campo Redirect URI del formulario de alta de nuestra app. A esta URL le va a añadir el parámetro code, que contendrá el código.

Así que nuestro SFSafariViewController recibe la petición desde el servidor de Trakt.TV de abrir una URL, concretamente acseries://oauth?code=1341341341… Pero claro, acseries no es un esquema conocido… todavía. Y digo todavía porque nuestra app va a registrar ese esquema en su Info.plist para que cualquier petición que le llegue a nuestro dispositivo con el esquema acseries sea ella la encargada de gestionarlo.

Como ya hemos registrado el esquema, iOS le dirá a nuestra app algo como “…oye, que un sitio web me pide que abra una dirección “acseries” y he visto que la encargada de gestionar esta protocolo eres tú, así que aquí tienes la URL.”

Y ahora nos queda la última parte, el usuario confía en nosotros, el servicio nos ha dado el código de autentificación y sólo nos queda pedirle que nos de los token de acceso y refresco.  Para eso le hacemos otra petición en la que pasamos el código de autentificación, el clientID y el clientSecret de nuestra app en formato json.

Si toda ha ido bien la respuesta que obtendremos del servicio serán los token de acceso y refresco e información sobre el tiempo de vida del token de acceso. Cuando el token de acceso llegue al final de su vida útil usaremos el token de refresco para pedirle al servicio que no de otro token de acceso.
¿Pero hay que pasar por todo esto otra vez? No, el código de refresco implica que el usuario confía en nosotros, así que sólo habrá que repetir el último paso, pero en lugar pasar el código de autentificación pasaremos el token de refresco.

 

Y ahora con Swift

Para no tener que crear desde cero la app podéis descargar el código desde este repositio de GitHub. Una vez abierto con Xcode veréis que la app tiene un target llamado CoreTraktTV, esta es la librería con el cliente de acceso a los servicios web. Es un cliente muy limitado, sólo nos permitirá descargar las series que marcan tendencia en este momento y validar con OAuth nuestra app para añadir series a nuestra Watchlist de usuario en Trakt.TV.

La app tiene un UIViewController con una UICollectionView donde mostraremos las 10 series de moda en este momento.

Cada cela contiene un botón (ADD) que al pulsarlo añadirá la serie a la Watchlist del usuario. Si el usuario todavía no ha autorizado a la app, el servicio nos devolverá un error HTTP 401 (no autorizado). En ese momento tendremos que comenzar todo el proceso de autentificación OAuth.

¡Vamos allá!

Al arrancar la app en el simulador veremos que se cargan las series, vamos a escoger una, la que más os guste, y pulsamos en el botón (ADD)

Como es la primera vez que intentamos acceder a los datos del usuario en Trakt.TV el servicio no nos lo permite, así que cuando recibamos el error 401 le pedimos al framework CoreTraktTV que nos de la URL a la que tenemos que llevar al usuario para que nos de permisos.

Esta es la función que compone la URL según la documentación del API de Trakt.TV

En cuanto tengamos la URL creamos un SFSafariViewController y lo presentamos para que se valide como usuario y decida si quiere dar acceso a la app a sus datos.

Si el usuario es válido y nos da permisos, Trakt.TV nos devolverá un código de validación en la URL…

¿Y cómo vamos a controlar que recibimos esta petición? Muy fácil, registrando un custom scheme para nuesta app.

Registrar el Custom URL Scheme

Lo primero que vamos a hacer es registrar el esquema URL donde dijimos que queríamos recibir la respuesta de validación del usuario cuando dimos de alta la app.

Nos dirigimos al archivo Info.plist y añadimos la siguiente entrada justo antes del cierre de la etiqueta <dicc>

Ahora cualquier petición que reciba iOS cuyo esquema sea acseries será dirigida a nuestra app.

Gestionar la respuesta de validación

Abrimos el archivo AppDelegate.swift y añadimos la función con la que iOS le dirá a nuestra app que ha recibido una petición con el esquema acseries.

Lo que hacemos dentro de la función es descomponer la URL es sus componentes gracias a la clase URLComponents. Lo que nos interesa de la URL devuelta por el servicio es el parámetro code.

En cuanto comprobemos que la URL contiene ese parámetro y hayamos extraído su valor hacemos una llamada al servicio para canjear ese código por los token de acceso y refresco.

Me ha llegado el código ¿Cómo lo intercambio?

Tenemos que hacer una llamada más al servicio, la última, para ello tenemos que pasarle el código recibido y los datos ID y Secret de nuestra app.

Si todo va según lo esperado tendremos en nuestro poder un token de acceso y otro de refresco. Ahora sólo tenemos que añadir el token de acceso en todas aquellas operaciones que requieran de autentificación OAuth.

Para probar que todo está en orden sólo tenemos que añadir algunas series tras dar permisos a la app

Podéis comprobar que las series añadidas aparecen en el sitio web yendo a la sección List de vuestro perfil de Trakt.TV, una vez allí pulsamos en la lista Watchlist y ahí estarán las series que acabamos de añadir.

One more thing… ¿Dónde guardo los token de acceso y refresco?

Que el usuario nos de su consentimiento para acceder a sus datos y que el servicio se preocupe de establecer un mecanismo que permite gestionar esos tokens de forma segura no vale de mucho si al final almacenamos esos tokens de acceso y refresco en el UserDefaults de nuestra app o en un archivo de texto plano.

Lo recomendable sería utilizar los servicios de seguridad que tanto iOS como macOS nos proporcionan, en este caso es recomendable guardarlos los token con Keychain.

El uso de Keychain nos da para otra guía, así que estad atentos que dentro de poco publicaremos sobre el tema.

 

Enlaces de interés

OAuth

Trackt.TV

Etiquetas

Adolfo Vera

Me gustan las camisetas y las zapatillas // Swift + UX/UI en sistemas Apple // Ahora @seeyuu_app // Creador de @GetPomodoroApp · @MADatBUS · @GetMeteo y...

Artículos relacionados

Close
Close