Home > Blockchain >  How to store Cookies in flutter and use it to authenticate if user is logged in or not
How to store Cookies in flutter and use it to authenticate if user is logged in or not

Time:06-15

I'm trying to create a platform, once I log in it, creates a token and store it in the cookie. I have successfully been able to create a route that stores the cookie using node js(I could see it saved in postman). But once I try to use the route in my flutter app, it seems the the token doesn't save anywhere.

How do I save the cookie and use it to validate if the user should be logged in or should log in again

Login.dart

Future<void> _signIn(email, password) async {
    try {
      setState(() {
        LoadingWidget.show(context);
        bool _absorbme = true;
      });

      var url = "http://192.168.8.23:3000/route/login"; // iOS
      final http.Response response = await http.post(
        Uri.parse(url),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: jsonEncode(<String, String>{
          'email': email.toLowerCase(),
          'password': password,
        }),
      );

      SharedPreferences prefs = await SharedPreferences.getInstance();
      var parse = jsonDecode(response.body);
      await prefs.setString('msg', parse["msg"]);
      await prefs.setString('success', parse["success"]);
      String? msg = prefs.getString("msg");

    } finally {
      setState(() {
        LoadingWidget.hide(context);
        bool _absorbme = false;
      });
    }
  }

My Route.js file

const express = require('express');
const router = express.Router();
const Users = require('./model/model')
const passport = require('passport')
const bcrypt = require("bcrypt");
const { createTokens, validateToken, authenticateToken } = require("./JWT");
const Server = require('http-proxy');
router.get('/', (req, res)=>{
  res.send('Hello world')
})

router.post("/signup", async (req, res) =>  {

  const { username, email, password } = req.body;
  let user = await Users.findOne({ email });

  if (user){ 
    
    return res.status(400).json({success: 'false', msg: "Email Already Exist"});
  }
  bcrypt.hash(password, 10).then((hash) => {
    Users.create({
      username: username,
      password: hash,
      email:email,
    })
      .then(() => {
        res.json({success: 'true', msg: 'login Successfully'});
      })
      .catch((err) => {
        if (err) {
          res.status(400).json({success: 'false', msg: 'Failed to save'});
        }
      });
  });
});

router.post("/login", async (req, res) => {
  const { email, password } = req.body;

  let user = await Users.findOne({ email });

  if (!user) {
    
    return res.status(400).json({success: 'false', msg: 'Authentication Failed, User not found'});
  }

  const dbPassword = user.password;
  bcrypt.compare(password, dbPassword).then((match) => {
    if (!match) {
      res
        .status(400)
        .json({success: 'false',  msg: 'Authentication failed, wrong password'});
    } else {
      const accessToken = createTokens(user);

      var token = res.cookie("access-token", accessToken, {
        maxAge: 60 * 60 * 24 * 30 * 1000,
        httpOnly: true,
      });
      
      res
        .status(200)
        .json({success: 'true',  msg: 'Successfully logged In'});
    }
  });
});

router.get("/profile", validateToken, async (req, res) => {
 let user = await Users.findOne({email: req.decoded.email});
 return res.json({
   email: user.email, 
   balance: user.balance,
   name: user.username
})


router.get("/logout", validateToken, (req, res) => {
  return res
    .clearCookie("access-token")
    .status(200)
    .json({success: "true" , msg: "Successfully logged out" });
});

router.get("/authenticate" ,authenticateToken, (req,res)=>{

})


  module.exports = router;

enter image description here

CodePudding user response:

Why not use JWT it can help you manage your users for the numbers of hours you specified

CodePudding user response:

Create authorize endpoint on your api to refresh token when expired. In dart side, create an authenticated client singleton.

class AuthenticatedClient extends http.BaseClient {
  factory AuthenticatedClient() => _instance;
  AuthenticatedClient._();

  static final _instance = AuthenticatedClient._();

  int? expiresAt;
  String? token;
  final _client = http.Client();

  void setParams(http.Response res) {
    final response = jsonDecode(res.body);

    expiresAt = response['expiresAt'];
    token = response['token'];
  }

  Future<void> authorize() async {
    // Send a request to refresh token, update token and expiresAt
    // accordingly. Note that, you can't use _client to send request, use 
    // htt.put, http.post.
    // Ex:
    //
    // final response = await http.put(
    //  Uri.parse('https://myapi.com/authorize'),
    //  headers: {
    //    'Content-Type': 'application/json',
    //  },
    //  body: jsonEncode({
    //    'email': <email>,
    //    'password': <password>,
    //  }),
    // );
    //
    // setParams(response);
  }

  @override
  Future<http.StreamedResponse> send(http.BaseRequest request) async {
    // Ensure you set params for the first time.
    assert(expiresAt != null);

    if (expiresAt! < DateTime.now().millisecondsSinceEpoch) {
      await authorize();
    }

    request.headers['Authorization'] = 'Bearer $token';

    return _client.send(request);
  }
}

On your api, generate a token on login or signup request and send token to client. For this example, response format is that:

{
  'token': <generated token>,
  'expiresAt': <timestamp>,
}

When you got response, call setParams method of AuthenticatedClient and set request params. I didn't add code for error handling to the example, don't forget to add.

Use AuthenticatedClient like this:

AuthenticatedClient().get(Uri.parse('https://myapi/profile'));
  • Related