[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"

Ouverte Adaptée aux débutants
#1,954 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 2 jours

Personne n'a encore pris cette issue.

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
82/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
cpp, ios, objective-c
Domaine
authentication

Piste de recherche

Commencez dans auth/src/ios/credential_ios.mm et comparez les sélecteurs d’identifiants iOS décrits dans l’issue. Vérifiez comment l’appel à GetCredential à 4 arguments gère un access_token null. Le travail est terminé lorsque, dans ce cas, le sélecteur sans access_token est utilisé, afin que la requête n’inclue pas de access_token vide et que la connexion avec Apple réussisse.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

[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);
Langage dominant
C++
Étoiles
325
Forks
137
Merge moyen
2 j 20 h
PR mergées (30 j)
15

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de firebase/firebase-cpp-sdk

Toutes les issues de firebase/firebase-cpp-sdk

Issues similaires

Plus d'issues C++

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.