Comment ajouter l’authentification à une application React Native ?

Couverture d'authentification React Native (Expo)

L’authentification est un élément essentiel de presque toutes les applications.

Cet article pratique fournira un guide étape par étape pour démarrer avec l’authentification React Native.

En outre, il décrit les bases de l’authentification, sa comparaison avec l’autorisation, le flux d’authentification et les avantages de son utilisation.

Qu’est-ce que l’authentification ?

L’authentification est le processus de vérification de l’identité d’une personne. D’une manière générale, il existe trois manières de s’authentifier, soit avec :

  1. Quelque chose que vous connaissez (par exemple, un mot de passe, un code PIN)
  2. Quelque chose que vous possédez (par exemple, un téléphone portable, des clés)
  3. Quelque chose que vous êtes (par ex. empreinte digitale, iris)

La plupart des applications utilisent la première option, mais beaucoup d’entre elles en combinent plusieurs pour augmenter le niveau de sécurité. Ce concept est appelé authentification multifactorielle (AMF).

Flux d’authentification

Le flux d’authentification générique fonctionne comme suit :

  1. L’utilisateur envoie son mot de passe au serveur.
  2. Le serveur hache le mot de passe et le compare au hachage du mot de passe dans la base de données.
  3. Si les hachages correspondent, le serveur crée une session et envoie le jeton de session à l’utilisateur. En revanche, si les hachages ne correspondent pas, une erreur est soulevée.
  4. L’utilisateur utilise ensuite le jeton de session à chaque demande. À chaque demande, le serveur vérifie si le jeton est présent et valide.

Le flux ci-dessus correspond à ce que l’on appelle l’authentification par jeton. Il existe d’autres systèmes d’authentification tels que le JSON Web Token (JWT), l’authentification d’accès de base, la connexion sociale, etc.

Authentification et autorisation

L’authentification consiste à vérifier l’identité d’un utilisateur, tandis que l’autorisation consiste à vérifier si un utilisateur dispose des autorisations suffisantes pour effectuer une action.

Les modèles d’autorisation comprennent notamment le contrôle d’accès obligatoire (MAC), le contrôle d’accès discrétionnaire (DAC) et l’autorisation basée sur le rôle.

Avantages de l’authentification

Examinons les avantages de l’utilisation de l’authentification dans vos applications mobiles.

Sécurité

L’authentification peut protéger votre application contre les accès non autorisés et garantir que seuls les utilisateurs légitimes ont accès à votre service.

Cela permet d’éviter les violations de données et les cyber-attaques et de maintenir l’environnement de votre application sécurisé et digne de confiance.

Personnalisation

L’authentification permet de personnaliser l’expérience de l’utilisateur dans l’application. Lorsque les utilisateurs se connectent, ils peuvent accéder à des paramètres personnalisés, à des préférences et à des recommandations adaptées à leurs besoins.

Cette personnalisation rend l’application plus attrayante et plus conviviale. Elle permet de fidéliser les utilisateurs en leur offrant une expérience plus pertinente et plus agréable.

Exigences légales

Dans certains pays, la législation vous oblige à vérifier l’identité de vos utilisateurs. Il s’agit par exemple de la connaissance du client (KYC).

Presque toutes les applications financières sont tenues de le faire. Vous devez disposer d’un système d’authentification approprié pour vous conformer à ces réglementations ou pour protéger les informations personnelles de vos utilisateurs.

Comment ajouter de l’authentification à une application React Native ?

Cette partie de l’article fournira un guide étape par étape sur l’ajout de l’authentification Back4app à une application React Native(Expo).

Conditions préalables

  • Compréhension de base du Backend as a Service (BaaS)
  • IDE JavaScript, Node.js, et un émulateur mobile ou un appareil physique
  • Capacité à lire et à écrire du code JavaScript
  • Expérience avec React Native et Expo
  • Un compte Back4app gratuit

Qu’est-ce que Back4app ?

Back4app est l’une des meilleures solutions open-source de Backend as a Service (BaaS). C’est une plateforme mature et fiable qui existe depuis 2015.

Ses principales fonctionnalités incluent des bases de données en temps réel, des fonctions Cloud Code, la génération automatique d’API RESTful/GraphQL, et bien plus encore !

Back4app dispose d’un tableau de bord d’administration facile à utiliser et intuitif et d’une interface de ligne de commande (CLI) pour les utilisateurs plus avancés.

Il fournit également des SDK pour les langages de programmation et les frameworks les plus populaires, tels que JavaScript, PHP, Flutter et Dart.

