Come aggiungere l’autenticazione a un’applicazione React Native?

Copertura per l'autenticazione di React Native (Expo)

L’autenticazione è un componente fondamentale di quasi tutte le app.

Questo articolo pratico fornisce una guida passo-passo per iniziare a utilizzare l’autenticazione di React Native.

Inoltre, descriverà le basi dell’autenticazione, il suo confronto con l’autorizzazione, il flusso di autenticazione e i vantaggi del suo utilizzo.

Che cos’è l’autenticazione?

L’autenticazione è il processo di verifica dell’identità di una persona. In generale, esistono tre modi di autenticazione: o con:

  1. Qualcosa che si conosce (ad es. password, PIN)
  2. Qualcosa in vostro possesso (ad es. cellulare, chiavi)
  3. Qualcosa che si è (ad es. impronte digitali, iride)

La maggior parte delle applicazioni utilizza la prima opzione, ma molte di esse ne combinano diverse per aumentare il livello di sicurezza. Questo concetto è chiamato autenticazione a più fattori (MFA).

Flusso di autenticazione

Il flusso di autenticazione generico funziona così:

  1. L’utente invia la propria password al server.
  2. Il server esegue l’hash della password e la confronta con l’hash della password nel database.
  3. Se gli hash corrispondono, il server crea una sessione e invia il token di sessione all’utente. Se invece gli hash non corrispondono, viene segnalato un errore.
  4. L’utente utilizza quindi il token di sessione per ogni richiesta. A ogni richiesta, il server controllerà se il token è presente e valido.

Il flusso sopra descritto è la cosiddetta autenticazione tramite token. Altri sistemi di autenticazione sono JSON Web Token (JWT), autenticazione di accesso di base, social login e così via.

Autenticazione vs. Autorizzazione

L’autenticazione è l’atto di verificare l’identità di un utente, mentre l’autorizzazione è l’atto di verificare se un utente ha i permessi sufficienti per eseguire un’azione.

I modelli di autorizzazione comprendono, tra gli altri, il controllo dell’accesso obbligatorio (MAC), il controllo dell’accesso discrezionale (DAC) e l’autorizzazione basata sui ruoli.

Vantaggi dell’autenticazione

Vediamo alcuni vantaggi dell’uso dell’autenticazione nelle vostre applicazioni mobili.

Sicurezza

L’autenticazione può proteggere la vostra applicazione da accessi non autorizzati e garantire che solo gli utenti legittimi abbiano accesso al vostro servizio.

Questo aiuta a prevenire le violazioni dei dati e gli attacchi informatici e a mantenere l’ambiente dell’applicazione sicuro e affidabile.

Personalizzazione

L’autenticazione consente di personalizzare l’esperienza dell’utente all’interno dell’applicazione. Quando gli utenti effettuano il login, possono accedere a impostazioni, preferenze e raccomandazioni personalizzate in base alle loro esigenze.

Questa personalizzazione rende l’app più coinvolgente e facile da usare. Aiuta a fidelizzare gli utenti fornendo un’esperienza più pertinente e piacevole.

Requisiti legali

Le leggi di alcuni Paesi richiedono di verificare l’identità degli utenti. Un esempio è il Know Your Customer (KYC).

Quasi tutte le app finanziarie sono obbligate a farlo. È necessario disporre di un sistema di autenticazione adeguato per conformarsi a queste normative o per proteggere le informazioni personali degli utenti.

Come aggiungere l’autenticazione a un’applicazione React Native?

Questa parte dell’articolo fornirà una guida passo passo sull’aggiunta dell’autenticazione Back4app a un’applicazione React Native(Expo).

Prerequisiti

  • Conoscenza di base del Backend as a Service (BaaS)
  • IDE JavaScript, Node.js e un emulatore mobile o un dispositivo fisico.
  • Capacità di leggere e scrivere codice JavaScript
  • Esperienza con React Native ed Expo
  • Un account Back4app gratuito

Che cos’è Back4app?

Back4app è una delle migliori soluzioni open-source di Backend as a Service (BaaS). È una piattaforma matura e affidabile che esiste dal 2015.

Le sue caratteristiche principali includono database in tempo reale, funzioni di Cloud Code, generazione automatica di API RESTful/GraphQL e altro ancora!

Back4app dispone di una dashboard di amministrazione facile e intuitiva e di un’interfaccia a riga di comando (CLI) per gli utenti più avanzati.

Fornisce inoltre SDK per i linguaggi di programmazione e i framework più diffusi, come JavaScript, PHP, Flutter e Dart.

La parte migliore è che Back4app offre un livello gratuito. Il livello gratuito è ottimo per i test e i prototipi e include quanto segue:

  • 25k/richieste mensili
  • 250 MB di memoria dati
  • 1 GB di trasferimento dati
  • 1 GB di memoria per i file

Perché utilizzare Back4app?

  • Supporta l’autenticazione sociale
  • Fornisce SDK per la maggior parte dei linguaggi di programmazione e dei framework.
  • Facile da configurare e utilizzare
  • Assistenza clienti eccellente

