简体   繁体   中英

Flutter: local_auth can be bypassed by pressing the back button

I'm using local_auth for user verification.

The root widget of my app is a stateless widget.

The bug: The authentication screen pops up as usual. If the fingerprint (or pin) matches, the user can then access the app. However, if the back button is pressed (while the authentication screen is still up), the authentication window vanishes and the user can access the app without authenticating.

I'm using Flutter-2.5.3 and local_auth-1.1.8 .

This is the main.dart :

//other imports here
import 'package:local_auth/local_auth.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  var localAuth = LocalAuthentication();
  SharedPreferences prefs = await SharedPreferences.getInstance();

  if (prefs.getBool('auth') == true) {
    await localAuth.authenticate(
        localizedReason: 'Authenticate to access Notes',
        useErrorDialogs: true,
        stickyAuth: true,);
  }

  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]).then((_) {
    runApp(ProviderScope(child: MyApp()));
  });
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //returns my widget
  }
}

I tried moving the runApp block under a conditional, such that the main root window gets called only when the authentication was successful. However the result remained the same. This was what I did:

if (prefs.getBool('auth') == true) {
    var authenticate = await localAuth.authenticate(
        localizedReason: 'Authenticate to access Notes',
        useErrorDialogs: true,
        stickyAuth: true,);
    if (authenticate == true) {
      await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]).then((_) {
        runApp(ProviderScope(child: MyApp()));
      });
    }
}

This is what worked for me:

  1. Changing MyApp to a StatefulWidget .

  2. Adding an awaited function that attempts to authenticate the user before the user can access the widget (that is, the build function).

Modifying the code:

//other imports here
import 'package:local_auth/local_auth.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  //removing the authentication block from the main method
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]).then((_) {
    runApp(ProviderScope(child: MyApp()));
  });
}

class MyApp extends StatefulWidget {  //changing MyApp to StatefulWidget
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    _authenticate();  //the function that handles authentication
  }

  void _authenticate() async {
    var localAuth = LocalAuthentication();

    SharedPreferences prefs = await SharedPreferences.getInstance();

    if (prefs.getBool('auth') == true) {
      var authenticate = await localAuth.authenticate(
        localizedReason: 'Authenticate to access Notes',
        useErrorDialogs: true,
        //Not using stickyAuth because:  https://github.com/flutter/flutter/issues/83773
        // stickyAuth: true,
      );
      if (authenticate != true) 
        exit(0);  //exiting the app if the authentication failed
    }
  }

  @override
  Widget build(BuildContext context) {
    //returns my widget
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM