firebase / firebase/firebase-admin-node

Misleading error message for THIRD_PARTY_AUTH_ERROR: raw "OAuth 2 access token" text surfaced instead of the APNs-specific message

Abierto
#3,215 0 comentarios 0 reacciones 0 asignados Ver en GitHub
api: messaging
Lenguaje dominante
TypeScript
Estrellas
1.7k
Forks
419
Merge medio
3 d 10 h
PR fusionados (30 d)
16

Descripción

## Summary

When FCM rejects an iOS send with `UNAUTHENTICATED`, the SDK surfaces the raw
gateway message ("...Expected OAuth 2 access token...") instead of its own
APNs-specific message, even though the error is classified as
`messaging/third-party-auth-error`. This sends developers down the wrong path
(debugging their own service-account / OAuth setup) when the real cause is a
downstream APNs credential problem.

## What happened

Sending to iOS device tokens, some tokens fail with:

```json
HTTP 401
{
"error": {
"code": 401,
"status": "UNAUTHENTICATED",
"message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. ...",
"details": [{ "@type": "...FcmError", "errorCode": "THIRD_PARTY_AUTH_ERROR" }]
}
}
```

`error.code` is correctly `messaging/third-party-auth-error`, but `error.message`
is the raw *"Expected OAuth 2 access token"* text. That message strongly implies
a problem with the caller's own authentication (service account / access token),
so it's natural to spend several debugging cycles verifying OAuth, the service
account, token refresh, etc. — all of which are fine. The actual cause is on the
APNs side (e.g. an APNs auth key/certificate that doesn't cover the environment a
given token was minted in). The misleading message cost us multiple debugging
rounds before we inspected `details[].errorCode`.

## Root cause in the SDK

In `src/messaging/error.ts` on current `main`:

- `UNAUTHENTICATED` is mapped to `THIRD_PARTY_AUTH_ERROR` (line ~201), and there is
a clear canonical message for it (lines ~133–137):

> "A message targeted to an iOS device could not be sent because the required
> APNs SSL certificate was not uploaded or has expired. Check the validity of
> your development and production certificates."

- But the error message is assigned as (line ~260):

```ts
error.message = message || error.message;
```

Since the raw server `message` is truthy, it always wins, so the SDK's own
clearer, APNs-specific message is never shown for this code — the misleading
"OAuth 2 access token" text is surfaced instead.

## A second, smaller issue: the canonical message is dated

Even when shown, the canonical message only mentions an *"APNs SSL certificate"*
and *"development and production certificates"* — i.e. the `.p12` model. Modern
setups use `.p8` **APNs auth keys** (token-based auth), and Web Push uses VAPID
keys. For those, "certificate ... has expired / check your certificates" is
itself misleading, because there is no certificate involved.

## Suggested fix

1. For `third-party-auth-error`, prefer (or prepend) the SDK's canonical message
rather than the raw `UNAUTHENTICATED` gateway text, since that raw text
systematically points debugging in the wrong direction. The raw text can be
kept as "Raw server response: ..." (the SDK already appends that in some
paths).
2. Update the canonical message to cover APNs **auth keys (`.p8`)** and **Web Push
(VAPID)**, not just SSL certificates.

## Environment

- Verified against current `main`, `src/messaging/error.ts`.
- Reproduced on a real send to an affected iOS token (401 / UNAUTHENTICATED /
`details[].errorCode = THIRD_PARTY_AUTH_ERROR`).

Happy to open a PR along the lines of the suggested fix if this direction sounds right.

Guía de contribución

Abrir la guía de contribución

Línea de trabajo

Empieza en src/messaging/error.ts leyendo el mapeo de THIRD_PARTY_AUTH_ERROR y la asignación posterior de error.message. Confirma cómo se selecciona el mensaje canónico de APNs cuando está presente la respuesta UNAUTHENTICATED sin procesar y, después, actualiza el comportamiento y la redacción para que se contemplen las claves de autenticación de APNs y las credenciales VAPID de Web Push. La tarea está terminada cuando third-party-auth-error ya no muestra la guía sin procesar y engañosa de OAuth como su mensaje principal.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
typescript
Área
api, backend
Tipo de issue
Error
Dificultad
3/5
Tiempo estimado
1-2 días
Estado de actividad
Tranquilo
Claridad
Bastante claro
Aptitud para principiantes
70/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.