How do I access the authentication token obtained on Login using BloC with Flutter
So here is the code in the user-dao, which I just need to import in any widget/class I am needing to access the server. Seems obvious and totally straight forward but amongst all the Dart code which I am unfamiliar with and the many files used in the bloc pattern, I think my head was getting confused.
Future<String> getUserToken(int id) async {
final db = await dbProvider.database;
try {
var res = await db.rawQuery("SELECT token FROM userTable WHERE id=0");
return res.isNotEmpty ? (User.fromDatabaseJson(res.first)).token : null;
} catch (err) {
return null;
}
}
Here is the new users_screen code, using FutureBuilder
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../widgets/logout_button.dart';
import '../repository/user_repository.dart';
import 'package:http/http.dart' as http;
import '../dao/user_dao.dart';
import '../api_connection/api_connection.dart';
import '../models/user_model.dart';
class UserScreen extends StatefulWidget {
@override
_UserScreenState createState() => _UserScreenState();
}
class _UserScreenState extends State<UserScreen> {
Future<User> futureUser;
@override
void initState() {
super.initState();
futureUser = getUser();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('The Yard Users'),
),
body: Container(
child: FutureBuilder( // use a future builder widget
future: futureUser, // assign the future
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
// show your layout if future is done
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 30.0),
child: Text(
'Username: ${snapshot.data.username}', // get the username from the snapshot
style: TextStyle(
fontSize: 24.0,
),
),
),
// Logout button
Padding(
padding: EdgeInsets.fromLTRB(34.0, 20.0, 0.0, 0.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.85,
height: MediaQuery.of(context).size.width * 0.16,
child: LogoutButton()
),
),
],
);
} else {
return CircularProgressIndicator(); // show a progress indicator while future is executing
}
},
),
),
);
}
}
HubertBlu
Updated on December 23, 2022Comments
-
HubertBlu over 1 year
I have completed the following tutorial https://dev.to/amartyadev/flutter-app-authentication-with-django-backend-1-21cp which although useful, has left me still pretty clueless how to move forward. I am able to login and the user details are saved via a UserRepository class to a sqlite database locally, including the authentication token, but I have no idea how to access this when trying to make repeat requests to the server for data. there are no problems with the existing code but I will present several pages so you can see what I have done and am trying to achieve and how it is put together.
main.dart:
import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:bloc/bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import './repository/user_repository.dart'; import './bloc/authentication/authentication_bloc.dart'; import './screens/splash_screen.dart'; import './screens/login/login_screen.dart'; import './screens/home_screen.dart'; import './widgets/loading_indicator.dart'; import './widgets/video_widget.dart'; import './screens/home_screen.dart'; const welcomeUrl = 'https://soundjudgement.github.io/static-sf/tour.mp4'; class SimpleBlocDelegate extends BlocDelegate { @override void onEvent(Bloc bloc, Object event) { super.onEvent(bloc, event); print(event); } @override void onTransition(Bloc bloc, Transition transition) { super.onTransition(bloc, transition); print(transition); } @override void onError(Bloc bloc, Object error, StackTrace stacktrace) { super.onError(bloc, error, stacktrace); } } void main() { BlocSupervisor.delegate = SimpleBlocDelegate(); final userRepository = UserRepository(); runApp(BlocProvider<AuthenticationBloc>( create: (context) { return AuthenticationBloc(userRepository: userRepository) ..add(AppStarted()); }, child: SundayFundayApp(userRepository: userRepository), )); } class SundayFundayApp extends StatelessWidget { // This widget is the root of your application. final UserRepository userRepository; SundayFundayApp({Key key, @required this.userRepository}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'The Yard Mobile App', theme: ThemeData( primarySwatch: Colors.yellow, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: BlocBuilder<AuthenticationBloc, AuthenticationState>( builder: (context, state) { if (state is AuthenticationUnintialized) { return SplashPage(); } if (state is AuthenticationAuthenticated) { return HomeScreen(); } if (state is AuthenticationUnauthenticated) { return LogInScreen( userRepository: userRepository, ); } if (state is AuthenticationLoading) { return LoadingIndicator(); } }, ), ); } }
user_repository.dart
import 'dart:async'; import '../models/user_model.dart'; import 'package:meta/meta.dart'; import '../models/api_model.dart'; import '../api_connection/api_connection.dart'; import '../dba/user_dba.dart'; class UserRepository { final userDao = UserDba(); Future<User> authenticate({ @required String username, @required String password, }) async { UserLogin userLogin = UserLogin(username: username, password: password); Token token = await getToken(userLogin); User user = User( id: 0, username: username, token: token.token, ); return user; } Future<void> persistToken({@required User user}) async { // write token with the user to the database await userDao.createUser(user); } Future<void> deleteToken({@required int id}) async { await userDao.deleteUser(id); } Future<bool> hasToken() async { bool result = await userDao.checkUser(0); return result; } }
user_dao.dart:
import '../database/user_database.dart'; import '../models/user_model.dart'; class UserDao { final dbProvider = DatabaseProvider.dbProvider; Future<int> createUser(User user) async { final db = await dbProvider.database; var result = db.insert(userTable, user.toDatabaseJson()); return result; } Future<int> deleteUser(int id) async { final db = await dbProvider.database; var result = await db .delete(userTable, where: "id = ?", whereArgs: [id]); return result; } Future<bool> checkUser(int id) async { final db = await dbProvider.database; try { List<Map> users = await db .query(userTable, where: 'id = ?', whereArgs: [id]); if (users.length > 0) { return true; } else { return false; } } catch (error) { return false; } } }
login_screen.dart:
import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import '../../repository/user_repository.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../bloc/authentication/authentication_bloc.dart'; import './bloc/login_bloc.dart'; import 'login_form.dart'; class LogInScreen extends StatelessWidget { final UserRepository userRepository; LogInScreen({Key key, @required this.userRepository}) : assert(userRepository != null), super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( // Here we take the value from the MyHomePage object that was created by // the App.build method, and use it to set our appbar title. title: Text('The Yard App'), ), body: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/theyardbook.png'), fit: BoxFit.cover, ) ), child: BlocProvider( create: (context) { return LoginBloc( authenticationBloc: BlocProvider.of<AuthenticationBloc>(context), userRepository: userRepository, ); }, child: Container( child: Scaffold( backgroundColor: Colors.transparent, body: Container( width: MediaQuery.of(context).size.width, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: Colors.transparent, ), child: Padding( padding: EdgeInsets.all(23), child: LoginForm(), ), ), ), ), ), ), ); } }
Once the user is logged in, the app takes you to a home screen and it is this screen I have placed a button to take me to another screen which will fetch data from the server to display. For now the only data available is the one single registered user which is fine, I just need to see how it works because I am totally stuck and have been for 3 days. What I need to know, is how do I access the authentication token?? I am assuming (hoping) the process will be the same accessing any data saved to a local db.
TIA
I can copy and paste more code but I feel like there is a lot there and the tutorial is pretty clear, it just help me with this final
-
Pedro R. almost 4 yearsI think you could implement a method to retrieve the stored token in your UserRepository class. And then call that method to get the token every time you are making a request to the server.
-
HubertBlu almost 4 yearsOk that makes sense just wondered if there was a other way specific to dart/flutter thanks!
-
-
BartusZak over 3 yearsI still feel like that solution is not fully following
BLoC
pattern assumptions. -
HubertBlu over 3 yearsThat may be so I was only playing around with Flutter for the first time. I'd be delighted to see the correct way to do things.