Migra de HTTP heredado a HTTP v1

Sigue las instrucciones de esta guía para migrar las apps que usan la API de HTTP heredada de FCM a la API de HTTP v1. Esta API tiene las siguientes ventajas en comparación con la API heredada:

  • 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.

Antes

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

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 para Firebase), usa el servicio 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 mediante 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 proporcionan Compute Engine, Google Kubernetes Engine, App Engine y Cloud Functions 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 solo si configuraste la variable de entorno o si la aplicación se ejecuta 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 Firebase console, 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.refreshAccessToken();
  return googleCredentials.getAccessToken().getTokenValue();
}

Cuando venza el token de acceso, se llamará automáticamente al método de actualización 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 " + getAccessToken());
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: 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!",
      "time": "FCM Message"
    },
    "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
  }

Después

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

Revisa el blog de Firebase para obtener más información y ejemplos sobre la API de HTTP v1 de FCM.