Per sapere come l’autenticazione di Back4app si confronta con quella di Firebase, date un’occhiata a The Ultimate Guide to React Firebase Authentication.

Introduzione al progetto – Iniziare con l’autenticazione in React Native

Costruiremo un’applicazione React Native pronta per la produzione che utilizza l’autenticazione Back4app. L’applicazione consentirà agli utenti di registrarsi, accedere e gestire i propri profili.

Inoltre, l’applicazione avrà due schede di navigazione, una per gli utenti autenticati e l’altra per gli utenti non autenticati.

Il prodotto finale avrà un aspetto simile a questo:

Back4app Autenticazione App React Native

Iniziamo a codificare!

Backend (Back4app)

In questa sezione, creeremo un’applicazione Back4app, estenderemo il modello utente predefinito e otterremo le chiavi API necessarie per connetterci al backend.

Creare un’applicazione

Per prima cosa, accedete al vostro account Back4app o createne uno se non lo avete ancora.

Una volta effettuato l’accesso, si verrà reindirizzati all’elenco delle app. Fare clic su “Crea nuova app” per creare una nuova app.

Back4app Elenco applicazioni

La piattaforma Back4app consente di distribuire due tipi di applicazioni: Backend as a Service (BaaS) o Containers as a Service (CaaS). L’autenticazione è inclusa nel BaaS, quindi selezionatela.

Back4app Backend as a Service Seleziona

Quindi, date alla vostra applicazione un nome descrittivo, lasciate il database come NoSQL e fate clic su “Crea”.

Configurazione dell'app Back4app

Attendere circa due minuti affinché la piattaforma crei l’applicazione. Back4app si occuperà di tutto, dalla creazione del livello dell’app all’impostazione del database, della sicurezza, della scalabilità e altro ancora.

Una volta fatto, si verrà reindirizzati all’interfaccia del database.

Vista del database di Back4app

Modifica del database

Parliamo poi delle classi del database.

Ogni classe di database Back4app è dotata dei seguenti campi predefiniti:

+-----------+------------+-----------------------------------------+
| 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 Utente è dotata di alcuni campi aggiuntivi:

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

La classe utente predefinita di Back4app dovrebbe andare bene per la maggior parte dei casi d’uso. Tuttavia, è facile estenderla. Per dimostrare come si fa, aggiungiamo un campo biografia(bio).

Per prima cosa, fare clic sul pulsante “+ Colonna” sopra la tabella del database.

Back4app Database Aggiungi colonna

Nel modulo di creazione della colonna, selezionare “String” come tipo di dato, impostare il nome su bio, renderlo obbligatorio e fare clic su “Aggiungi”.

Back4app Aggiungi campo database

Bene, ora sapete come funzionano le classi del database di Back4app e come estendere il modello utente.

Chiavi API

È necessario ottenere le chiavi API della propria applicazione per connettersi al backend dal frontend.

Per ottenerli, accedere all’applicazione Back4app e selezionare “Sicurezza e chiavi” nella barra laterale. Prendere nota di “Client key” e “JavaScript key”.

Chiavi API di Back4app

Bene, questo è tutto dal lato del backend.

Frontend (React Native)

In questa sezione creeremo un’applicazione Expo, installeremo una libreria di componenti, imposteremo la navigazione, ci occuperemo delle schermate e infine collegheremo il frontend con il backend.

Creare un’applicazione

Per creare un’applicazione React Native, utilizzeremo l’utility create-expo-app. Questa utility semplifica la creazione di applicazioni React Native, generando la struttura delle cartelle, configurando TypeScript, ecc.

Per prima cosa, eseguire i seguenti comandi:

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

Questo comando installerà anche create-expo-app, se non lo avete ancora.

Si noterà che il progetto bootstraped ha la seguente struttura di cartelle:

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
├── ...    

Avviare il server di sviluppo:

$ npx expo start

Infine, premere A per aprire l’applicazione sull’emulatore Android. In alternativa, è possibile utilizzare un emulatore iOS o un dispositivo iOS fisico. Una volta aperta l’app, si dovrebbe vedere la schermata predefinita di Expo.

Schermata predefinita dell'Expo

React Native Paper

Per semplificare il processo di sviluppo dell’interfaccia utente, utilizzeremo React Native Paper.

React Native Paper è una libreria di componenti di alta qualità e facile da usare per applicazioni React Native. Fornisce molti componenti predefiniti che coprono quasi tutti i casi d’uso.

Si inizia con l’installazione tramite NPM:

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

Se state costruendo per iOS, dovrete anche collegare parti native della libreria:

npx pod-install

Quindi, configurare Babel per non includere i componenti inutilizzati nella produzione:

// babel.config.js

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

Quindi navigare in app/_layout.tsx e avvolgere l’applicazione in PaperProvider in questo modo:

// 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>
  );
}

Non dimenticate l’importazione all’inizio del file:

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

Perfetto, abbiamo installato con successo la libreria dei componenti.

Contenitore

Un’altra cosa da fare è creare un componente Container. Questo componente sarà utilizzato in tutte le nostre schermate e aggiungerà un margine su tutti i lati, in modo che il contenuto non arrivi al bordo dello schermo.

