0
votes

I am working on a flutter app where after sign-in, I have to validate a user's idToken on a custom backend (written in Go) using the Firebase admin SDK: firebase.google.com/go.

I am using the following snippet to sign-in the user via GoogleSignIn and retrieve the Firebase idToken on the client side:

final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();

Future<String> signInWithGoogle() async {
  await Firebase.initializeApp();
 
  final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
  
  final GoogleSignInAuthentication googleSignInAuthentication =
      await googleSignInAccount.authentication;

  final AuthCredential credential = GoogleAuthProvider.credential(
    accessToken: googleSignInAuthentication.accessToken,
    idToken: googleSignInAuthentication.idToken,
  );  

  final UserCredential authResult = await _auth.signInWithCredential(credential);

  final User user = authResult.user;

  String FirebaseIdToken = await _auth.currentUser.getIdToken();
  print("FirebaseIdToken: " + FirebaseIdToken);
  
  if (user != null) {
    /* code to validate user and return it */
  }  return null;
}

I copy the token corresponding to the FirebaseIdToken variable and send it to the backend using Postman with a Authentication: Bearer <token> request header.

At the backend, there is the following:

  /* am.cli here is basically the auth.Client in firebase admin SDK and clientToken is the token received from flutter app. */
  idToken, err := am.cli.VerifyIDToken(context.Background(), clientToken) 
  log.Println("ERROR:", err)

I get the following error printed:

  ERROR: failed to verify token signature

Based on the documentation for both client & backend, I believe that I'm using the correct methods to retrieve and to verify the token.

I have tried to retrieve the idToken with the following code as well:

  IdTokenResult idTokRes = await _auth.currentUser.getIdTokenResult(true);
  print("idTokRes: " + idTokRes.token);

But this fails the same way. (And idTokRes.token and the FirebaseIdToken from the previous method are not same.)

I have also tried to verify the token manually on https://jwt.io/ with the public certificate and the private key which fails as well.

Any help would be appreciated!

1

1 Answers

0
votes

Thanks to a member of the Flutter community, I was able to solve the problem.

Turns out, for some reason, the FirebaseIdToken printed by

print("FirebaseIdToken: " + FirebaseIdToken);

is not the complete token. Because of being large, the output gets truncated. (Still not sure why though. Does Dart's print() statement truncate large strings?)

Edit: Apparently, its the terminal window that truncates/wraps a large output by embedding linebreaks to it.

But, by using the following snippet

 String firebaseIdToken = await user.getIdToken();
 while (firebaseIdToken.length > 0) {
   int startTokenLength =
       (firebaseIdToken.length >= 500 ? 500 : firebaseIdToken.length);
   print("TokenPart: " + firebaseIdToken.substring(0, startTokenLength));
   int lastTokenLength = firebaseIdToken.length;
   firebaseIdToken =
       firebaseIdToken.substring(startTokenLength, lastTokenLength);
 }

I was able to print the complete token in 3 broken parts, which I then concatenated, and sent to the backend via Postman and got no errors this time.

Thanks Rexford!