【问题标题】:Flutter - Get Firebase custom claims while writing Firebase user to own user instanceFlutter - 在将 Firebase 用户写入拥有的用户实例时获取 Firebase 自定义声明
【发布时间】:2021-01-18 06:00:56
【问题描述】:

我正在尝试将How do I access custom claims? 给出的示例应用到我现有的代码中。

我有一个 Stream,它监听身份验证更改并使用响应的 Firebase 用户更新我自己的用户对象。当我存储我的用户对象时,我也想获取该用户的自定义声明。

问题出在 _userFromFirebaseUser

它说“等待表达式只能在异步函数中使用。 尝试使用 'async' 或 'async*' 标记函数体。”

但是当我这样做时,错误会跳到我的流中,然后显示“参数类型'Future Function(User)' 不能分配给参数类型'User Function(User)'。”对于“_userFromFirebaseUser”在

// auth change user stream
  Stream<local.User> get user {
    return _auth.authStateChanges().map(_userFromFirebaseUser);
  }

这是我完整的身份验证类:

import 'package:<my-pckg>/models/user.dart' as local;
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:<my-pckg>/services/database.dart';
//import 'package:shared_preferences/shared_preferences.dart';

class AuthService {
  final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;

  // create user obj based on firebase user
  local.User _userFromFirebaseUser(auth.User user) {
    
    final isAdmin = (await _currentUserClaims)['admin'] == true;
    
    return user != null
        ? local.User(
            uid: user.uid,
            email: user.email,
            displayName: user.displayName,
            isAdmin: isAdmin)
        : null;
  }

  // auth change user stream
  Stream<local.User> get user {
    return _auth.authStateChanges().map(_userFromFirebaseUser);
  }

  // sign in anon
  Future signInAnon() async {
    try {
      auth.UserCredential result = await _auth.signInAnonymously();
      auth.User user = result.user;
      return _userFromFirebaseUser(user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  // sign in with email and password
  Future signInWithEmailAndPassword(String email, String password) async {
    try {
      auth.UserCredential result = await _auth.signInWithEmailAndPassword(
          email: email, password: password);
      auth.User user = result.user;
      print('Successfully logged in, User UID: ${user.uid}');
      return user;
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  // register with email and password
  Future registerWithEmailAndPassword(String email, String password) async {
    try {
      auth.UserCredential result = await _auth.createUserWithEmailAndPassword(
          email: email, password: password);
      auth.User user = result.user;
      // create a new document for the user with the uid
      await DatabaseService(uid: user.uid).updateUserData(null);
      print('Successfully registered, User UID: ${user.uid}');
      return _userFromFirebaseUser(user);
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  // sign out
  Future signOut() async {
    try {
      print('User signed out');
      return await _auth.signOut();
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  Future<Map<dynamic, dynamic>> get _currentUserClaims async {
    final user = _auth.currentUser;

    // If refresh is set to true, a refresh of the id token is forced.
    final idTokenResult = await user.getIdTokenResult(true);

    return idTokenResult.claims;
  }
}

我是不是走错方向了?有什么明显的,我根本不考虑的吗?

感谢您的帮助!

【问题讨论】:

    标签: firebase async-await firebase-authentication stream future


    【解决方案1】:

    对于那些遇到同样问题的人,我在进一步研究后找到了解决方案:

    您必须将.map 更改为.asyncMap

    这是代码,对我有用:

    import 'package:<my-pckg>/models/user.dart' as local;
    import 'package:firebase_auth/firebase_auth.dart' as auth;
    import 'package:<my-pckg>/services/database.dart';
    //import 'package:shared_preferences/shared_preferences.dart';
    
    class AuthService {
      final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
    
      // create user obj based on firebase user
      Future<local.User> _userFromFirebaseUser(auth.User user) async {
        final isAdmin = (await _userClaims)['admin'] == true;
    
        return user != null
            ? local.User(
                uid: user.uid,
                email: user.email,
                displayName: user.displayName,
                isAdmin: isAdmin)
            : null;
      }
    
      // auth change user stream
      Stream<local.User> get user {
        return _auth.authStateChanges().asyncMap(_userFromFirebaseUser);
      }
    
      // sign in anon
      Future signInAnon() async {
        try {
          auth.UserCredential result = await _auth.signInAnonymously();
          auth.User user = result.user;
          return _userFromFirebaseUser(user);
        } catch (e) {
          print(e.toString());
          return null;
        }
      }
    
      // sign in with email and password
      Future signInWithEmailAndPassword(String email, String password) async {
        try {
          auth.UserCredential result = await _auth.signInWithEmailAndPassword(
              email: email, password: password);
          auth.User user = result.user;
          print('Successfully logged in, User UID: ${user.uid}');
          return user;
        } catch (error) {
          print(error.toString());
          return null;
        }
      }
    
      // register with email and password
      Future registerWithEmailAndPassword(String email, String password) async {
        try {
          auth.UserCredential result = await _auth.createUserWithEmailAndPassword(
              email: email, password: password);
          auth.User user = result.user;
          // create a new document for the user with the uid
          await DatabaseService(uid: user.uid).updateUserData(null);
          print('Successfully registered, User UID: ${user.uid}');
          return _userFromFirebaseUser(user);
        } catch (error) {
          print(error.toString());
          return null;
        }
      }
    
      // sign out
      Future signOut() async {
        try {
          print('User signed out');
          return await _auth.signOut();
        } catch (error) {
          print(error.toString());
          return null;
        }
      }
    
      Future<Map<dynamic, dynamic>> get _userClaims async {
        final user = _auth.currentUser;
    
        // If refresh is set to true, a refresh of the id token is forced.
        final idTokenResult = await user.getIdTokenResult(true);
    
        return idTokenResult.claims;
      }
    }
    

    在这里找到:In flutter, how can I "merge" Firebase onAuthStateChanged with user.getTokenId() to return a Stream?

    【讨论】:

    • 绝妙的解决方案。感谢您在此处发布。
    猜你喜欢
    • 2020-01-30
    • 1970-01-01
    • 2019-03-24
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    • 2018-12-18
    • 2021-10-31
    相关资源
    最近更新 更多