La meilleure partie est que Back4app offre un niveau gratuit. Le niveau gratuit est idéal pour les tests et le prototypage, et il comprend les éléments suivants :

  • 25k/mois demandes
  • 250 Mo de stockage de données
  • 1 Go de transfert de données
  • 1 Go de stockage de fichiers

Pourquoi utiliser Back4app ?

  • Prise en charge de l’authentification sociale
  • Fournit des SDK pour la plupart des langages de programmation et des frameworks
  • Installation et utilisation aisées
  • Excellente assistance à la clientèle

Pour savoir comment l’authentification Back4app se compare à l’authentification Firebase, consultez Le guide ultime de l’authentification React Firebase.

Introduction du projet – Démarrer avec l’authentification React Native

Nous allons construire une application React Native prête à la production qui utilise l’authentification Back4app. L’application permettra aux utilisateurs de s’inscrire, de se connecter et de gérer leurs profils.

En outre, l’application comportera deux onglets de navigation, l’un pour les utilisateurs authentifiés et l’autre pour les utilisateurs non authentifiés.

Le produit final ressemblera à ceci :

Back4app Authentification React Native App

Commençons à coder !

Backend (Back4app)

Dans cette section, nous allons créer une application Back4app, étendre le modèle utilisateur par défaut et obtenir les clés API nécessaires pour se connecter au backend.

Créer une application

Tout d’abord, connectez-vous à votre compte Back4app, ou créez-en un si vous n’en avez pas encore.

Lorsque vous vous connectez, vous êtes redirigé vers votre liste d’applications. Cliquez sur “Créer une nouvelle application” pour créer une nouvelle application.

Liste des applications de Back4app

La plateforme Back4app vous permet de déployer deux types d’applications – soit Backend as a Service (BaaS), soit Containers as a Service (CaaS). L’authentification est incluse dans le BaaS, il faut donc la sélectionner.

Back4app Backend as a Service Select

Ensuite, donnez à votre application un nom descriptif, laissez la base de données comme NoSQL, et cliquez sur “Créer”.

Configuration de l'application Back4app

Attendez environ deux minutes pour que la plateforme crée l’application. Back4app s’occupe de tout, de la création de la couche applicative à la mise en place de la base de données, de la sécurité, de la mise à l’échelle, et plus encore.

Une fois cela fait, vous serez redirigé vers l’interface de la base de données.

Vue de la base de données de Back4app

Modifier la base de données

Parlons maintenant des classes de base de données.

Chaque classe de base de données Back4app est livrée avec les champs par défaut suivants :

+-----------+------------+-----------------------------------------+
| Data type | Name       | Description                             |
+-----------+------------+-----------------------------------------+
| String    | objectId   | Object's unique identifier              |
+-----------+------------+-----------------------------------------+
| Date      | createdAt  | Date of object creation                 |
+-----------+------------+-----------------------------------------+
| Date      | updatedAt  | Date of object's last update            |
+-----------+------------+-----------------------------------------+
| ACL       | ACL        | Access Control List (security features) |
+-----------+------------+-----------------------------------------+

La classe User est assortie de quelques champs supplémentaires :

+-----------+----------------+--------------------------+----------+
| Data type | Name           | Default value            | Required |
+-----------+----------------+--------------------------+----------+
| String    | username       |                          | yes      |
+-----------+----------------+--------------------------+----------+
| String    | email          |                          | no       |
+-----------+----------------+--------------------------+----------+
| Boolean   | emailVerified  | false                    | no       |
+-----------+----------------+--------------------------+----------+
| String    | password       |                          | yes      |
+-----------+----------------+--------------------------+----------+
| Object*   | authData       | {}                       | yes      |
+-----------+----------------+--------------------------+----------+

La classe d’utilisateur par défaut de Back4app devrait convenir à la plupart des cas d’utilisation. Néanmoins, il est facile de l’étendre. Pour le démontrer, ajoutons un champ biographie(bio).

Tout d’abord, cliquez sur le bouton “+ Colonne” au-dessus de la table de la base de données.

Base de données Back4app Ajouter une colonne

Dans le formulaire de création de colonne, sélectionnez “String” comme type de données, attribuez le nom ” bio", rendez-le obligatoire et cliquez sur “Add”.

Back4app Ajouter un champ de base de données

Vous savez maintenant comment fonctionnent les classes de base de données de Back4app et comment étendre le modèle utilisateur.

Clés API

Vous devrez obtenir les clés API de votre application pour vous connecter au backend depuis le frontend.

Pour les obtenir, naviguez dans votre application Back4app et sélectionnez “Security & Keys” dans la barre latérale. Prenez note de la “Clé client” et de la “Clé JavaScript”.

Clés API de Back4app

