Search code examples
flutterdartauthenticationsharedpreferences

manage login tokens (flutter)


I'm using Shared Preference in my flutter app and I want to manage login token.

this is my Auth class :

class Auth with ChangeNotifier {
  String? _objId;

  String? _token;

  DateTime? createdAt;

  bool get isAuth {
    return token != null;
  }

  String? get token {
    return _token;
  }

  String? get objId {
    return _objId;
  }






and it's my login method , here I tried to save login tokens in shared preferences :

Future<void> loginMethod(String? username, String? password) async {
    var url = Uri.parse('https://drbody.b4a.io/login');

    try {
      final response = await http.post(url,
          headers: {
            'X-Parse-Application-Id': kParseApplicationId,
            'X-Parse-REST-API-Key': kParseRestApiKey,
            'Content-Type': 'application/json'
          },
          body: jsonEncode({
            'username': username,
            'password': password,
          }));

      Map<String, dynamic> jBody = jsonDecode(response.body);
      final jBodyData = jBody;
      if (jBody.containsKey('error')) {
        throw HttpException(jBodyData['code'].toString());
      }
      _token = jBodyData['sessionToken'];
      _objId = jBodyData['objectId'];

      // final currentData = jsonEncode({'token': _token});

      SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.setString('token', jBodyData['sessionToken']);

      //print(jBody);
    } catch (error) {
      throw error;
    }
    notifyListeners();
  }

and this is MaterialApp home page depends on authentication status, I'm using FutureBuilder to return correct page

 Future<bool> tryAutoLogin() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String? currentToken = prefs.getString('token');
    if (!prefs.containsKey('token')) {
      return false;
    }
    _token = currentToken;
    print(_token);
    notifyListeners();
    return true;
  }
}
MaterialApp(
          home: authData.isAuth
              ? TabsScreen()
              : FutureBuilder(
                  future: authData.tryAutoLogin(),
                  builder: (ctx, snapshot) =>
                      snapshot.connectionState == ConnectionState.waiting
                          ? SplashScreen()
                          : AuthScreen(),
                ),)

but after hot restart I've got this in my console :


Exception caught by widgets library 
The following _CastError was thrown building _BodyBuilder:
Null check operator used on a null value

The relevant error-causing widget was
Scaffold


Solution

  • do something like this,

    void main() async{
    WidgetsFlutterBinding.ensureInitialized();
    
    SharedPreferences prefs = await SharedPreferences.getInstance();
    var data = prefs.getString('token') ?? ''; //null check
      runApp(MyApp(token:data)); //pass it through construtor 
    }
    

    now you have the token and in addition just check for if string is empty or null then return false