Comment sécuriser ses clés API avec Firebase Functions ?


Avatar de Pierre Courtois

Sécuriser vos clés API peut paraitre secondaire quand on code une application pour la première fois et est portant quelque chose de très important. Dans cet article, je vous explique comment stocker vos clés de manière sécurisée avec Firebase.


Stocker clé API flutter

Pourquoi sécuriser ses clés API en back-end plutôt que de les laisser en front ?

Si vous avez besoin de faire des requêtes HTTP qui requière une clé API, la laisser dans le code front-end est une mauvaise pratique pour plusieurs raisons :

  1. Exposition publique : Même si l’utilisateur moyen n’a aucun intérêt à le faire, n’importe qui peut inspecter votre code et trouver vos clés. Cela expose vos services à un risque d’abus, comme le dépassement des quotas ou des appels malveillants.
  2. Sécurité des données : Une clé API non sécurisée peut servir de point d’entrée pour accéder aux données qui sont stockées dans votre backend.
  3. Gestion des accès : En utilisant un backend, vous pouvez contrôler finement les permissions et limiter l’accès à la clé en fonction des besoins réels.

La solution ? Stocker et gérer vos clés API dans un environnement sécurisé, comme Firebase Functions, et n’exposer que les données qui vont être affichées en front-end.

Comment stocker sa clé dans Firebase en utilisant firebase functions:secrets:accessor add API_KEY ?

Firebase offre un système de gestion de secrets qui permet de sécuriser vos clés sensibles et de les stocker en back-end, plutôt que dans votre code Dqrt. Voici les étapes à suivre.

  1. Si ce n’est pas encore fait, initialisez Firebase Functions dans votre projet Flutter, avec la commande :
firebase init functions

Si vous avez besoin d’aide, je décris plus en détails toutes les étapes à suivre pour installer les fonctions cloud sur son projet Flutter.

2. Ajoutez un « secret » dans Firebase, avec la commande

firebase functions:secrets:set API_KEY //Vous pouvez remplacer API_KEY par un autre nom, en suivant bien cette notation.

Vous allez alors être invité à entrer la valeur de votre clé API. Ne vous inquiétez pas si le texte reste invisible, cela est tout à fait normal.

Si un message « Update available » s’affiche dans le terminal, mettez simplement la CLI Firebase à jour avec la commande npm install -g firebase-tools.

3. Enfin, vous pouvez vérifier que votre clé a été conservée correctement en lançant la fonction :

firebase functions:secrets:access API_KEY //Remplacer par le nom de votre secret

Comment accéder à sa clé pour l’utiliser ?

Maintenant que votre clé est stockée en back-end, vous allez pouvoir y accéder dans Firebase pour réaliser vos requêtes HTTP. L’usage courant est de faire l’appelle dans Firebase, mais admettons qu’ici je souhaite la récupérer pour l’afficher dans mon front. Voici comment faire :

Pour commencer, on va créer une fonction cloud, pour accéder à la clé secrète que l’on vient de créer :

import * as functions from "firebase-functions";
import {defineSecret} from "firebase-functions/params";

const OpenAIApiKey = defineSecret("API_KEY");

// Fonction Firebase pour renvoyer la clé API au frontend
export const getApiKey = functions.https.onRequest(
  {secrets: [OpenAIApiKey]},
  async (req, res) => {
    try {
      // Récupération de la clé API depuis Firebase Secrets
      const apiKey = await OpenAIApiKey.value();
      console.log("API key retrieved:", apiKey);

      if (!apiKey) {
        res.status(500).send("Internal Server Error: API key is missing");
        return;
      }

      // Envoyer la clé API en réponse (à ne faire qu'à titre éducatif)
      res.status(200).json({apiKey});
    } catch (error) {
      console.error("Error retrieving API key:", error);
      res.status(500).send("Internal Server Error");
    }
  }
);

Généralement, on va ajouter une autre couche de sécurité en n’autorisant que les utilisateurs authentifiés à accéder à la fonction et en limitant le nombre de tokens utilisables pour la requête HTTP.

Voici ensuite un code qui va afficher notre clé en front end (Encore une fois, ce n’est pas la manière correcte d’utiliser votre clé, mais c’est pour l’exemple) :

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ApiKeyDemo(),
    );
  }
}

class ApiKeyDemo extends StatefulWidget {
  @override
  _ApiKeyDemoState createState() => _ApiKeyDemoState();
}

class _ApiKeyDemoState extends State<ApiKeyDemo> {
  String _apiKey = "Fetching...";

  @override
  void initState() {
    super.initState();
    _fetchApiKey();
  }

  Future<void> _fetchApiKey() async {
    final url = "https://<your-cloud-function-url>"; //Remplacer par l'Url de votre fonction
    final response = await http.get(Uri.parse(url));

    if (response.statusCode == 200) {
      setState(() {
        _apiKey = json.decode(response.body)['apiKey'];
      });
    } else {
      setState(() {
        _apiKey = "Error fetching API Key";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Firebase API Key Demo")),
      body: Center(
        child: Text(
          "API Key: $_apiKey",
          style: TextStyle(fontSize: 18),
        ),
      ),
    );
  }
}

Où trouver l’URL de ma fonction cloud ?

Vous trouverez l’Url de votre fonction cloud, en vous rendant dans Firebase, Functions, puis en cliquant sur « Statistiques d’utilisation détaillées », pour la fonction qui vous intéresse. Le lien se trouve en haut, au centre de l’écran.

Avatar de Pierre Courtois