1

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!

ancientfuture
  • 31
  • 1
  • 8

1 Answers1

1

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!

ancientfuture
  • 31
  • 1
  • 8
  • 1
    I experienced the same problem. The id token which was printed to terminal/console was truncated and unusable. But if you open Flutter Devtools, the print result was not truncated and can be used. So there is no need to print it in chunks like above. – Daniel Wu Mar 21 '23 at 05:28