Voilà, c’est tout pour le backend.

Frontend (React Native)

Dans cette section, nous allons créer une application Expo, installer une bibliothèque de composants, configurer la navigation, nous occuper des écrans et enfin connecter le frontend avec le backend.

Créer une application

Pour créer une application React Native, nous utiliserons l’utilitaire create-expo-app. Cet utilitaire simplifie la création d’apps React Native en générant la structure des répertoires, en configurant TypeScript, etc.

Exécutez d’abord les commandes suivantes :

npx create-expo-app@latest back4app-expo-auth
cd back4app-expo-auth

Cette commande installera également create-expo-app si vous ne l’avez pas encore.

Vous remarquerez que le projet bootstraped a la structure de répertoire suivante :

back4app-expo-auth/
├── app                 - Layouts, screens
├── assets              - Static assets (e.g. images, videos, fonts)
├── components          - Reusable components used through the app
├── constants           - Static variables & configurations
├── hooks               - Custom React hooks
├── scripts             - Development scripts
├── app.json            - Expo configuration & metadata
├── expo-env.d.ts       - Expo TypeScript declarations
├── ...    

Démarrer le serveur de développement :

$ npx expo start

Enfin, appuyez sur A pour ouvrir l’application sur votre émulateur Android. Vous pouvez également utiliser un émulateur iOS ou un appareil iOS physique. Une fois l’application ouverte, vous devriez voir l’écran Expo par défaut.

Écran par défaut de l'Expo

React Native Paper

Pour simplifier le processus de développement de l’interface utilisateur, nous utiliserons React Native Paper.

React Native Paper est une bibliothèque de composants facile à utiliser et de haute qualité pour les applications React Native. Elle fournit de nombreux composants pré-fabriqués couvrant presque tous les cas d’utilisation.

Commencez par l’installer via NPM :

$ npm install react-native-paper react-native-safe-area-context 

Si vous construisez pour iOS, vous devrez également lier les parties natives de la bibliothèque :

npx pod-install

Ensuite, configurez Babel pour qu’il n’inclue pas les composants inutilisés dans la production :

// babel.config.js

module.exports = function(api) {
  api.cache(true);
  return {
    presets: ["babel-preset-expo"],
    env: {
      production: {
        plugins: ["react-native-paper/babel"],
      },
    },
  };
};

Naviguez ensuite vers app/_layout.tsx et intégrez l’application dans PaperProvider de la manière suivante :

// app/_layout.tsx

// ...

export default function RootLayout() {

  // ...

  return (
    <ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
      <PaperProvider>
        <Stack>
          <Stack.Screen name="index" options={{headerShown: false}}/>
          <Stack.Screen name="(auth)" options={{headerShown: false}}/>
          <Stack.Screen name="(tabs)" options={{headerShown: false}}/>
          <Stack.Screen name="+not-found"/>
        </Stack>
      </PaperProvider>
    </ThemeProvider>
  );
}

N’oubliez pas l’importation en tête de fichier :

import {PaperProvider} from "react-native-paper";

Parfait, nous avons installé avec succès la bibliothèque de composants.

Conteneur

Nous allons également créer un composant Container. Ce composant sera utilisé dans tous nos écrans et ajoutera une marge sur tous les côtés afin que le contenu ne dépasse pas le bord de l’écran.

Créez un fichier Container.tsx dans le dossier components:

// components/Container.tsx

import React from "react";
import {View} from "react-native";

export type ContainerProps = {
  children: React.ReactNode;
}

export function Container({children}: ContainerProps) {
  return (
    <View style={{margin: 12}}>
      {children}
    </View>
  );
}

Navigation et écrans

Comme mentionné dans l’introduction du projet, notre application aura deux onglets de navigation.

L’un est destiné aux utilisateurs authentifiés, l’autre aux utilisateurs non authentifiés. L’onglet authentifié permet aux utilisateurs de gérer leur profil et l’autre de se connecter ou de créer un compte.

Pour ce faire, créez d’abord la structure de répertoire suivante :

app/
├── (auth)/
│   ├── _layout.tsx
│   ├── login.tsx
│   └── register.tsx
├── (tabs)/
│   ├── _layout.tsx
│   └── profile.tsx
├── +html.tsx
├── +not-found.tsx
├── _layout.tsx
└── index.tsx

Pour plus d’informations sur Expo Router, consultez les documents officiels.

Les mises en page d’Expo contiennent généralement beaucoup de code standard. Je ne veux pas inonder l’article avec du code, donc je vous invite à récupérer le contenu du fichier sur GitHub :

  1. (auth)/_layout.tsx
  2. (onglets)/_layout.tsx
  3. _layout.tsx

