How to redirect to a login page if Flutter API response is unauthorized?
Since you already have a MaterialApp
in your tree and the named routes registered, this should be as simple as adding a call to push your login page around the same time you get the response.
First, you should modify getTables
to check response
for the status code with statusCode
property of the Response
object and shown with the following code block:
var response = await http.get('$_baseUrl/tables/list');
if(response.statusCode == 401) {
//Act on status of 401 here
}
Now that you have a way of checking when the response has a status code of 401, you can navigate to your login page with the Navigator
. The Navigator
needs BuildContext
, so that must be passed to the getTables
function.
This involves modifying getTables
to be:
Future<List<Tbl>> getTables(BuildContext context) async {
and fetchTables
needs a similar change:
Future fetchTables(BuildContext context) async {
Then, where these methods are called, you pass context
down:
In Tables
model.fetchTables(context)
In TablesModel
Future fetchTables(BuildContext context) async {
setBusy(true);
tables = await _api.getTables(context);
setBusy(false);
}
and finally in getTables
, you use the passed context
to use the Navigator
:
Future<List<Tbl>> getTables(BuildContext context) async {
var tables = List<Tbl>();
try {
var response = await http.get('$_baseUrl/tables/list');
//Check response status code
if(response.statusCode == 401) {
Navigator.of(context).pushNamed(RoutePaths.Login);//Navigator is used here to go to login only with 401 status code
return null;
}
var parsed = json.decode(response.body) as List<dynamic>;
if (parsed != null) {
for (var table in parsed) {
tables.add(Tbl.fromJson(table));
}
}
} catch (e) {print(e); return null;}
return tables;
}
Instead of Navigator.of(context).pushNamed(RoutePaths.Login);
, you could use Navigator.pushNamed(context, RoutePaths.Login);
if you prefer, but as you can read at this answer, they internally do the same thing.
Now when there is a status code of 401, a user will be navigated to the login screen.
markhorrocks
Updated on December 23, 2022Comments
-
markhorrocks over 1 year
I am building a Flutter app which uses a Golang API to fetch data. The API will return a 401 unauthorized if the JWT token is not valid. How can I redirect to a login page on any API call if the response status is 401?
Here is my flutter code:
main.dart
void main() async { WidgetsFlutterBinding.ensureInitialized(); Provider.debugCheckInvalidValueType = null; AppLanguage appLanguage = AppLanguage(); await appLanguage.fetchLocale(); runApp(MyApp( appLanguage: appLanguage, )); } class MyApp extends StatelessWidget { final AppLanguage appLanguage; MyApp({this.appLanguage}); @override Widget build(BuildContext context) { return MultiProvider( providers: providers, child: MaterialApp( localizationsDelegates: [ AppLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], initialRoute: RoutePaths.Login, onGenerateRoute: Router.generateRoute, ) ); } }
tables.dart
class Tables extends StatelessWidget { const Tables({Key key}) : super(key: key); @override Widget build(BuildContext context) { return BaseWidget<TablesModel>( model: TablesModel(api: Provider.of(context, listen: false)), onModelReady: (model) => model.fetchTables(), builder: (context, model, child) => model.busy ? Center( child: CircularProgressIndicator(), ) : Expanded( child: GridView.builder ( ---
tables_model.dart
class TablesModel extends BaseModel { Api _api; TablesModel({@required Api api}) : _api = api; List<Tbl> tables; Future fetchTables() async { setBusy(true); tables = await _api.getTables(); setBusy(false); } @override void dispose() { print('Tables has been disposed!!'); super.dispose(); } }
api.dart
Future<List<Tbl>> getTables() async { var tables = List<Tbl>(); try { var response = await http.get('$_baseUrl/tables/list'); var parsed = json.decode(response.body) as List<dynamic>; if (parsed != null) { for (var table in parsed) { tables.add(Tbl.fromJson(table)); } } } catch (e) {print(e); return null;} return tables; }