[Bug] iOS: OAuthProvider::GetCredential with raw_nonce and null access_token sends empty access_token, Sign in with Apple fails with "Invalid OAuth response from apple.com"

Offen Anfängerfreundlich
#1,954 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 2 Tagen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
2/5
Geschätzter Aufwand
1-3 Stunden
Anfängerfreundlichkeit
82/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
cpp, ios, objective-c
Bereich
authentication

Rechercherichtung

Beginne in auth/src/ios/credential_ios.mm und vergleiche die im Issue beschriebenen iOS-Anmeldeinformationsselektoren. Prüfe, wie der 4-Argumente-Aufruf von GetCredential mit einem null access_token umgeht. Fertig ist die Aufgabe, wenn in diesem Fall der Selektor ohne access_token verwendet wird, sodass die Anfrage keinen leeren access_token enthält und die Apple-Anmeldung erfolgreich ist.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

[REQUIRED] Please fill in the following fields:
  • Pre-built SDK from the website or open-source from this repo: Pre-built SDK from the website (firebase_cpp_sdk_13.13.0.zip)
  • Firebase C++ SDK version: 13.13.0. The same code is in 13.13.1, 14.0.0, 14.1.0 and main.
  • Problematic Firebase Component: Auth
  • Other Firebase Components in use: App, Firestore, Functions, Analytics, Crashlytics, Remote Config, Storage, Database
  • Platform you are using the C++ SDK on: Mac
  • Platform you are targeting: iOS (Firebase iOS SDK 12.19.1, iPhone 13)
[REQUIRED] Please describe the issue here:

On iOS, Sign in with Apple always fails when the credential comes from OAuthProvider::GetCredential(provider_id, id_token, raw_nonce, access_token) with access_token == nullptr, as the Apple C++ guide recommends. Both Auth::SignInAndRetrieveDataWithCredential and User::LinkWithCredential return:

error 4 (kAuthErrorInvalidCredential): "Invalid OAuth response from apple.com"

The backend reply is INVALID_IDP_RESPONSE : Invalid OAuth response from apple.com.

Root cause

auth/src/ios/credential_ios.mm passes nil when access_token is null:

NSString* access_token_string =
    (access_token != nullptr) ? util::CStringToNSString(access_token) : nullptr;
FIRAuthCredential* credential =
    (FIRAuthCredential*)[FIROAuthProvider credentialWithProviderID:@(provider_id)
                                                           IDToken:@(id_token)
                                                          rawNonce:@(raw_nonce)
                                                       accessToken:access_token_string];

Since the Swift rewrite of FirebaseAuth (iOS SDK 11+), this selector's accessToken is a non-optional String. See FirebaseAuth/Sources/Swift/AuthProvider/OAuthProvider.swift:

@objc(credentialWithProviderID:IDToken:rawNonce:accessToken:)
public static func credential(withProviderID providerID: String, idToken: String,
                              rawNonce: String,
                              accessToken: String) -> OAuthCredential

Passing nil from Objective-C into a non-optional Swift String bridges to an empty string. OAuthCredential then sets providerAccessToken = "", and the verifyAssertion / signInWithIdp post body includes access_token=. The backend tries to validate the empty access token against apple.com and rejects the request.

The iOS SDK already has a selector for this case: credentialWithProviderID:IDToken:rawNonce:, which takes no access token. Apple also has its own factory: appleCredentialWithIDToken:rawNonce:fullName:.

Evidence

We logged the Apple identity token and raw nonce on the device, then sent them straight to accounts:signInWithIdp over REST:

postBody Result
id_token=…&providerId=apple.com&nonce=<raw> 200 OK (sign-in and link both work)
id_token=…&access_token=&providerId=apple.com&nonce=<raw> 400 INVALID_IDP_RESPONSE : Invalid OAuth response from apple.com, the same error the C++ SDK returns
id_token=…&providerId=apple.com 400 MISSING_OR_INVALID_NONCE : Nonce is missing in the request.

The token is valid: iss = https://appleid.apple.com, aud = <bundle id>, and nonce equals the SHA-256 of the raw nonce. The project is configured correctly, because the same token succeeds without access_token=.

Suggested fix

In auth/src/ios/credential_ios.mm, use the no-access-token selector when access_token is null:

Credential OAuthProvider::GetCredential(const char* provider_id, const char* id_token,
                                        const char* raw_nonce, const char* access_token) {
  FIREBASE_ASSERT_RETURN(Credential(), provider_id && id_token && raw_nonce);
  FIRAuthCredential* credential =
      access_token != nullptr
          ? (FIRAuthCredential*)[FIROAuthProvider credentialWithProviderID:@(provider_id)
                                                                   IDToken:@(id_token)
                                                                  rawNonce:@(raw_nonce)
                                                               accessToken:@(access_token)]
          : (FIRAuthCredential*)[FIROAuthProvider credentialWithProviderID:@(provider_id)
                                                                   IDToken:@(id_token)
                                                                  rawNonce:@(raw_nonce)];
  return Credential(new FIRAuthCredentialPointer(credential));
}

This only affects the 4-argument overload. The 3-argument GetCredential(provider_id, id_token, access_token) asserts that access_token is non-null, so it never passes nil.

Steps to reproduce:

Have you been able to reproduce this issue with just the Firebase C++ quickstarts ?
Not tried with the quickstart. We reproduced it in our own app and with the minimal code below.

What's the issue repro rate? (eg 100%, 1/5 etc)
100% on a real device.

What happened? How can we make the problem occur?

  1. Enable the Apple provider in the Firebase console. Add the com.apple.developer.applesignin entitlement to the iOS app.
  2. Run ASAuthorizationAppleIDProvider with request.nonce = SHA256(rawNonce).
  3. Take identityToken from the returned ASAuthorizationAppleIDCredential.
  4. Call OAuthProvider::GetCredential("apple.com", idToken, rawNonce, nullptr), then SignInAndRetrieveDataWithCredential or LinkWithCredential.
  5. The future completes with error 4, "Invalid OAuth response from apple.com". No apple.com user is created.
Relevant Code:
// Objective-C++ on iOS, after ASAuthorizationController succeeds
ASAuthorizationAppleIDCredential *apple = (ASAuthorizationAppleIDCredential *)authorization.credential;
NSString *idToken = [[NSString alloc] initWithData:apple.identityToken encoding:NSUTF8StringEncoding];

firebase::auth::Credential credential = firebase::auth::OAuthProvider::GetCredential(
    "apple.com", idToken.UTF8String, rawNonce.UTF8String, /*access_token=*/nullptr);

// Either call fails with kAuthErrorInvalidCredential: "Invalid OAuth response from apple.com"
auth->SignInAndRetrieveDataWithCredential(credential);
auth->current_user().LinkWithCredential(credential);
Vorherrschende Sprache
C++
Sterne
325
Forks
137
Ø Merge
2 T. 20 Std.
Gemergte PRs (30 T.)
15

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus firebase/firebase-cpp-sdk

Alle Issues in firebase/firebase-cpp-sdk

Ähnliche Issues

Weitere Issues zu C++

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.