Pour aller plus loin, placez les éléments suivants dans index.tsx:

// app/index.tsx

import React, {useEffect} from "react";
import {ActivityIndicator} from "react-native-paper";
import {useRouter} from "expo-router";
import {View} from "react-native";

export default function IndexScreen() {

  const router = useRouter();
  const isAuthenticated = true;

  useEffect(() => {
    setTimeout(() => {
      if (isAuthenticated) {
        router.push("profile");
      } else {
        router.push("login");
      }
    }, 1000);
  }, []);

  return (
    <View style={{
      flex: 1,
      justifyContent: "center",
      alignItems: "center",
    }}>
      <ActivityIndicator
        size="large"
        animating={true}
      />
    </View>
  );
}

Le fichier index.tsx est le point d’entrée de l’application. Dans ce fichier, nous vérifions si l’utilisateur est authentifié et nous le redirigeons en conséquence. Pour l’instant, la redirection est basée sur la variable isAuthenticated.

Saisissez ensuite le code pour les écrans :

  1. app/(auth)/login.tsx
  2. app/(auth)/register.tsx
  3. app/(tabs)/profil.tsx

Le code des écrans est assez simple. C’est du code React Native qui utilise React Native Paper pour créer les formulaires et autres interfaces utilisateur. Il utilise également des hooks React de base tels que useState() et useEffect().

Parse SDK

Pour se connecter au backend, nous utiliserons le SDK de Parse. Le SDK offre des méthodes pour le stockage et la manipulation des données, l’authentification des utilisateurs et d’autres fonctionnalités.

Tout d’abord, installez-le via NPM :

$ npm install parse @react-native-async-storage/async-storage --save
$ npm install --save-dev @types/parse

Nous avons également installé le paquetage @react-native-async-storage/async-storage pour conserver la session de l’utilisateur lorsque l’application se ferme. Sans cela, les utilisateurs devraient s’authentifier à chaque fois qu’ils ouvrent l’application.

Créez ensuite un fichier .env à la racine du projet comme suit :

EXPO_PUBLIC_APPLICATION_ID=<your-back4app-application-id>
EXPO_PUBLIC_JAVASCRIPT_KEY=<your-back4app-client-key>

Veiller à remplacer <your-back4app-application-id> et <your-back4app-client-key> par les clés d’API obtenues dans la section backend de l’article.

Initialiser Parse dans _layout.tsx comme suit :

// app/_layout.tsx

// ...
import Parse from "parse/react-native.js";
import AsyncStorage from "@react-native-async-storage/async-storage";
import ParseContext from "@/context/parseContext";

Parse.setAsyncStorage(AsyncStorage);
Parse.initialize(
  process.env.EXPO_PUBLIC_APPLICATION_ID ?? "",
  process.env.EXPO_PUBLIC_JAVASCRIPT_KEY ?? "",
)
Parse.serverURL = "https://parseapi.back4app.com/";

async function testParse() {
  try {
    const testMessage = new Parse.Object("TestMessage");
    testMessage.set("message", "Hello, World!");
    await testMessage.save();
  } catch (error) {
    console.log("Error saving the test message: ", error);
  }
}
testParse().then(() => console.log("Successfully connected to Parse!"));

// ...

Nous avons également inclus la fonction testParse(), qui teste la connexion à Back4app en ajoutant un message “Hello, world !” à la base de données. Assurez-vous que la connexion fonctionne en redémarrant le serveur Expo et en lançant l’application dans l’émulateur.

Message de test de la base de données Back4app

Naviguez vers la vue de la base de données de votre application et vérifiez si vous pouvez voir le message.

Si vous obtenez une erreur disant “Error : crypto.getRandomValues() not supported”. Installez les dépendances suivantes :

npm install react-native-get-random-values --save
npm i --save-dev @types/react-native-get-random-values

Ajoutez ensuite l’importation en haut de _layout.tsx (avant d’importer Parse) :

import "react-native-get-random-values";

Redémarrez le serveur de développement ; tout devrait bien fonctionner.

Pour que l’instance Parse soit disponible dans tous les écrans, nous allons la passer en utilisant React Context.

Tout d’abord, créez un répertoire contextuel et placez-y le fichier parseContext.ts suivant :

import {createContext} from "react";

const ParseContext = createContext<typeof Parse | null>(null);

export default ParseContext;

Ensuite, l’application entière est enveloppée dans ce système tout en passant l’instance de Parse :

// app/_layout.tsx

// ...

return (
  <ParseContext.Provider value={Parse}>
    {/* ... */}
  </ParseContext.Provider>
)

Récupération et manipulation de données

