Migra de las APIs de FCM heredadas a HTTP v1

Las apps que usan las APIs heredadas de FCM para HTTP y XMPP deben migrar a la API de HTTP v1 lo antes posible. El envío de mensajes (incluidos los mensajes upstream) con esas APIs dejó de estar disponible el 20 de junio de 2023 y la baja ocurrirá el 22 de julio de 2024.

Obtén más información sobre las funciones afectadas específicas.

Además de la compatibilidad continua y las funciones nuevas, la API de HTTP v1 tiene estas ventajas sobre las APIs heredadas:

  • Mejor seguridad mediante tokens de acceso: La API de HTTP v1 usa tokens de acceso de corta duración según el modelo de seguridad OAuth2. Si un token de acceso se vuelve público, solo se puede usar de manera indebida durante aproximadamente una hora antes de que se venza. Los tokens de actualización no se transmiten tan seguido como las llaves de seguridad que usan las APIs heredadas, por lo que es menos probable que los capturen.

  • Personalización más eficiente de los mensajes en todas las plataformas: Para el cuerpo del mensaje, la API de HTTP v1 tiene claves comunes que van a todas las instancias a las que se orientan y claves específicas para personalizar el mensaje en todas las plataformas. Esto te permite crear versiones de “anulación” que envían cargas útiles diferentes a otras plataformas cliente en un solo mensaje.

  • Nuevas versiones de plataformas cliente más preparadas para el futuro y extensibles: La API de HTTP v1 admite todas las opciones de mensajería disponibles en la Web, en Android y en las plataformas de Apple. FCM puede extender la API a versiones y plataformas nuevas según sea necesario, ya que cada plataforma tiene su propio bloque definido en la carga útil JSON.

Actualiza el extremo del servidor

A continuación, se detallan las características de la URL de extremo de la API de HTTP v1 que la diferencian de los extremos heredados:

  • Cuenta con la versión /v1 en la ruta.
  • La ruta contiene el ID del proyecto de Firebase de la app en el formato /projects/myproject-ID/. Puedes encontrar este ID en la pestaña Configuración general del proyecto de Firebase console.
  • Especifica de manera explícita el método send como :send.

Si deseas actualizar el extremo del servidor para HTTP v1, agrega estos elementos al extremo del encabezado de las solicitudes de envío.

Solicitudes HTTP anteriores

POST https://fcm.googleapis.com/fcm/send

Solicitudes XMPP anteriores

Los mensajes XMPP heredados se envían a través de una conexión al siguiente extremo:

fcm-xmpp.googleapis.com:5235

Después

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send

Actualiza la autorización de solicitudes de envío

Las solicitudes de envío de HTTP v1 requieren un token de acceso de OAuth 2.0 en lugar de la string de la clave del servidor que se usa en las solicitudes heredadas. Si usas el SDK de Admin para enviar mensajes, la biblioteca administrará el token por ti. Si usas el protocolo sin procesar, debes obtener el token como se describe en esta sección y agregarlo al encabezado como Authorization: Bearer <valid Oauth 2.0 token>.

Antes

Authorization: key=AIzaSyZ-1u...0GBYzPu7Udno5aA

Después

Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

En función de los detalles del entorno del servidor, usa una combinación de las siguientes estrategias para autorizar las solicitudes del servidor a los servicios de Firebase:

  • Credenciales predeterminadas de la aplicación (ADC) de Google
  • Un archivo JSON de una cuenta de servicio
  • Un token de acceso de OAuth 2.0 de corta duración de una cuenta de servicio

Si la aplicación se ejecuta en Compute Engine, Google Kubernetes Engine, App Engine o Cloud Functions (incluido Cloud Functions for Firebase), usa el servicio de credenciales predeterminadas de la aplicación (ADC). ADC usa tu cuenta de servicio predeterminada existente para obtener credenciales y autorizar solicitudes. Además, permite realizar pruebas locales flexibles a través de la variable de entorno GOOGLE_APPLICATION_CREDENTIALS. Si deseas lograr la automatización más completa del flujo de autorización, usa ADC y las bibliotecas de servidor del SDK de Admin.

Si la aplicación se ejecuta en un entorno de servidor que no es de Google, deberás descargar un archivo JSON de una cuenta de servicio desde el proyecto de Firebase. Puedes usar la variable de entorno GOOGLE_APPLICATION_CREDENTIALS para autorizar solicitudes con las credenciales que obtuviste de forma manual, siempre y cuando tengas acceso a un sistema de archivos que contenga el archivo de claves privadas. De lo contrario, debes hacer referencia al archivo de la cuenta de servicio en el código. Este proceso se debe realizar con mucho cuidado para evitar exponer tus credenciales.

Proporciona credenciales con ADC