Creare un file Container.tsx nella cartella 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>
  );
}

Navigazione e schermate

Come accennato nell’introduzione al progetto, la nostra applicazione avrà due schede di navigazione.

Una è per gli utenti autenticati e l’altra per gli utenti non autenticati. La scheda autenticata consentirà agli utenti di gestire i propri profili, mentre l’altra permetterà di accedere o creare un account.

Per ottenere questo risultato, creare innanzitutto la seguente struttura di directory:

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

Per ulteriori informazioni su Expo Router, consultate i documenti ufficiali.

I layout delle Expo contengono generalmente molto codice di base. Non voglio sommergere l’articolo di codice, quindi vi invito a prelevare il contenuto dei file da GitHub:

  1. (auth)/_layout.tsx
  2. (schede)/_layout.tsx
  3. layout.tsx

Procedendo, inserite quanto segue in 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>
  );
}

Il file index.tsx è il punto di ingresso dell’applicazione. In esso, si verifica se l’utente è autenticato e lo si reindirizza di conseguenza. Per ora, il reindirizzamento si basa sulla variabile isAuthenticated.

Poi prendete il codice per le schermate:

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

Il codice delle schermate è piuttosto semplice. È codice React Native che utilizza React Native Paper per creare i moduli e altre interfacce utente. Utilizza anche gli hook di base di React, come useState() e useEffect().

SDK Parse

Per connetterci al backend useremo Parse SDK. L’SDK offre metodi per la memorizzazione e la manipolazione dei dati, l’autenticazione degli utenti e altre funzioni.

Per prima cosa, installarlo tramite NPM:

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

Abbiamo anche installato il pacchetto @react-native-async-storage/async-storage per persistere la sessione utente alla chiusura dell’applicazione. Senza di esso, gli utenti dovrebbero autenticarsi ogni volta che aprono l’applicazione.

Creare quindi un file .env nella radice del progetto in questo modo:

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

Assicurarsi di sostituire <your-back4app-application-id> e <your-back4app-client-key> con le chiavi API ottenute nella sezione backend dell’articolo.

Inizializzare Parse in _layout.tsx in questo modo:

// 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!"));

// ...

Abbiamo anche incluso la funzione testParse(), che testa la connessione a Back4app aggiungendo un messaggio “Hello, world!” al database. Per verificare che la connessione funzioni, riavviare il server Expo ed eseguire l’applicazione nell’emulatore.

Messaggio di prova del database di Back4app

Passare alla vista del database dell’applicazione e verificare se il messaggio è visibile.

Se si ottiene un errore che dice “Errore: crypto.getRandomValues() non supportato”. Installare le seguenti dipendenze:

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

Quindi aggiungere l’importazione all’inizio di _layout.tsx (prima di importare Parse):

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

Riavviare il server di sviluppo; tutto dovrebbe funzionare bene.

Per avere l’istanza di Parse disponibile in tutte le schermate, la passeremo utilizzando React Context.

Per prima cosa, creare una cartella context e inserirvi il seguente file parseContext.ts:

import {createContext} from "react";

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

export default ParseContext;

Quindi avvolgere l’intera applicazione con essa, passando l’istanza di Parse:

// app/_layout.tsx

// ...

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

Recupero e manipolazione dei dati

In quest’ultima sezione, useremo Parse SDK per autenticare l’utente e recuperare le sue informazioni.

Invece di ripetere lo stesso codice in ogni schermata, creeremo un hook useParse. Questo hook recupererà l’istanza di Parse dal contesto, otterrà le informazioni sull’utente e attiverà un aggiornamento una volta che tutto è pronto.

Creare un nuovo file chiamato useParse.ts nella cartella del contesto:

// 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};
}

Quindi modificare index.tsx sostituendo isAuthenticated con un controllo effettivo della sessione:

// 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 (
    // ...
  );
}

Quindi, modificare login.tsx per accedere all’utente:

// 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 (
    // ...
  );
}

Quindi modificare il file register.tsx in modo simile a login.tsx, ma questa volta sostituendo il TODO in questo modo:

// 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);
}

Modificare infine profile.tsx per visualizzare le informazioni sul profilo:

// 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>
  );
}

Ricordarsi di modificare i TODO nella chiamata di ritorno. Utilizzare {parseUser!.getUsername()} e {parseUser!.getEmail()}.

A questo punto, l’applicazione dovrebbe funzionare completamente. Riavviare il server di sviluppo e testarlo creando un account, accedendo, uscendo e cambiando la propria biografia. Infine, assicurarsi che le modifiche si riflettano nel database.

Conclusione

In conclusione, ora sapete cos’è l’autenticazione, i suoi vantaggi e come si confronta con l’autorizzazione.

Inoltre, avete imparato a impostare l’autenticazione Back4app e a integrarla con un’applicazione React Native (basata su Expo).

Passi futuri

  1. Scoprite l’autenticazione sociale con Google, Facebook e Apple.
  2. Guardate l’App Back4app Admin per un pannello di amministrazione in tempo reale di grande qualità

Il codice sorgente finale è disponibile su GitHub.


Leave a reply

Your email address will not be published.