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

Aberta Para iniciantes
#1,954 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 2 dias

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
82/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
cpp, ios, objective-c
Domínio
authentication

Direção de pesquisa

Comece em auth/src/ios/credential_ios.mm e compare os seletores de credenciais do iOS descritos na issue. Verifique como a chamada de 4 argumentos a GetCredential lida com um access_token null. O trabalho estará concluído quando, nesse caso, o seletor sem access_token for usado, para que a solicitação não inclua um access_token vazio e o início de sessão com a Apple funcione.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

[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);
Linguagem predominante
C++
Estrelas
325
Forks
137
Merge médio
2d 20h
PRs com merge (30d)
15

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de firebase/firebase-cpp-sdk

Todas as issues de firebase/firebase-cpp-sdk

Issues semelhantes

Mais issues de C++

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.