El servicio de credenciales predeterminadas de la aplicación (ADC) de Google revisa tus credenciales en el siguiente orden:

  1. ADC verifica si se configuró la variable de entorno GOOGLE_APPLICATION_CREDENTIALS. Si está configurada, ADC usa el archivo de cuenta de servicio al que hace referencia la variable.

  2. Si no se configuró la variable de entorno, ADC usa la cuenta de servicio predeterminada que Compute Engine, Google Kubernetes Engine, App Engine y Cloud Functions proporcionan para las aplicaciones que se ejecutan en esos servicios.

  3. Si ADC no puede usar ninguna de las credenciales mencionadas, el sistema arrojará un error.

En el siguiente ejemplo de código del SDK de Admin, se muestra esta estrategia, pero no se especifican las credenciales de la aplicación de forma explícita. Sin embargo, ADC puede encontrar las credenciales de forma implícita siempre que la variable de entorno esté configurada o que la aplicación se ejecute en Compute Engine, Google Kubernetes Engine, App Engine o Cloud Functions.

Node.js

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
});

Java

FirebaseOptions options = FirebaseOptions.builder()
    .setCredentials(GoogleCredentials.getApplicationDefault())
    .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
    .build();

FirebaseApp.initializeApp(options);

Python

default_app = firebase_admin.initialize_app()

Go

app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

C#

FirebaseApp.Create(new AppOptions()
{
    Credential = GoogleCredential.GetApplicationDefault(),
});

Proporciona credenciales de forma manual

Los proyectos de Firebase son compatibles con las cuentas de servicio de Google, por lo que puedes llamar a las APIs del servidor de Firebase desde tu servidor de apps o un entorno de confianza. Si desarrollas código o implementas tu aplicación de manera local, puedes usar las credenciales obtenidas mediante la cuenta de servicio para autorizar las solicitudes del servidor.

Para autenticar una cuenta de servicio y autorizar su acceso a los servicios de Firebase, debes generar un archivo de claves privadas en formato JSON.

Sigue estos pasos a fin de generar un archivo de claves privadas para la cuenta de servicio:

  1. En la consola de Firebase, abre Configuración > Cuentas de servicio.

  2. Haz clic en Generar nueva clave privada y luego en Generar clave para confirmar.

  3. Almacena de forma segura el archivo JSON que contiene la clave.

Cuando autorices mediante una cuenta de servicio, tienes dos opciones para proporcionar las credenciales a la aplicación. Puedes configurar la variable de entorno GOOGLE_APPLICATION_CREDENTIALS o pasar la ruta a la clave de la cuenta de servicio en el código de forma explícita. Recomendamos enfáticamente que uses la primera opción, ya que es más segura.

Para configurar la variable de entorno, haz lo siguiente:

Configura la variable de entorno GOOGLE_APPLICATION_CREDENTIALS con la ruta del archivo JSON que contiene la clave de tu cuenta de servicio. Esta variable solo se aplica a la sesión actual de Cloud Shell. Por lo tanto, si abres una sesión nueva, deberás volver a configurar la variable.

Linux o macOS

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

Windows

Con PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

Cuando completes los pasos anteriores, el servicio de credenciales predeterminadas de la aplicación (ADC) puede determinar de forma implícita tus credenciales, lo que te permite usar credenciales de cuentas de servicio cuando realizas pruebas o ejecutas aplicaciones en entornos de terceros.

Usa credenciales para crear tokens de acceso

Para recuperar el token de acceso de OAuth 2.0 de corta duración, usa las credenciales de Firebase y la biblioteca cliente de Google Auth en tu lenguaje preferido, como se muestra a continuación:

node.js

 function getAccessToken() {
  return new Promise(function(resolve, reject) {
    const key = require('../placeholders/service-account.json');
    const jwtClient = new google.auth.JWT(
      key.client_email,
      null,
      key.private_key,
      SCOPES,
      null
    );
    jwtClient.authorize(function(err, tokens) {
      if (err) {
        reject(err);
        return;
      }
      resolve(tokens.access_token);
    });
  });
}

En este ejemplo, la biblioteca cliente de la API de Google autentica la solicitud con un token web JSON o JWT. Para obtener más información, consulta la sección sobre los tokens web JSON.

Python

def _get_access_token():
  """Retrieve a valid access token that can be used to authorize requests.

  :return: Access token.
  """
  credentials = service_account.Credentials.from_service_account_file(
    'service-account.json', scopes=SCOPES)
  request = google.auth.transport.requests.Request()
  credentials.refresh(request)
  return credentials.token

Java

private static String getAccessToken() throws IOException {
  GoogleCredentials googleCredentials = GoogleCredentials
          .fromStream(new FileInputStream("service-account.json"))
          .createScoped(Arrays.asList(SCOPES));
  googleCredentials.refresh();
  return googleCredentials.getAccessToken().getTokenValue();
}

Cuando venza el token de acceso, se llamará al método de actualización automáticamente para obtener un token actualizado.

Para autorizar el acceso a FCM, solicita el permiso https://www.googleapis.com/auth/firebase.messaging.

Para agregar el token de acceso a un encabezado de solicitud HTTP, haz lo siguiente:

Agrega el token como el valor del encabezado Authorization en el formato Authorization: Bearer <access_token>:

node.js

headers: {
  'Authorization': 'Bearer ' + accessToken
}

Python

headers = {
  'Authorization': 'Bearer ' + _get_access_token(),
  'Content-Type': 'application/json; UTF-8',
}

Java

URL url = new URL(BASE_URL + FCM_SEND_ENDPOINT);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Authorization", "Bearer " + getServiceAccountAccessToken());
httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
return httpURLConnection;

Actualiza la carga útil de las solicitudes de envío

En HTTP v1 de FCM, se incluye un cambio importante en la estructuración de la carga útil de mensajes JSON. La función principal de estos cambios es garantizar que se traten los mensajes de forma correcta cuando se reciben en diferentes plataformas cliente. Los cambios también permiten una mayor flexibilidad para personalizar o “anular” los campos de mensajes por plataforma.

Para familiarizarte con HTTP v1, además de revisar los ejemplos de esta sección, consulta Personaliza un mensaje en diferentes plataformas y revisa la referencia de la API.

Ejemplo: mensaje de notificación simple

Te presentamos una comparación de una carga útil de notificación simple, que solo contiene los campos title, body y data. Además, podrás descubrir las diferencias fundamentales entre las cargas útiles heredada y HTTP v1.

Antes

{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available."
  },
  "data": {
    "story_id": "story_12345"
  }
}

Después

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    }
  }
}

Ejemplo: datos JSON anidados

A diferencia de la API de mensajería heredada, la API de HTTP v1 no admite valores JSON anidados en el campo data. Se requiere una conversión de JSON a cadena.

Antes

{
  ...
  "data": {
    "keysandvalues": {"key1": "value1", "key2": 123}
  }
}

Después

{
  "message": {
   ...
    "data": {
      "keysandvalues": "{\"key1\": \"value1\", \"key2\": 123}"
    }
  }
}

Ejemplo: orientación a varias plataformas

La API heredada realiza una anulación en el backend para habilitar la orientación hacia varias plataformas. Por el contrario, HTTP v1 proporciona bloques de claves específicos que detallan y visibilizan todas las diferencias entre las plataformas. Esta característica te permite usar solo una solicitud a fin de siempre orientar hacia varias plataformas, como se demuestra en el siguiente ejemplo.

Antes

// Android
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available.",
    "click_action": "TOP_STORY_ACTIVITY"
  },
  "data": {
    "story_id": "story_12345"
  }
}
// Apple
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available.",
    "click_action": "HANDLE_BREAKING_NEWS"
  },
  "data": {
    "story_id": "story_12345"
  }
}

Después

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    },
    "android": {
      "notification": {
        "click_action": "TOP_STORY_ACTIVITY"
      }
    },
    "apns": {
      "payload": {
        "aps": {
          "category" : "NEW_MESSAGE_CATEGORY"
        }
      }
    }
  }
}

Ejemplo: personalización con anulaciones de plataforma

La API de HTTP v1 brinda flexibilidad para personalizar los mensajes por plataforma, además de simplificar la orientación de mensajes en todas las plataformas.

Antes

// Android
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "Check out the Top Story.",
    "click_action": "TOP_STORY_ACTIVITY"
  },
  "data": {
    "story_id": "story_12345"
  }
}
// Apple
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available.",
    "click_action": "HANDLE_BREAKING_NEWS"
  },
  "data": {
    "story_id": "story_12345"
  }
}

Después

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    },
    "android": {
      "notification": {
        "click_action": "TOP_STORY_ACTIVITY",
        "body": "Check out the Top Story"
      }
    },
    "apns": {
      "payload": {
        "aps": {
          "category" : "NEW_MESSAGE_CATEGORY"
        }
      }
    }
  }
}

Ejemplo: orientación a dispositivos específicos

Para orientarse a dispositivos específicos con la API de HTTP v1, proporciona el token de registro actual del dispositivo en la clave token en lugar de hacerlo en la clave to.

Antes

  { "notification": {
      "body": "This is an FCM notification message!",
      "title": "FCM Message"
    },
    "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
  }

Después

{
   "message":{
      "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
      "notification":{
        "body":"This is an FCM notification message!",
        "title":"FCM Message"
      }
   }
}

Para obtener más muestras y más información sobre la API de HTTP v1 de FCM, consulta los siguientes vínculos: