Skip to content

fix(messaging): surface the APNs guidance for THIRD_PARTY_AUTH_ERROR - #3229

Open
milcho0604 wants to merge 1 commit into
firebase:mainfrom
milcho0604:fix/third-party-auth-error-message
Open

fix(messaging): surface the APNs guidance for THIRD_PARTY_AUTH_ERROR#3229
milcho0604 wants to merge 1 commit into
firebase:mainfrom
milcho0604:fix/third-party-auth-error-message

Conversation

@milcho0604

@milcho0604 milcho0604 commented Aug 13, 2026

Copy link
Copy Markdown

Fixes #3215.

The problem

When FCM rejects a send with a provider-auth error, the accompanying server message is often the generic gateway text:

Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential.

FirebaseMessagingError.fromServerError() lets any server message replace the canonical one:

error.message = message || error.message;

so that text is what developers see. It describes the caller's own credential, while the actual fault is an APNs or web push credential on the Firebase project — so it sends people to audit their service account and OAuth setup, all of which are fine. The SDK already has a correct message for this code, but it was unreachable in practice, because the backend supplies a message.

The change

  1. For the server codes that name the provider credential outright, the canonical message leads and the server text follows as Server message: "...", so no detail is lost.
  2. Widened the canonical message. It named only an "APNs SSL certificate" and "development and production certificates" — the .p12 model. The backend documents this code as "APNs certificate or web push auth key was invalid or missing", which also covers APNs auth keys and Web Push, and for those "certificate has expired" is itself misleading.
  3. Wired messaging-errors-internal.spec into test/unit/index.spec.ts. It was not imported, so the file never ran under npm test. The unit suite goes from 6064 to 6076 tests.

Which server codes, and why not all of them

Four server codes map to THIRD_PARTY_AUTH_ERROR, and they do not all mean the same thing:

Server code Leads with SDK message Why
THIRD_PARTY_AUTH_ERROR yes names the provider credential outright
APNS_AUTH_ERROR yes same
InvalidApnsCredential (legacy) yes same
UNAUTHENTICATED no without an FcmError detail this is the plain gateway rejection, which can genuinely mean this SDK's own credential is bad

Keying the special case on the mapped client code would prepend APNs guidance to the last row too, which would be actively wrong when the caller's service account really is at fault. The condition therefore tests serverErrorCode, which still tells them apart, and that path keeps showing the server message on its own.

The canonical message likewise makes no claim about which credential is not at fault, because it is still the fallback for UNAUTHENTICATED when the backend sends no message at all.

Tests

messaging-errors-internal.spec.ts covers, parameterized over the three provider-auth codes and varying the HTTP status so the behavior cannot be keyed on it:

  • canonical guidance first, server text preserved — asserted by full-string equality, so weakening any part of the guidance fails;
  • no server message, and an empty one, produce the canonical message with nothing appended;
  • a bare UNAUTHENTICATED returns the server message unchanged;
  • NOT_FOUND still uses the server message verbatim, so the special case cannot silently widen.

Each assertion was checked against a mutated source. Removing the message guard, looking the code up by the mapped client code, narrowing the set back to a single alias, coupling the branch to HTTP 401, and reducing the canonical message to a stub each make the relevant tests fail. The pre-existing cases in messaging.spec.ts assert rejectedWith('test error message'), which is a substring match and passes either way, so they do not cover this.

npm test passes (6076 unit tests, lint clean) and npm run api-extractor reports every API file up to date.

Notes for reviewers

  • fromTopicManagementServerError() is deliberately untouched: TOPIC_MGT_SERVER_TO_CLIENT_CODE never maps to THIRD_PARTY_AUTH_ERROR.
  • Error codes are unchanged; only message text changes. If message text is treated as API surface, I am happy to narrow this to the condition change alone, or to reword.
  • The UNAUTHENTICATED → THIRD_PARTY_AUTH_ERROR mapping itself looks questionable, but changing it would change error.code for existing callers, so it is left alone here.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the error handling for THIRD_PARTY_AUTH_ERROR in the Firebase Messaging SDK. Instead of letting the generic server-side OAuth error message overwrite the SDK's specific guidance regarding APNs and web push credentials, the SDK now prepends its own descriptive message and appends the raw server response. Unit tests have been added to verify this behavior and ensure other error codes remain unaffected. I have no feedback to provide as there are no review comments.

@milcho0604
milcho0604 force-pushed the fix/third-party-auth-error-message branch from f2c6e89 to 216aa37 Compare August 13, 2026 05:45
When FCM rejects a send with a provider-auth error, the accompanying server
message is often the generic gateway text ("Request is missing required
authentication credential. Expected OAuth 2 access token, login cookie or other
valid authentication credential."). fromServerError() lets any server message
replace the canonical one, so that text is what developers see. It describes the
caller's own credential, while the fault is an APNs or web push credential on
the project, so it sends people to audit their service account instead. The
SDK's own message for this code was unreachable in practice.

Lead with the canonical message for the server codes that name the provider
credential outright -- THIRD_PARTY_AUTH_ERROR, APNS_AUTH_ERROR and the legacy
InvalidApnsCredential -- and keep the server text after it.

UNAUTHENTICATED maps to the same client code but is deliberately excluded.
Without an FcmError detail it is the plain gateway rejection, which really can
mean this SDK's own credential is bad, so prefixing APNs guidance there would
point developers away from the actual fault. Keying on the server code rather
than the mapped client code keeps the two apart.

Also widen the canonical message, which named only an "APNs SSL certificate"
and development/production certificates. The backend documents this code as
"APNs certificate or web push auth key was invalid or missing", which also
covers APNs auth keys and Web Push.

test/unit/index.spec.ts did not import messaging-errors-internal.spec, so that
file never ran under `npm test`. Wired it in; the unit suite goes from 6064 to
6076 tests.

Fixes firebase#3215
@milcho0604
milcho0604 force-pushed the fix/third-party-auth-error-message branch from 216aa37 to 5287915 Compare August 13, 2026 06:07
@milcho0604
milcho0604 marked this pull request as ready for review August 13, 2026 06:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant