Thibault Mocellin

Thibault Mocellin

Développeur Full-Stack freelance basé à Annecy 🇫🇷

OAuth Dropbox avec React Native

Posted on June 12, 2017

Cet article a pour but de montrer comment s’authentifier à l’api Dropbox via Oauth depuis une application ReactNative.

Commençons par créer le projet :

react-native init DropboxOAuthSample

Pour nous authentifier sur l’api de Dropbox le principe de fonctionnement est le suivant :

  • Nous allons utiliser la librairie Linking de ReactNative pour pouvoir ouvrir le navigateur sur la page d’authentification Dropbox.
  • Ensuite nous allons aussi utiliser le Linking pour que notre application puisse être ouverte depuis une url spécifique.

Donc lorsque l’on clique sur le bouton pour s’authentifier dans l’application le navigateur s’ouvre, nous demande nos informations pour s’authentifier. Une fois authentifié le navigateur nous renvoie dans l’application en passant le token que nous utiliserons par la suite avec l’api de Dropbox.

Installation et configuration de Linking

La première chose à faire c’est d’ajouter la librairie Linking à notre projet Xcode pour cela suivez les instructions ici.

Ensuite ajoutez le code suivant dans le fichier AppDelegate.m :

En dessous des autres imports

#import "RCTLinkingManager.h"

Juste après @implementation AppDelegate

- (BOOL)application:(UIApplication _)application openURL:(NSURL _)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
  return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
}

Maintenant que nous avons ajouté la librairie Linking à notre projet nous allons configurer l’url sur laquelle notre application devra s’ouvrir.

iOS :

Sélectionnez le projet, rendez-vous dans l’onglet Info puis dans la section URL Types. Ajoutez un nouveau type comme sur l’écran ci-dessous :

set url type

Pour vérifier que le Linking fonctionne correctement, lancez l’application puis depuis le simulateur ouvrez safari et saisissez l’adresse suivante : dropboxoauthsample://open. Normalement il vous sera proposé d’ouvrir l’application.

Android :

Sur Android la configuration est différente nous allons venir modifier le fichier AndroidManifest.xml.

Premièrement nous allons ajouter le code suivant dans la section activity du fichier :

android:launchMode = "singleTask";

Cela va permettre de ne pas redémarrer une nouvelle Activity lorsqu’on ouvrira l’application via le Linking.

Ensuite on va rajouter un nouveau IntentFilter sous celui existant et qui contiendra les informations des URLs acceptées pour lancer l’application.

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <!-- Accepts URIs that begin with "http://www.dropboxoauthsample.com/open” -->
    <data android:scheme="https"
        android:host="www.dropboxoauthsample.com"
        android:pathPrefix="/open" />
    <!-- note that the leading "/" is required for pathPrefix-->
    <!-- Accepts URIs that begin with "dropboxoauthsample://open” -->
    <data android:scheme="dropboxoauthsample"
        android:host="open" />
</intent-filter>

Vous pouvez retrouver le fichier AndroidManifest ici.

Création de l’application Dropbox Maintenant que nous en avons terminé avec la configuration, nous allons devoir créer une application sur Dropbox. Pour ce faire rendez-vous sur la plateforme développeur de Dropbox et cliquez sur “Create app”.

Remplissez ensuite le formulaire comme sur la photo ci-dessous :

creer une application dropbox

Une fois votre application créée vous devrez ajouter les urls suivantes dans la section OAuth2 RedirectUris :

dropbox redirect uri

Gestion de l’authentification dans l’application ReactNative Nous somme maintenant prêt pour gérer l’authentification dans notre application. Nous allons d’abord créer un dossier src et ajouter le fichier index.js

mkdir src && cd src
touch index.js

Ajoutez le code suivant dans le fichier index.js

import React, { Component } from 'react'
import { StyleSheet, Text, View, Linking, Button, Platform } from 'react-native'

const DROPBOX_APP_KEY = 'bol535f38zp9krv' //change with your app key this one is not valid
import uuidV4 from 'uuid/v4'

export default class DropboxOAuthSample extends Component {
  constructor(props) {
    super(props)
    this.state = {
      isDropboxInit: false,
      apiToken: '',
      verification: uuidV4(),
    }
  }