Dans cette dernière section, nous utiliserons Parse SDK pour authentifier l’utilisateur et récupérer ses informations.

Au lieu de répéter le même code dans chaque écran, nous allons créer un hook useParse. Ce hook va récupérer l’instance de Parse dans le contexte, obtenir des informations sur l’utilisateur et déclencher une mise à jour une fois que tout est prêt.

Créez un nouveau fichier nommé useParse.ts dans le dossier context:

// context/useParse.ts

import {useContext, useEffect, useState} from "react";
import ParseContext from "@/context/parseContext";

export function useParse() {
  const parse = useContext(ParseContext) as typeof Parse;
  const [parseUser, setParseUser] = useState<Parse.User | null>(null);
  const [isParseLoaded, setIsParseLoaded] = useState(false);

  useEffect(() => {
    (async () => {
      try {
        setParseUser(await parse.User.currentAsync());
      } catch (e) {
        console.error(e);
      } finally {
        setIsParseLoaded(true);
      }
    })();

  }, []);

  return {parse, parseUser, isParseLoaded};
}

Modifiez ensuite index.tsx en remplaçant isAuthenticated par une vérification de session réelle :

// app/index.tsx

// ...
import {useParse} from "@/hooks/useParse";

export default function IndexScreen() {

  const router = useRouter();
  const {parse, parseUser, isParseLoaded} = useParse();

  useEffect(() => {
    if (!isParseLoaded) return;
    (async () => {
      if (parseUser) {
        console.log("User is authenticated!");
        console.log(parseUser.toJSON());
        router.replace("/profile");
      } else {
        console.log("User is not authenticated.");
        console.log({});
        router.replace("/(auth)/login");
      }
    })();
  }, [isParseLoaded]);

  return (
    // ...
  );
}

Ensuite, modifiez login.tsx pour connecter l’utilisateur :

// app/(auth)/login.tsx

// ...
import {useParse} from "@/hooks/useParse";

export default function LoginScreen() {

  const router = useRouter();
  const {parse, parseUser, isParseLoaded} = useParse();

  // ...

  const onLogin = async () => {
    // ...
    try {
      await parse.User.logIn(username, password);
      router.push("/(tabs)/profile");
    } catch (error: any) {
      setError(error.message);
    }
  }

  return (
    // ...
  );
}

Ensuite, modifiez le fichier register.tsx de la même manière que le fichier login.tsx, mais cette fois-ci, remplacez le TODO comme suit :

// app/(auth)/register.tsx

try {
  const user = await parse.User.signUp(username, password, undefined, undefined);
  user.setEmail(email);
  await user.save();
  router.replace("/(tabs)/profile")
} catch (error: any) {
  setError(error.message);
}

Enfin, modifiez profile.tsx pour afficher les informations relatives au profil :

// app/(tabs)/profile.tsx

// ...
import {useParse} from "@/hooks/useParse";

export default function IndexScreen() {

  const router = useRouter();
  const {parse, parseUser, isParseLoaded} = useParse();

  // ...

  useEffect(() => {
    if (!parseUser) return;
    setBio(parseUser.get("bio") || "");
  }, [parseUser]);

  const onSave = async () => {
    if (!parseUser) return;
    parseUser.set("bio", bio);
    try {
      await parseUser.save();
      setSuccess("Bio saved successfully.");
    } catch (error: any) {
      setError(error.message);
    }
  }

  const onLogout = async () => {
    router.replace("/(auth)/login");
    await parse.User.logOut();
  }

  return (
    <Container>
      {!isParseLoaded ? (
        <ActivityIndicator
          size="large"
          animating={true}
        />
      ) : (
        <>
          {/* ... */}
        </>
      )}
    </Container>
  );
}

N’oubliez pas de modifier les TODO dans l’appel de retour. Utilisez {parseUser !.getUsername()} et {parseUser !.getEmail()}.

À ce stade, l’application devrait fonctionner pleinement. Redémarrez le serveur de développement et testez-le en créant un compte, en vous connectant, en vous déconnectant et en changeant votre bio. Enfin, assurez-vous que les changements sont reflétés dans la base de données.

Conclusion

En conclusion, vous savez maintenant ce qu’est l’authentification, quels sont ses avantages et comment elle se compare à l’autorisation.

En outre, vous avez appris à configurer l’authentification Back4app et à l’intégrer à une application React Native (basée sur Expo).

Prochaines étapes

  1. En savoir plus sur l’authentification sociale avec Google, Facebook et Apple
  2. Regardez Back4app Admin App pour un panneau d’administration en temps réel.

Le code source final est disponible sur GitHub.


Leave a reply

Your email address will not be published.