SharedPreferences Flutter.. Set Expiration Time

300 views Asked by At

I am making a application in Flutter.

I have a access token coming from an API which I save in shared preferences for session management and authentication.

But here the catch is that this token expires every 1 hour so I need to clear the shared preferences every 1 hour ..

Package used - shared_preferences

So, How do I do that??

3

There are 3 answers

0
Hamed On

I suppose you can handle this scenario better with other approaches, however, if you want to invalidate your token locally based on a validation time you can do this:

void saveAccessToken(String token) async {
  final prefs = await SharedPreferences.getInstance();
  final now = DateTime.now();

  await prefs.setString('access_token', token);
  await prefs.setString('token_timestamp', now.toIso8601String());
}

Future<String?> getAccessToken() async {
  final prefs = await SharedPreferences.getInstance();
  final token = prefs.getString('access_token');
  final tokenTimestamp = prefs.getString('token_timestamp');

  if (token != null && tokenTimestamp != null) {
    final timestamp = DateTime.parse(tokenTimestamp);
    final currentTime = DateTime.now();
    final tokenDuration = currentTime.difference(timestamp);

    const Duration tokenExpirationDuration = Duration(hours: 1);

    if (tokenDuration <= tokenExpirationDuration) {
      return token;
    } else {
      await clearAccessToken();

      return null;
    }
  }

  return null;
}

0
Syed Minhal On
Timer timer = Timer.periodic(const Duration(hour: 1), (Timer timer) {
  //Clear Shared preference here
});

You can clear using this. But it has some limitation regarding background case.

0
Dharam Budh On

Here's my solution. I've used one feature-rich package, which helps us to decode the JWT Token. Decoding means extracting the information.

I've used: jwt_decoder

import "dart:developer";

import "package:flutter/material.dart";
import "package:jwt_decoder/jwt_decoder.dart";
import "package:shared_preferences/shared_preferences.dart";

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const HomePage(),
      theme: ThemeData(useMaterial3: true),
      debugShowCheckedModeBanner: false,
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  HomePageState createState() => HomePageState();
}

class HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback(
      (Duration timeStamp) async {
        await SharedPrefSingleton.instance.initSharedPreferences();
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: ElevatedButton(
            onPressed: fun,
            child: const Text("Check JWT Token"),
          ),
        ),
      ),
    );
  }

  Future<void> fun() async {
    // Not Expired Token
    // const String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjk5OTk5OTk5OTl9.Vg30C57s3l90JNap_VgMhKZjfc-p7SoBXaSAy8c28HA";

    // Expired Token
    const String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjEyMzQ1Njc4OTB9.Ev7tjNe1-zHZvSeoeEplJ1_xxfWLawVbp_EJXAsdzJU";

    final bool expired = JwtDecoder.isExpired(token);
    log("is token expired: $expired");

    await SharedPrefSingleton.instance.setToken(value: expired ? "New" : token);

    final String getCurrentToken = SharedPrefSingleton.instance.getToken();
    log("CurrentToken: $getCurrentToken");

    return Future<void>.value();
  }
}

class SharedPrefSingleton {
  SharedPrefSingleton._();
  static final SharedPrefSingleton instance = SharedPrefSingleton._();

  SharedPreferences? preferences;

  Future<void> initSharedPreferences() async {
    preferences = await SharedPreferences.getInstance();
    log("Loaded and parsed the SharedPreferences for this app from disk.");
    return Future<void>.value();
  }

  Future<bool> setToken({required String value}) async {
    final bool isSaved = await preferences?.setString("jwtKey", value) ?? false;
    log("Token Saved: ${isSaved ? "Successfully" : "Unsuccessfully"}");
    return Future<bool>.value(isSaved);
  }

  String getToken() {
    final String value = preferences?.getString("jwtKey") ?? "";
    log("Token value: $value");
    return value;
  }
}