Is there an existing issue for this?
Which plugins are affected?
Auth
Which platforms are affected?
iOS
Description
On iOS, creating an Apple credential with the documented API:
final credential = OAuthProvider('apple.com').credential(
idToken: identityToken,
rawNonce: rawNonce,
);
await user.linkWithCredential(credential); // or signInWithCredential
always fails with:
[firebase_auth/invalid-credential] Invalid OAuth response from apple.com
even though the Apple identityToken is perfectly valid (correct aud, iss, matching nonce, valid signature — replaying the exact same token against accounts:signInWithIdp via plain REST succeeds).
Root cause
I captured the actual request the SDK sends by routing useAuthEmulator through a logging proxy that forwards to production. The verifyAssertion postBody the plugin produces is:
providerId=apple.com&id_token=<valid JWT>&nonce=<rawNonce>&access_token=
Note the trailing empty access_token= parameter. When access_token is present (even empty), the Identity Toolkit backend ignores the valid id_token and takes the access-token-exchange path with apple.com, which fails with INVALID_IDP_RESPONSE : Invalid OAuth response from apple.com.
Where the empty string comes from:
- Dart sends the credential map with
accessToken: null (correct).
FLTFirebaseAuthPlugin.m → getFIRAuthCredentialFromArguments takes the generic OAuth branch (signInMethod oauth) and calls:
[FIROAuthProvider credentialWithProviderID:providerId
IDToken:idToken
rawNonce:rawNonce
accessToken:accessToken]; // accessToken == nil
- In firebase-ios-sdk (12.15.0, Swift rewrite), that selector maps to
OAuthProvider.swift:
@objc(credentialWithProviderID:IDToken:rawNonce:accessToken:)
public static func credential(withProviderID providerID: String, idToken: String,
rawNonce: String,
accessToken: String) -> OAuthCredential
accessToken is declared non-optional String. Passing nil from Objective-C bridges it to an empty string instead of nil.
VerifyAssertionRequest only skips access_token when it is nil — "" is non-nil, so the empty parameter is appended to the postBody.
This is the same class of regression as #13242 / #3674 (optional parameter handling), resurfaced after the firebase-ios-sdk Swift rewrite.
Proof via REST (server error fingerprint)
Same fake-signature token, only difference is the empty parameter:
| postBody |
server response |
providerId=apple.com&id_token=<t>&nonce=<n> |
INVALID_IDP_RESPONSE : Unable to verify the ID Token signature. (proceeds to signature check → a real token succeeds) |
providerId=apple.com&id_token=<t>&nonce=<n>&access_token= |
INVALID_IDP_RESPONSE : Invalid OAuth response from apple.com |
Workarounds
Suggested fix
In getFIRAuthCredentialFromArguments (generic OAuth branch), when accessToken == nil call the credentialWithProviderID:IDToken:rawNonce: selector instead of passing nil into the non-optional 4-arg variant (and similarly audit other optional params passed into the Swift-rewritten SDK). Alternatively fix the optionality upstream in firebase-ios-sdk.
Reproducing the issue
- iOS app,
firebase_auth: 6.5.4 (firebase-ios-sdk 12.15.0 via SPM).
- Sign in with Apple natively (e.g.
sign_in_with_apple), obtain identityToken + rawNonce.
OAuthProvider('apple.com').credential(idToken: ..., rawNonce: ...) → signInWithCredential or linkWithCredential.
- Observe
[firebase_auth/invalid-credential] Invalid OAuth response from apple.com.
No dashboard configuration issue is involved: Apple provider enabled (native-only, empty Services ID config), bundle ID registered, token aud/nonce verified correct.
Firebase Core version
4.11.0
Flutter Version
3.35 (Dart SDK ^3.12.2)
Relevant Log Output
flutter: [firebase_auth/invalid-credential] Invalid OAuth response from apple.com
Captured verifyAssertion request body (via logging proxy):
{
"returnSecureToken" : true,
"returnIdpCredential" : true,
"postBody" : "providerId=apple.com&id_token=<REDACTED valid Apple JWT>&nonce=<rawNonce>&access_token=",
"idToken" : "<anonymous user idToken>",
"requestUri" : "http://localhost",
"autoCreate" : true
}
Response:
{ "error": { "code": 400, "message": "INVALID_IDP_RESPONSE : Invalid OAuth response from apple.com" } }
Is there an existing issue for this?
Which plugins are affected?
Auth
Which platforms are affected?
iOS
Description
On iOS, creating an Apple credential with the documented API:
always fails with:
even though the Apple
identityTokenis perfectly valid (correctaud,iss, matchingnonce, valid signature — replaying the exact same token againstaccounts:signInWithIdpvia plain REST succeeds).Root cause
I captured the actual request the SDK sends by routing
useAuthEmulatorthrough a logging proxy that forwards to production. TheverifyAssertionpostBody the plugin produces is:Note the trailing empty
access_token=parameter. Whenaccess_tokenis present (even empty), the Identity Toolkit backend ignores the validid_tokenand takes the access-token-exchange path with apple.com, which fails withINVALID_IDP_RESPONSE : Invalid OAuth response from apple.com.Where the empty string comes from:
accessToken: null(correct).FLTFirebaseAuthPlugin.m→getFIRAuthCredentialFromArgumentstakes the generic OAuth branch (signInMethodoauth) and calls:OAuthProvider.swift:accessTokenis declared non-optionalString. Passingnilfrom Objective-C bridges it to an empty string instead ofnil.VerifyAssertionRequestonly skipsaccess_tokenwhen it isnil—""is non-nil, so the empty parameter is appended to the postBody.This is the same class of regression as #13242 / #3674 (optional parameter handling), resurfaced after the firebase-ios-sdk Swift rewrite.
Proof via REST (server error fingerprint)
Same fake-signature token, only difference is the empty parameter:
providerId=apple.com&id_token=<t>&nonce=<n>INVALID_IDP_RESPONSE : Unable to verify the ID Token signature.(proceeds to signature check → a real token succeeds)providerId=apple.com&id_token=<t>&nonce=<n>&access_token=INVALID_IDP_RESPONSE : Invalid OAuth response from apple.comWorkarounds
AppleAuthProvider.credentialWithIDToken(idToken, rawNonce, AppleFullPersonName(...))works — it takes the dedicated Apple branch in the plugin (appleCredentialWithIDToken:rawNonce:fullName:), which never touchesaccessToken. Verified: postBody contains noaccess_tokenand sign-in/link succeeds.accessToken: authorizationCode(suggested in [firebase_auth] Native iOS Sign in with Apple rejected with invalid-credential despite valid JWT — reproducible on one Firebase project only #18325) merely avoids the empty parameter by filling it; it should not be necessary per the docs.Suggested fix
In
getFIRAuthCredentialFromArguments(generic OAuth branch), whenaccessToken == nilcall thecredentialWithProviderID:IDToken:rawNonce:selector instead of passing nil into the non-optional 4-arg variant (and similarly audit other optional params passed into the Swift-rewritten SDK). Alternatively fix the optionality upstream in firebase-ios-sdk.Reproducing the issue
firebase_auth: 6.5.4(firebase-ios-sdk 12.15.0 via SPM).sign_in_with_apple), obtainidentityToken+rawNonce.OAuthProvider('apple.com').credential(idToken: ..., rawNonce: ...)→signInWithCredentialorlinkWithCredential.[firebase_auth/invalid-credential] Invalid OAuth response from apple.com.No dashboard configuration issue is involved: Apple provider enabled (native-only, empty Services ID config), bundle ID registered, token
aud/nonceverified correct.Firebase Core version
4.11.0
Flutter Version
3.35 (Dart SDK ^3.12.2)
Relevant Log Output