Autoriza solicitudes de envío

Las solicitudes enviadas a FCM desde el servidor de apps o el entorno de confianza se deben autorizar. Ten en cuenta las siguientes diferencias importantes entre la API HTTP heredada y la autorización HTTP v1 API:

  • La API de HTTP v1 de FCM autoriza solicitudes con un token de acceso de OAuth 2.0 de corta duración. Para crear este token, en los entornos de servidor de Google, puedes usar las credenciales predeterminadas de la aplicación o también obtener las credenciales obligatorias de forma manual desde un archivo de claves privadas JSON generado para una cuenta de servicio. Si usas Firebase Admin SDK para enviar mensajes, la biblioteca administra el token por ti.
  • Los protocolos heredados obsoletos solo pueden usar claves de API de larga duración que se obtienen desde Firebase console.

Autoriza solicitudes de envío HTTP v1

Según los detalles de tu entorno de servidor, usa una combinación de las siguientes estrategias para autorizar las solicitudes de 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

A menos que uses el SDK de Admin, en el que la autorización se controla automáticamente, será necesario que crees el token de acceso y agregarlo para enviar solicitudes.

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;

Autoriza las solicitudes de envío del protocolo heredado

Con el protocolo HTTP heredado, cada solicitud debe contener la clave de servidor disponible en la pestaña Cloud Messaging del panel Configuración de Firebase console. En el caso del protocolo XMPP, debes usar la misma clave de servidor para establecer una conexión.

Migra claves de servidor heredadas

A partir de marzo de 2020, FCM dejó de crear claves de servidor heredadas. Las claves de servidor heredadas existentes seguirán funcionando, pero recomendamos que uses la versión más reciente de la clave con la etiqueta Clave del servidor en Firebase console.

Si deseas borrar una clave de servidor heredada existente, puedes hacerlo en la consola de Google Cloud.

Autoriza solicitudes HTTP

Una solicitud de mensaje tiene dos partes: el encabezado HTTP y el cuerpo HTTP. El encabezado HTTP debe contener los siguientes encabezados:

  • Authorization: key=YOUR_SERVER_KEY
    Asegúrate de que esta sea la clave de servidor, cuyo valor está disponible en la pestaña Cloud Messaging del panel Configuración de Firebase console. FCM rechaza las claves de Android, de las plataformas de Apple y del navegador.
  • Content-Type: application/json para JSON; application/x-www-form-urlencoded;charset=UTF-8 para texto sin formato.
    Si se omite Content-Type, se determina que el formato es texto sin formato.

Por ejemplo:

Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
  "data" : {
    ...
  },
}

Consulta Compilar solicitudes de envío para ver detalles completos sobre la creación de solicitudes de envío. En la referencia del protocolo HTTP heredado, se proporciona una lista de todos los parámetros que puede contener tu mensaje.

Cómo verificar la validez de una clave de servidor

Si recibes errores de autenticación cuando envías mensajes, verifica la validez de tu clave de servidor. Por ejemplo, en Linux, ejecuta el siguiente comando:

api_key=YOUR_SERVER_KEY

curl --header "Authorization: key=$api_key" \
     --header Content-Type:"application/json" \
     https://fcm.googleapis.com/fcm/send \
     -d "{\"registration_ids\":[\"ABC\"]}"

Si recibes un código de estado HTTP 401, tu clave de servidor no es válida.

Autoriza una conexión XMPP

Con XMPP, puedes mantener una conexión continua, asíncrona y bidireccional con los servidores de FCM. La conexión se puede usar para enviar y recibir mensajes entre tu servidor y los dispositivos de tus usuarios conectados con FCM.

Puedes usar la mayoría de las bibliotecas XMPP para administrar una conexión a FCM de larga duración. El extremo XMPP se ejecuta en fcm-xmpp.googleapis.com:5235. Cuando pruebes la funcionalidad con usuarios fuera de producción, en su lugar debes conectarte al servidor de preproducción fcm-xmpp.googleapis.com:5236 (ten en cuenta que el puerto es diferente).

Hacer pruebas habituales en la preproducción (un entorno más pequeño en el que se ejecutan las últimas compilaciones de FCM) permite aislar a los usuarios reales del código de prueba. Los dispositivos de prueba y el código de prueba que se conectan a fcm-xmpp.googleapis.com:5236 deberían usar un ID de remitente de FCM diferente para evitar enviar mensajes de prueba a usuarios de producción o enviar mensajes upstream desde el tráfico de producción a través de conexiones de prueba.

La conexión tiene dos requisitos importantes:

  • Debes iniciar una conexión de seguridad de la capa de transporte (TLS, Transport Layer Security). Ten en cuenta que FCM no es compatible con la extensión STARTTLS actualmente.
  • FCM necesita un mecanismo de autenticación SASL PLAIN que use <your_FCM_Sender_Id>@fcm.googleapis.com (el ID de remitente de FCM) y la clave de servidor como contraseña. Estos valores están disponibles en la pestaña Cloud Messaging del panel Configuración de Firebase console.

Si en algún momento la conexión falla, debes volver a conectarte inmediatamente. No es necesario retirarse después de una desconexión que se produzca tras la autenticación. Para cada ID de remitente, FCM permite 2,500 conexiones paralelas.

En los siguientes fragmentos, se muestra cómo ejecutar la autenticación y la autorización para una conexión XMPP a FCM.

Servidor XMPP

El servidor XMPP solicita una conexión a FCM

<stream:stream to="fcm.googleapis.com"
        version="1.0" xmlns="jabber:client"
        xmlns:stream="http://etherx.jabber.org/streams">

FCM

FCM abre la conexión y solicita un mecanismo de autenticación, incluido el método PLAIN.

<stream:features>
  <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
    <mechanism>X-OAUTH2</mechanism>
    <mechanism>X-GOOGLE-TOKEN</mechanism>
    <mechanism>PLAIN</mechanism>
  </mechanisms>
</stream:features>

Servidor XMPP

El servidor XMPP debe responder con el método de autenticación PLAIN y proporcionar la clave de servidor disponible en la pestaña Cloud Messaging del panel Configuración de Firebase console.

<auth mechanism="PLAIN"
xmlns="urn:ietf:params:xml:ns:xmpp-sasl">MTI2MjAwMzQ3OTMzQHByb2plY3RzLmdjbS5hb
mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==</auth>

FCM

<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

Servidor XMPP

<stream:stream to="fcm.googleapis.com"
        version="1.0" xmlns="jabber:client"
        xmlns:stream="http://etherx.jabber.org/streams">

FCM

<stream:features>
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
  <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
</stream:features>

Servidor XMPP

<iq type="set">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"></bind>
</iq>

FCM

<iq type="result">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
    <jid>SENDER_ID@fcm.googleapis.com/RESOURCE</jid>
  </bind>
</iq>

Nota: FCM no usa el recurso vinculado mientras enruta mensajes.

Consulta Compilar solicitudes de envío para ver detalles completos sobre la creación de solicitudes de envío. En la referencia del protocolo XMPP heredado, se proporciona una lista de todos los parámetros que puede contener tu mensaje.