How do I access the authentication token obtained on Login using BloC with Flutter

3,062

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
            }
          },
        ),
      ),
    );
  }
}
Share:
3,062
HubertBlu
Author by

HubertBlu

Updated on December 23, 2022

Comments

  • HubertBlu
    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.
      Pedro R. almost 4 years
      I 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
      HubertBlu almost 4 years
      Ok that makes sense just wondered if there was a other way specific to dart/flutter thanks!
  • BartusZak
    BartusZak over 3 years
    I still feel like that solution is not fully followingBLoC pattern assumptions.
  • HubertBlu
    HubertBlu over 3 years
    That 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.