> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Découvrez les différences entre l’utilisation du stockage de données Auth0 et d’une base de données externe pour stocker les données des utilisateurs.

# Stockage des données des utilisateurs

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

Auth0 stocke les renseignements sur les utilisateurs de votre tenant dans une base de données infonuagique hébergée, ou vous pouvez choisir de stocker les données utilisateur dans votre propre base de données externe personnalisée.

Pour stocker des données utilisateur au-delà des renseignements de base qu’Auth0 utilise pour l’authentification, vous pouvez utiliser le magasin de données Auth0 ou une base de données personnalisée. Toutefois, si vous utilisez ces données supplémentaires à des fins d’authentification, nous vous recommandons d’utiliser le magasin de données Auth0, car cela vous permet de gérer vos données utilisateur à partir du [tableau de bord de gestion Auth0](https://manage.auth0.com/#).

<div id="external-database-vs-auth0-data-store">
  ## Base de données externe ou magasin de données Auth0
</div>

Le magasin de données Auth0 est conçu spécialement pour les données d’authentification. Il ne faut stocker autre chose que les renseignements utilisateur par défaut que dans des cas limités. Voici pourquoi :

* **Évolutivité** : Le magasin de données Auth0 présente des limites d’évolutivité, et les données de votre application pourraient dépasser les seuils appropriés. En utilisant une base de données externe, vous gardez votre magasin de données Auth0 simple, tandis qu’une base de données externe plus efficace stocke les données supplémentaires;
* **Performance** : Vos données d’authentification sont probablement consultées moins souvent que vos autres données. Le magasin de données Auth0 n’est pas optimisé pour une utilisation à fréquence élevée; les données qui doivent être récupérées plus souvent devraient donc être stockées ailleurs;
* **Flexibilité** : Comme le magasin de données Auth0 a été conçu pour prendre en charge uniquement les profils utilisateur et les métadonnées qui y sont associées, vous êtes limité quant aux actions que vous pouvez effectuer sur la base de données. En utilisant des bases de données distinctes pour vos autres données, vous pouvez les gérer comme bon vous semble et effectuer des appels directs sans passer par l’<Tooltip tip="API de gestion : Un produit qui permet aux clients d’effectuer des tâches administratives." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=Management+API">API de gestion</Tooltip> d’Auth0.

Lorsqu’on confie l’authentification des utilisateurs à un fournisseur externe, il n’est généralement pas nécessaire de maintenir sa propre table utilisateurs/mots de passe. Cela dit, vous pourriez quand même vouloir associer les données de l’application aux utilisateurs authentifiés.

* Par exemple, vous pourriez avoir une table Users qui répertorie chaque utilisateur authentifié par Auth0. Chaque fois qu’un utilisateur ouvre une session, vous pourriez le rechercher dans la table. S’il n’existe pas, vous créeriez un nouvel enregistrement. S’il existe déjà, vous mettriez à jour tous les champs, ce qui reviendrait essentiellement à conserver une copie locale de toutes les données utilisateur.
* Autrement, vous pourriez stocker l’identifiant utilisateur dans chaque table ou collection qui contient des données associées à l’utilisateur. Il s’agit d’une approche plus simple, adaptée aux applications de plus petite taille.

<div id="user-data-storage-example-scenario">
  ## Exemple de scénario de stockage des données utilisateur
</div>

Auth0 fournit une application de démonstration — une application musicale mobile — qui illustre l’expérience utilisateur de bout en bout lorsqu’on utilise Auth0 avec une base de données externe personnalisée. Cette application de démonstration est une appli iOS créée à partir du [projet de démarrage Auth0 pour iOS](/fr-CA/docs/quickstart/native/ios-swift). Le backend utilise l’[API Node.js](/fr-CA/docs/quickstart/backend/nodejs).

Pour obtenir une vue d’ensemble de la structure de l’application, consultez le [scénario d’architecture Mobile + API](/fr-CA/docs/get-started/architecture-scenarios/mobile-api).

<div id="metadata">
  ### Métadonnées
</div>

<div id="app-metadata">
  #### Métadonnées de l’application
</div>

Les éléments de données suivants de notre application mobile de musique peuvent être stockés dans `app_metadata` :

* Le forfait d’abonnement de l’utilisateur
* Le droit de l’utilisateur (ou non) de modifier les listes de lecture en vedette

Ces deux éléments devraient être stockés dans `app_metadata` plutôt que dans `user_metadata`, puisqu’ils ne devraient pas pouvoir être modifiés directement par l’utilisateur.

<div id="user-metadata">
  #### Métadonnées de l’utilisateur
</div>

Les types de données suivants de notre application mobile de musique peuvent être stockés dans `user_metadata` :

* Préférences de l’application
* Éléments choisis par l’utilisateur pour personnaliser son expérience de l’application à la connexion.

Notez que, contrairement aux données de `app_metadata`, l’utilisateur peut facilement modifier celles stockées dans `user_metadata`.

Nous pouvons permettre à l’utilisateur de modifier son `displayName`, c’est-à-dire le nom qu’il voit à la connexion et qui est affiché aux autres utilisateurs de l’application.

Pour afficher l’identifiant choisi par l’utilisateur chaque fois qu’il se connecte, nous utilisons une règle pour récupérer la valeur `user.user_metadata`.

```javascript lines theme={null}
function(user, context, callback){
  user.user_metadata = user.user_metadata || {};
  user.user_metadata.displayName = user.user_metadata.displayName || "user";

  auth0.users.updateUserMetadata(user.user_id, user.user_metadata)
    .then(function(){
      callback(null, user, context);
    })
    .catch(function(err){
      callback(err);
    });
}
```

Voici l’écran que l’utilisateur utiliserait pour modifier son `displayName` :

<Frame>
  <img src="https://mintcdn.com/translations/Dcx0M11uuptU53TX/docs/images/cdy7uua7fh8z/33YxGQKYztHY3OM6mxJ4jN/0a06103e6b6455c2e1962a1f738b663a/4-settings.png?fit=max&auto=format&n=Dcx0M11uuptU53TX&q=85&s=55de886498d279cf6d10c1378391a7c0" alt="Écran des paramètres de l’application iOS avec une option permettant de mettre à jour le nom d’affichage." width="300" height="534" data-path="docs/images/cdy7uua7fh8z/33YxGQKYztHY3OM6mxJ4jN/0a06103e6b6455c2e1962a1f738b663a/4-settings.png" />
</Frame>

Pour enregistrer les modifications dans la base de données, l’application appelle le point de terminaison [Get a User](https://auth0.com/docs/api/management/v2#!/Users/get_users_by_id) de l’API de gestion afin de repérer l’utilisateur concerné :

<AuthCodeGroup>
  ```bash cURL lines theme={null}
  curl --request GET \
    --url https://%7ByourAccount%7D.auth0.com/api/v2/users/user_id \
    --header 'authorization: Bearer {yourIdToken}'
  ```

  ```csharp C# lines theme={null}
  var client = new RestClient("https://%7ByourAccount%7D.auth0.com/api/v2/users/user_id");
  var request = new RestRequest(Method.GET);
  request.AddHeader("authorization", "Bearer {yourIdToken}");
  IRestResponse response = client.Execute(request);
  ```

  ```go Go lines theme={null}
  package main

  import (
  	"fmt"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://%7ByourAccount%7D.auth0.com/api/v2/users/user_id"

  	req, _ := http.NewRequest("GET", url, nil)

  	req.Header.Add("authorization", "Bearer {yourIdToken}")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java lines theme={null}
  HttpResponse<String> response = Unirest.get("https://%7ByourAccount%7D.auth0.com/api/v2/users/user_id")
    .header("authorization", "Bearer {yourIdToken}")
    .asString();
  ```

  ```javascript Node.JS lines theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'GET',
    url: 'https://%7ByourAccount%7D.auth0.com/api/v2/users/user_id',
    headers: {authorization: 'Bearer {yourIdToken}'}
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP lines theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://%7ByourAccount%7D.auth0.com/api/v2/users/user_id",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
      "authorization: Bearer {yourIdToken}"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python lines theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  headers = { 'authorization': "Bearer {yourIdToken}" }

  conn.request("GET", "%7ByourAccount%7D.auth0.com/api/v2/users/user_id", headers=headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby lines theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://%7ByourAccount%7D.auth0.com/api/v2/users/user_id")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Get.new(url)
  request["authorization"] = 'Bearer {yourIdToken}'

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

Cela est suivi d’un appel au point de terminaison [Update a User](https://auth0.com/docs/api/management/v2#!/Users/patch_users_by_id) pour mettre à jour le champ `user_metadata` :

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url 'https://{yourDomain}/api/v2/users/user_id' \
    --header 'authorization: Bearer {yourAccessToken}' \
    --header 'content-type: application/json' \
    --data '{"user_metadata": {"displayName": "J-vald3z"}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/api/v2/users/user_id");
  var request = new RestRequest(Method.PATCH);
  request.AddHeader("authorization", "Bearer {yourAccessToken}");
  request.AddHeader("content-type", "application/json");
  request.AddParameter("application/json", "{"user_metadata": {"displayName": "J-vald3z"}", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/api/v2/users/user_id"

  	payload := strings.NewReader("{"user_metadata": {"displayName": "J-vald3z"}")

  	req, _ := http.NewRequest("PATCH", url, payload)

  	req.Header.Add("authorization", "Bearer {yourAccessToken}")
  	req.Header.Add("content-type", "application/json")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.patch("https://{yourDomain}/api/v2/users/user_id")
    .header("authorization", "Bearer {yourAccessToken}")
    .header("content-type", "application/json")
    .body("{"user_metadata": {"displayName": "J-vald3z"}")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'PATCH',
    url: 'https://{yourDomain}/api/v2/users/user_id',
    headers: {authorization: 'Bearer {yourAccessToken}', 'content-type': 'application/json'},
    data: '{"user_metadata": {"displayName": "J-vald3z"}'
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/api/v2/users/user_id",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "PATCH",
    CURLOPT_POSTFIELDS => "{"user_metadata": {"displayName": "J-vald3z"}",
    CURLOPT_HTTPHEADER => [
      "authorization: Bearer {yourAccessToken}",
      "content-type: application/json"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{"user_metadata": {"displayName": "J-vald3z"}"

  headers = {
      'authorization': "Bearer {yourAccessToken}",
      'content-type': "application/json"
      }

  conn.request("PATCH", "/{yourDomain}/api/v2/users/user_id", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/api/v2/users/user_id")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Patch.new(url)
  request["authorization"] = 'Bearer {yourAccessToken}'
  request["content-type"] = 'application/json'
  request.body = "{"user_metadata": {"displayName": "J-vald3z"}"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

Vous devez remplacer `{yourAccessToken}` par un [jeton d’accès à l’API de gestion](https://auth0.com/docs/api/management/v2/concepts/tokens).

<div id="user-data-permission-rules">
  ### Règles d’autorisation pour les données utilisateur
</div>

Utilisez les [règles](/fr-CA/docs/customize/rules) pour définir si un utilisateur peut modifier ou non les listes de lecture en vedette.

<div id="assign-playlist-editor-role">
  #### Attribuer le rôle Playlist Editor
</div>

La première règle envoie une requête à notre API Node, qui interroge ensuite la base de données connectée à Heroku pour vérifier combien de lectures la liste de lecture de l’utilisateur a obtenues. Si ce nombre est de 100 ou plus, nous ajoutons `playlist_editor` comme valeur dans le tableau `roles` de `app_metadata`.

```javascript lines expandable theme={null}
function (user, context, callback) {

  var request = require('request');

  user.app_metadata = user.app_metadata || {};
  user.app_metadata.roles = user.roles || [];

  var CLIENT_SECRET = configuration.AUTH0_CLIENT_SECRET;
  var CLIENT_ID = configuration.AUTH0_CLIENT_ID;

  var scope = {
    user_id: user.user_id,
    email: user.email,
    name: user.name
  };

  var options = {
    subject: user.user_id,
    expiresInMinutes: 600,
    audience: CLIENT_ID,
    issuer: 'https://example.auth0.com'
  };

  var id_token = jwt.sign(scope, CLIENT_SECRET, options);

  var auth = 'Bearer ' + id_token;

  request.get({
    url: 'https://example.com/playlists/getPlays',
    headers: {
       'Authorization': auth,
      'Content-Type': 'text/html'
    },
    timeout: 15000
  }, function(err, response, body){
    if (err)
      return callback(new Error(err));
    var plays = parseInt(body, 10);

    if (plays >= 100 && user.roles.indexOf('playlist_editor') < 0){
      user.app_metadata.roles.push('playlist_editor');
      auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
        .then(function(){
          callback(null, user, context);
        })
        .catch(callback);
    }

    else if (plays < 100 && user.roles.indexOf('playlist_editor') >= 0){
      user.app_metadata.roles = [];
      auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
        .then(function(){
          callback(null, user, context);
        })
        .catch(callback);
    }
    else{
      callback(null, user, context);
    }

  });

}
```

<div id="scope-parameter-specifies-role">
  #### Le paramètre scope précise le rôle
</div>

La deuxième règle récupère le champ `app_metadata` et assigne le tableau `roles` à un champ de l’objet utilisateur afin qu’il soit accessible sans avoir à appeler `app_metadata` dans l’application. Le paramètre `scope` peut ensuite préciser `roles` au moment de la connexion de l’utilisateur, sans inclure tout le contenu de `app_metadata` dans l’objet utilisateur :

```javascript lines theme={null}
function(user, context, callback) {
   if (user.app_metadata) {
      user.roles = user.app_metadata.roles;
   }
   user.roles = user.roles || [];
   callback(null, user, context);
}
```

Après avoir mis en place ces deux règles, l’application détermine si l’utilisateur est un éditeur de playlists ou non et adapte l’écran d’accueil en conséquence. Si `playlist_editor` figure dans le tableau `roles` enregistré dans le `app_metadata` de l’utilisateur, celui-ci sera accueilli comme un **ÉDITEUR** après s’être connecté :

<Frame>
  <img src="https://mintcdn.com/translations/eVsQcTnbClN-oB7d/docs/images/cdy7uua7fh8z/1WEKC4eWvm8GPK2BlodGFk/3eb36843f22518ace800fc1507bd5816/3-home.png?fit=max&auto=format&n=eVsQcTnbClN-oB7d&q=85&s=5ee92e1fda3ad7e69fb1990f1a60c8f1" alt="Exemple de page de profil utilisateur avec le rôle d’éditeur." width="300" height="534" data-path="docs/images/cdy7uua7fh8z/1WEKC4eWvm8GPK2BlodGFk/3eb36843f22518ace800fc1507bd5816/3-home.png" />
</Frame>

<div id="associate-a-users-music-with-the-user">
  #### Associer la musique à un utilisateur
</div>

Nous devons associer la musique d’un utilisateur à celui-ci, mais cette information n’est pas requise pour l’authentification. Voici comment stocker cette information dans une base de données distincte intégrée au backend de l’application.

L’identifiant unique de l’utilisateur est `user_id`, et il correspond à la propriété `sub` de l’objet `idTokenPayload` dans un `authResult`. Voici un exemple de ligne de la table `songs` dans notre base de données :

| song\_id | songname       | user\_id      |
| -------- | -------------- | ------------- |
| 1        | Number One Hit | google-oauth2 |

Le backend Node.js authentifie les requêtes vers l’URI utilisée pour récupérer les données personnelles de l’utilisateur depuis la base de données en validant un <Tooltip tip="JSON Web Token (JWT) : format standard de jeton d’identité (et souvent de jeton d’accès) utilisé pour transmettre de façon sécurisée des déclarations entre deux parties." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=JSON+Web+Token">JSON Web Token</Tooltip>.

[Pour en savoir plus sur l’authentification par jeton et sur l’implémentation de JWT dans vos applications.](/fr-CA/docs/secure/tokens/json-web-tokens)

Voici le code qui implémente la validation des JWT dans le projet de démarrage Node.js :

```javascript lines theme={null}
var genres = require('./routes/genres');
var songs = require('./routes/songs');
var playlists = require('./routes/playlists');
var displayName = require('./routes/displayName');

var authenticate = jwt({
  secret: process.env.AUTH0_CLIENT_SECRET,
  audience: process.env.AUTH0_CLIENT_ID
});

app.use('/genres', authenticate, genres);
app.use('/songs', authenticate, songs);
app.use('/playlists', authenticate, playlists);
app.use('/displayName', authenticate, displayName);
```

Nous pouvons ajouter des fonctionnalités pour traiter différentes requêtes de données provenant de notre application. Par exemple, si nous recevons une requête `GET` à `/secured/getFavGenre`, l’API appelle la fonction `queryGenre()`, qui interroge la base de données et renvoie le genre préféré de l’utilisateur.

```swift lines theme={null}
@IBAction func getGenre(sender: AnyObject) {
        let request = buildAPIRequest("/genres/getFav", type:"GET")
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {[unowned self](data, response, error) in
            let genre = NSString(data: data!, encoding: NSUTF8StringEncoding)
            dispatch_async(dispatch_get_main_queue(), {
                self.favGenre.text = "Favorite Genre:  \(genre!)"
            })
        }
        task.resume()
    }
```

La fonction `buildAPIRequest()` prend en paramètres le chemin d’accès et la méthode HTTP de la requête, puis construit celle-ci à partir de l’URL de base de notre API Node.js hébergée sur Heroku.

Dans l’application, la fonction `getGenre()` envoie une requête à l’API et modifie l’interface pour afficher la réponse à la requête envoyée à `/genres/getFav`. Le backend récupère les données nécessaires à cette action à l’aide de la fonction `queryGenre()` et renvoie les résultats à l’application :

```javascript lines theme={null}
function queryGenre(user_id, res){

  db.connect(process.env.DATABASE_URL, function(err, client) {
  if (err) throw err;

  client
    .query('SELECT fav_genre as value FROM user_data WHERE user_id = $1', [user_id], function(err, result) {

      if(err) {
        return console.error('error running query', err);
      }
      res.send(result.rows[0].value);
    });
  });

};
```

<div id="learn-more">
  ## En savoir plus
</div>

* [Profils d’utilisateurs normalisés](/fr-CA/docs/manage-users/user-accounts/user-profiles/normalized-user-profiles)
* [Schéma de profil d’utilisateur normalisé](/fr-CA/docs/manage-users/user-accounts/user-profiles/normalized-user-profile-schema)
* [Exemples de profils d’utilisateurs](/fr-CA/docs/manage-users/user-accounts/user-profiles/sample-user-profiles)
