Skip to content

Commit a6236bd

Browse files
committed
fix(auth, android): handle null id-tokens from google credential manager
1 parent a4b3407 commit a6236bd

3 files changed

Lines changed: 46 additions & 1 deletion

File tree

packages/auth/__tests__/auth.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,16 @@ describe('Auth', function () {
413413
expect(credential?.idToken).toBe('id-token');
414414
});
415415

416+
it('GoogleAuthProvider.credential maps id-token-only credentials for native bridge', function () {
417+
const credential = GoogleAuthProvider.credential('google-id-token', null);
418+
expect(credential.providerId).toBe('google.com');
419+
expect(credential.signInMethod).toBe('google.com');
420+
expect(credential.idToken).toBe('google-id-token');
421+
expect(credential.accessToken).toBeUndefined();
422+
expect(credential.token).toBe('google-id-token');
423+
expect(credential.secret).toBe('');
424+
});
425+
416426
it('PhoneAuthCredential.fromJSON deserializes phone credentials', function () {
417427
const credential = PhoneAuthCredential.fromJSON({
418428
verificationId: 'vid',

packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2046,7 +2046,10 @@ private AuthCredential getCredentialForProvider(
20462046
case "facebook.com":
20472047
return FacebookAuthProvider.getCredential(authToken);
20482048
case "google.com":
2049-
return GoogleAuthProvider.getCredential(authToken, authSecret);
2049+
// Firebase Android rejects empty access tokens; id-token-only flows require null.
2050+
// https://firebase.google.com/docs/auth/android/google-signin
2051+
String googleAccessToken = (authSecret == null || authSecret.isEmpty()) ? null : authSecret;
2052+
return GoogleAuthProvider.getCredential(authToken, googleAccessToken);
20502053
case "twitter.com":
20512054
return TwitterAuthProvider.getCredential(authToken, authSecret);
20522055
case "github.com":

packages/auth/e2e/provider.e2e.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,38 @@ describe('auth() -> Providers', function () {
236236
'At least one of ID token and access token must be non-null',
237237
);
238238
});
239+
240+
it('should accept id-token-only credentials (Credential Manager)', function () {
241+
const { GoogleAuthProvider } = authModular;
242+
243+
const token = 'google-id-token-only';
244+
const credential = GoogleAuthProvider.credential(token, null);
245+
credential.providerId.should.equal('google.com');
246+
credential.signInMethod.should.equal('google.com');
247+
credential.token.should.equal(token);
248+
credential.secret.should.equal('');
249+
credential.idToken.should.equal(token);
250+
should.equal(credential.accessToken, undefined);
251+
});
252+
253+
it('should reach Android native signInWithCredential for id-token-only Google credentials', async function () {
254+
if (!Platform.android) {
255+
this.skip();
256+
}
257+
const { getApp } = modular;
258+
const { GoogleAuthProvider, signInWithCredential, getAuth } = authModular;
259+
const defaultAuth = getAuth(getApp());
260+
const credential = GoogleAuthProvider.credential('google-id-token-only-e2e', null);
261+
262+
try {
263+
await signInWithCredential(defaultAuth, credential);
264+
throw new Error('Did not error.');
265+
} catch (error) {
266+
error.code.should.be.a.String();
267+
error.code.should.not.equal('auth/unknown');
268+
String(error.message).should.not.match(/accessToken cannot be empty/i);
269+
}
270+
});
239271
});
240272

241273
describe('GOOGLE_SIGN_IN_METHOD', function () {

0 commit comments

Comments
 (0)