In one of my most recent applications, known as Gift Grab, the concept of a user's "session" was implemented in a rather simplistic way.
It was solely based on whether the user had signed into the app or not.
Unfortunately, this approach did not take into account the exact moment of sign-in or the duration of the user's interaction with the app.
However, as I delved deeper into the comprehensive and detailed documentation provided by Nakama, a realization dawned on me.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:nakama/nakama.dart';
import 'package:nakama_ui/data/services/hive_session_service.dart';
/// Provider used to check if the user is authenticated.
class NakamaAuthProvider extends AsyncNotifier<bool> {
/// HiveSessionService instance.
final _hiveSessionService = HiveSessionService();
@override
FutureOr<bool> build() async {
// Initialize Nakama client.
getNakamaClient(
host: '127.0.0.1',
ssl: false,
serverKey: 'defaultkey',
httpPort: 7350,
);
// Fetch the current session.
final session = await _hiveSessionService.sessionActive();
return session != null;
}
}
It became clear that I should be leveraging the concept of sessions to manage user interactions with the app in a much more effective and efficient way.
To provide a bit of context, broadly speaking, a "session" refers to a distinct period during which a user is authenticated with a particular system.
It represents an established connection between the user and the system, facilitating a secure and personalized interaction.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:nakama/nakama.dart';
import 'package:nakama_ui/data/services/hive_session_service.dart';
/// Provider that handles listing/creating leaderboard records.
class NakamaLeaderboardProvider extends AsyncNotifier<List<LeaderboardRecord>> {
/// Leaderboard name.
static const _leaderboardName = 'weekly_leaderboard';
/// HiveSessionService instance.
final _hiveSessionService = HiveSessionService();
@override
FutureOr<List<LeaderboardRecord>> build() async {
// Fetch the current session.
final session = await _hiveSessionService.sessionActive();
// If session is null, return empty list.
if (session == null) {
return [];
}
// Get leaderboard records.
final leaderboardRecordList =
await getNakamaClient().listLeaderboardRecords(
session: session,
leaderboardName: _leaderboardName,
);
// Return leaderboard records from list.
return leaderboardRecordList.records;
}
}
In the context of Nakama, the session takes on an even more critical role. It is represented as a client-side object that authenticates the client when they are accessing server functions.
This implementation provides a significantly more secure way for users to interact with server functions, thereby improving overall app security.
// Decode the session token.
final res = JwtDecoder.decode(session.token);
// Return session data from decoded token.
return SessionData(
uid: res['uid'],
username: res['usn'],
email: res['vrs']['email'],
expiresAt: DateTime.fromMillisecondsSinceEpoch(res['exp'] * 1000),
);
There is more to come on this topic, so stay tuned for more insights and revelations in the near future.