invertase / dart_firebase_admin

🔥 A Firebase Admin SDK for Dart.
Apache License 2.0
122 stars 39 forks source link

Verify token generated by flutter app throws: Null check operator used on a null value #56

Open Alemasoft opened 1 month ago

Alemasoft commented 1 month ago

Describe the bug Trying to verify a firebase auth token generated with mail and password from a flutter app throws a Null check error when decoding it.

ERROR: Null check operator used on a null value
#0      new DecodedIdToken.fromMap (package:dart_firebase_admin/src/auth/token_verifier.dart:318:48)
#1      FirebaseTokenVerifier.verifyJWT (package:dart_firebase_admin/src/auth/token_verifier.dart:82:43)
<asynchronous suspension>
#2      _BaseAuth.verifyIdToken (package:dart_firebase_admin/src/auth/base_auth.dart:360:28)

The error comes from: package:dart_firebase_admin/src/auth/token_verifier.dart:318:48

@internal
  factory DecodedIdToken.fromMap(Map<String, Object?> map) {
    return DecodedIdToken(
      aud: map['aud']! as String,
      authTime: DateTime.fromMillisecondsSinceEpoch(
        (map['auth_time']! as int) * 1000,
      ),
      email: map['email'] as String?,
      emailVerified: map['email_verified'] as bool?,
      exp: map['exp']! as int,
      firebase: TokenProvider(
        identities: Map.from(map['firebase']! as Map),
        signInProvider: map['sign_in_provider']! as String, <<< THIS IS NULL
        signInSecondFactor: map['sign_in_second_factor'] as String?,
        secondFactorIdentifier: map['second_factor_identifier'] as String?,
        tenant: map['tenant'] as String?,
      ),
      iat: map['iat']! as int,
      iss: map['iss']! as String,
      phoneNumber: map['phone_number'] as String?,
      picture: map['picture'] as String?,
      sub: map['sub']! as String,
      uid: map['uid']! as String,
    );
  }

To Reproduce

In the flutter App

auth.UserCredential credential = await _auth.signInWithEmailAndPassword(
          email: email, password: password);
auth.IdTokenResult? token = await _auth.currentUser!.getIdToken();
var response = await client.auth.logIn(token!);

In the serverpod endpoint

Future<String> authenticate(Session session, String token) async {
    if (!_initialized) throw Exception("EnsureInitialized hasn't been called!"); //Checks the correct initialization of the admin sdk
    session.log(token); //Only for testing
    DecodedIdToken res = await _auth.verifyIdToken(token);

    return res.uid;
  }

Expected behavior The token should be valid since is not custom generated and furthermore is taken fromthe official firebase_auth package.

Alemasoft commented 1 month ago

This is the output from jwt.io. The sign_in_provider field is present. It seems that the constructor wrongfully get the sign_in_provider from the main map instead of the firebase inner field.

firebase: TokenProvider(
        identities: Map.from(map['firebase']! as Map),
        signInProvider: map['sign_in_provider']! as String, <<< THIS IS NULL
        signInSecondFactor: map['sign_in_second_factor'] as String?,
        secondFactorIdentifier: map['second_factor_identifier'] as String?,
        tenant: map['tenant'] as String?,
      ),

firebase: TokenProvider(
        identities: Map.from(map['firebase']! as Map),
        signInProvider: Map.from(map['firebase']! as Map)['sign_in_provider']! as String, <<< THIS SHOULD BE NOT NULL
        signInSecondFactor: map['sign_in_second_factor'] as String?,
        secondFactorIdentifier: map['second_factor_identifier'] as String?,
        tenant: map['tenant'] as String?,
      ),

image

markbreuss commented 3 weeks ago

Seeing the same bug - for a token thats valid using the python admin sdk.