¿Cómo asegurar sus claves API con Firebase Functions?


Avatar de Pedro Cortez

Asegurar sus claves API puede parecer algo secundario cuando se está desarrollando una aplicación por primera vez, pero es algo realmente importante. En este artículo, le explico cómo almacenar sus claves de manera segura con Firebase.


asegurar clave api flutter

¿Por qué asegurar sus claves API en el backend en lugar de dejarlas en el frontend?

Si necesita realizar solicitudes HTTP que requieran una clave API, dejarla en el código del frontend es una mala práctica por varias razones:

  • Exposición pública: Aunque el usuario promedio no tenga interés en hacerlo, cualquiera puede inspeccionar su código y encontrar sus claves. Esto expone sus servicios a un riesgo de abuso, como superar los límites de uso o realizar llamadas maliciosas.
  • Seguridad de los datos: Una clave API no asegurada puede servir como un punto de entrada para acceder a los datos almacenados en su backend.
  • Gestión de accesos: Usando un backend, puede controlar con precisión los permisos y limitar el acceso a la clave según las necesidades reales.

¿La solución? Almacenar y gestionar sus claves API en un entorno seguro, como Firebase Functions, y exponer solo los datos que se mostrarán en el frontend.

¿Cómo almacenar su clave en Firebase utilizando firebase functions:secrets:accessor add API_KEY?

Firebase ofrece un sistema de gestión de secretos que permite asegurar sus claves sensibles y almacenarlas en el backend, en lugar de en su código fuente. Aquí están los pasos a seguir:

  1. Si aún no lo ha hecho, inicialice Firebase Functions en su proyecto Flutter con el comando:
firebase init functions

Si necesita ayuda, describo más detalles sobre los pasos necesarios para instalar funciones en la nube en su proyecto Flutter.

2. Añada un «secreto» en Firebase con el siguiente comando:

firebase functions:secrets:set API_KEY

Puede reemplazar API_KEY por otro nombre, siguiendo esta notación. Se le pedirá que ingrese el valor de su clave API. No se preocupe si el texto permanece invisible, esto es completamente normal.

Si aparece un mensaje de «Actualización disponible» en el terminal, simplemente actualice la CLI de Firebase con el comando npm install -g firebase-tools

3. Finalmente, podrá agregar una capa adicional de seguridad con el siguiente comando:

firebase functions:secrets:accessor add API_KEY

Esto asegura que solo las funciones autorizadas puedan acceder a la clave.

¿Cómo acceder a su clave para usarla?

Ahora que su clave está almacenada en el backend, podrá acceder a ella en Firebase para realizar sus solicitudes HTTP. El uso común es hacer la llamada desde Firebase, pero supongamos que quiero recuperarla para mostrarla en mi frontend. Aquí está cómo hacerlo:

Para comenzar, vamos a crear una función en la nube para acceder a la clave secreta que acabamos de crear:

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

const OpenAIApiKey = defineSecret("API_KEY");

// Función de Firebase para enviar la clave API al frontend
export const getApiKey = functions.https.onRequest(
  {secrets: [OpenAIApiKey]},
  async (req, res) => {
    try {
      // Recuperar la clave API desde 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;
      }

      // Enviar la clave API como respuesta (solo para fines educativos)
      res.status(200).json({apiKey});
    } catch (error) {
      console.error("Error retrieving API key:", error);
      res.status(500).send("Internal Server Error");
    }
  }
);

Generalmente, se añadirá una capa adicional de seguridad permitiendo solo a los usuarios autenticados acceder a la función y limitando el número de tokens utilizables para la solicitud HTTP.

Aquí está el código para mostrar nuestra clave en el frontend (una vez más, esta no es la manera correcta de usar su clave, pero es solo para el ejemplo):

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>"; // Reemplace por la URL de su función
    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),
        ),
      ),
    );
  }
}

¿Dónde encontrar la URL de mi función Cloud?

Puede encontrar la URL de su función en la nube yendo a Firebase, luego a Functions, y haciendo clic en «Estadísticas de uso detalladas» para la función que le interesa. El enlace se encuentra en la parte superior, en el centro de la pantalla.

Avatar de Pedro Cortez