  componentDidMount() {
    Linking.addEventListener('url', event => this.handleLinkingUrl(event))
  }

  componentWillUnmount() {
    Linking.removeEventListener('url', event => this.handleLinkingUrl(event))
  }

  handleLinkingUrl(event) {}

  loginWithDropbox() {}

  render() {
    const instruction = this.state.isDropboxInit
      ? 'Dropbox API token : ' + this.state.apiToken
      : 'Vous ne vous êtes pas encore connecté'
    return (
      <View style={styles.container}>
        <Button title="Se connecter avec Dropbox" onPress={() => this.loginWithDropbox()} />
        <Text style={styles.instructions}>{instruction}</Text>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  instructions: {
    marginTop: 32,
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
})

Ici dans un premier temps on importe nos librairies ReactNative dont Linking. Puis on définit notre App Key Dropbox qui se trouve sur la page de l’application Dropbox. Dans le constructeur on définit l’état initial.

  • isDropboxInit : Permet de déterminer si on est connecté à dropbox.
  • apiToken : Token retourné par Dropbox une fois connecté.
  • verification: Paramètre passer à l’url de connection Dropbox.

Ensuite on ajoute un EventListener pour le linking qui à pour callback la méthode handleLinkingUrl.

Puis on ajoute les méthodes :

  • loginWithDropbox : Permet de se connecter à dropbox.
  • handleLinkingUrl : CallBack lorsque l’application est ouverte via le Linking.

Nous allons compléter ces méthodes dans la suite de l’article.

Enfin remplacez le code des fichiers index.android.js et index.ios.jspar :

import React, { Component } from 'react';
import { AppRegistry } from 'react-native';

import App from './src';

AppRegistry.registerComponent('DropboxOAuthSample', () => App);
Nous allons maintenant compléter la méthode loginWithDropbox :

loginWithDropbox() {
    const redirect_uri = Platform.OS === 'ios' ? 'dropboxoauthsample://open' : 'https://www.dropboxoauthsample.com/open';
    const url = `https://www.dropbox.com/oauth2/authorize?response_type=token&client_id=${DROPBOX_APP_KEY}&redirect_uri=${redirect_uri}&state=${this.state.verification}`;
    Linking.openURL(url).catch(err => console.error('An error occurred', err));
  }

Dans cette méthode premièrement nous définissons quel va être l’url de redirection après le login en fonction de la plateforme. C’est grace à ça que l’on va pouvoir ré-ouvrir l’application une fois connecté. Ensuite on construit l’url de login en passant les paramètres suivants : l’app id Dropbox, l’url de redirection et la variable state qui prend la valeur de verification définit dans le constructeur. Enfin on ouvre l’url via le Linking.

Nous utilisons la variable state pour combler un problème de sécurité. Il possible pour un utilisateur malveillant d’envoyer à notre application une url contenant son propre token et non celui de l’utilisateur de l’application, ensuite sans le savoir notre utilisateur pourrait envoyer des données sensibles directement sur le compte de l’attaquant.

C’est la qu’intervient la variable state, généré aléatoirement au lancement de l’application, elle va permettre dès que l’on reçoit une url de vérifier si cette url est bien celle générée par l’application. Si la valeur reçue par l’url est différente de celle générée par l’application alors on enregistre pas le token et on affiche un message d’erreur.

Dans la méthode handleLinkingUrl nous allons avoir besoin de parser l’url de retour pour simplifier cette étape nous allons utiliser la librairie shitty-qs.

yarn add shitty-qs

Ensuite importer shitty-qs :

import shittyQs from 'shitty-qs'

Enfin rajoutez le code suivant dans le méthode handleLinkingUrl :

var [, query_string] = event.url.match(/\#(.*)/)
var query = shittyQs(query_string)
if (this.state.verification === query.state) {
  this.setState({ isDropboxInit: true, apiToken: query.access_token })
} else {
  alert('Verification non égale')
}

Ici on parse les paramètres de l’url de retour ensuite on test que la valeur de la variable state est bien égale à la valeur de vérification définit dans le constructeur. Si c’est ok alors on définit la valeur du token avec la valeur retourner par l’url.

Voila ensuite vous pouvez utiliser l’api ou le sdk js avec le token que l’on vient de récupérer.

Le code source est disponible ici.