Skip to content

Commit

Permalink
Add debug logs to anti-csrf, cookie and dio related code
Browse files Browse the repository at this point in the history
  • Loading branch information
deepjyoti30-st committed Sep 26, 2024
1 parent 8e3f253 commit 49c5ced
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 0 deletions.
6 changes: 6 additions & 0 deletions lib/src/anti-csrf.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:shared_preferences/shared_preferences.dart';
import 'package:supertokens_flutter/src/logger.dart';

class _AntiCSRFInfo {
String? antiCSRF;
Expand All @@ -15,6 +16,8 @@ class AntiCSRF {
static String _sharedPreferencesKey = "supertokens-flutter-anti-csrf";

static Future<String?> getToken(String? associatedAccessTokenUpdate) async {
logDebugMessage('Getting token...')
logDebugMessage('associatedAccessTokenUpdate: ${associatedAccessTokenUpdate}')
if (associatedAccessTokenUpdate == null) {
AntiCSRF._antiCSRFInfo = null;
return null;
Expand Down Expand Up @@ -43,6 +46,8 @@ class AntiCSRF {

static Future<void> setToken(
String antiCSRFToken, String? associatedAccessTokenUpdate) async {
logDebugMessage('Setting token...')
logDebugMessage('associatedAccessTokenUpdate: ${associatedAccessTokenUpdate}')
if (associatedAccessTokenUpdate == null) {
AntiCSRF._antiCSRFInfo = null;
return;
Expand All @@ -58,6 +63,7 @@ class AntiCSRF {
}

static Future<void> removeToken() async {
logDebugMessage('Removing token...')
SharedPreferences preferences = await SharedPreferences.getInstance();
await preferences.remove(AntiCSRF._sharedPreferencesKey);
await preferences.reload();
Expand Down
15 changes: 15 additions & 0 deletions lib/src/cookie-store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:io';

import 'package:shared_preferences/shared_preferences.dart';
import 'package:supertokens_flutter/src/logger.dart';

class SuperTokensCookieStore {
static Map<Uri, List<Cookie>>? _allCookies;
Expand All @@ -24,10 +25,12 @@ class SuperTokensCookieStore {

/// Loads all cookies stored in shared preferences into the in memory map [_allCookies]
static Future<void> _loadFromPersistence() async {
logDebugMessage('Trying to load cookies from memory')
_allCookies = {};
String cookiesStringInStorage =
_sharedPreferences?.getString(_cookieSharedPrefsKey) ?? "{}";
Map<String, dynamic> cookiesInStorage = jsonDecode(cookiesStringInStorage);
logDebugMessage('cookies found: ${jsonEncode(cookiesInStorage)}')
cookiesInStorage.forEach((key, value) {
Uri uri = Uri.parse(key);
List<String> cookieStrings = List.from(value);
Expand All @@ -49,6 +52,8 @@ class SuperTokensCookieStore {
///
/// If you are trying to store cookies from a "set-cookie" header response, consider using the [saveFromSetCookieHeader] utility method which parses the header string.
Future<void> saveFromResponse(Uri uri, List<Cookie> cookies) async {
logDebugMessage('Saving cookies against: ${uri}')
logDebugMessage('Passed cookies: ${jsonEncode(cookies)}')
await Future.forEach<Cookie>(cookies, (element) async {
Uri uriToStore = await _getCookieUri(uri, element);
List<Cookie> currentCookies = _allCookies?[uriToStore] ?? List.from([]);
Expand Down Expand Up @@ -76,6 +81,7 @@ class SuperTokensCookieStore {

/// Returns a Uri to use when saving the cookie
Future<Uri> _getCookieUri(Uri requestUri, Cookie cookie) async {
logDebugMessage('Creating cookie uri from: ${requestUri}')
Uri cookieUri = Uri.parse(
// ignore: unnecessary_null_comparison
"${requestUri.scheme == null ? "http" : requestUri.scheme}://${requestUri.host}${cookie.path == null ? "" : cookie.path}");
Expand All @@ -98,13 +104,15 @@ class SuperTokensCookieStore {
}
}

logDebugMessage('Generated cookie uri: ${cookieUri}')
return cookieUri;
}

/// Uses the [_allCookies] map to update values in shared preferences.
///
/// Strips expired cookies before storing in shared preferences
Future<void> _updatePersistentStorage() async {
logDebugMessage('Updating persistent storage with cookies...')
Map<String, List<String>> mapToStore = {};
_allCookies?.forEach((key, value) {
String uriString = key.toString();
Expand All @@ -123,10 +131,12 @@ class SuperTokensCookieStore {
///
/// If you are trying to add cookies to a "cookie" header for a network call, consider using the [getCookieHeaderStringForRequest] which creates a semi-colon separated cookie string for a given Uri.
Future<List<Cookie>> getForRequest(Uri uri) async {
logDebugMessage('Getting cookies for request from uri: ${uri}')
List<Cookie> cookiesToReturn = [];
List<Cookie> allValidCookies = [];

if (_allCookies == null) {
logDebugMessage('No cookies found')
return cookiesToReturn;
}

Expand Down Expand Up @@ -155,6 +165,7 @@ class SuperTokensCookieStore {
}
}

logDebugMessage('Total cookies found ${cookiesToReturn.length}')
return cookiesToReturn;
}

Expand All @@ -175,6 +186,7 @@ class SuperTokensCookieStore {
/// Removes a list of cookies from persistent storage
Future<void> _removeFromPersistence(
Uri uri, List<Cookie> cookiesToRemove) async {
logDebugMessage('Removing cookies from persistent storage...')
List<Cookie> _cookiesToRemove = List.from(cookiesToRemove);
List<Cookie> currentCookies = _allCookies?[uri] ?? List.from([]);

Expand All @@ -192,6 +204,7 @@ class SuperTokensCookieStore {
///
/// Does not return expired cookies and will remove them from persistent storage if any are found.
Future<String> getCookieHeaderStringForRequest(Uri uri) async {
logDebugMessage('Getting cookie header for request from uri: ${uri}')
List<Cookie> cookies = await getForRequest(uri);
// ignore: unnecessary_null_comparison
if (cookies != null && cookies.isNotEmpty) {
Expand All @@ -214,6 +227,7 @@ class SuperTokensCookieStore {
///
/// Expired cookies are not saved.
Future<void> saveFromSetCookieHeader(Uri uri, String? setCookieHeader) async {
logDebugMessage('Saving cookie from header against uri: ${uri}')
if (setCookieHeader != null) {
await saveFromResponse(uri, getCookieListFromHeader(setCookieHeader));
}
Expand All @@ -224,6 +238,7 @@ class SuperTokensCookieStore {
setCookieHeader.split(RegExp(r',(?=[^ ])'));
List<Cookie> setCookiesList =
setCookiesStringList.map((e) => Cookie.fromSetCookieValue(e)).toList();
logDebugMessage('Total cookies found in header: ${setCookiesList.length}')
return setCookiesList;
}
}
12 changes: 12 additions & 0 deletions lib/src/dio-interceptor-wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:supertokens_flutter/src/front-token.dart';
import 'package:supertokens_flutter/src/supertokens-http-client.dart';
import 'package:supertokens_flutter/src/supertokens.dart';
import 'package:supertokens_flutter/src/utilities.dart';
import 'package:supertokens_flutter/src/logger.dart';

class SuperTokensInterceptorWrapper extends Interceptor {
ReadWriteMutex _refreshAPILock = ReadWriteMutex();
Expand All @@ -22,6 +23,7 @@ class SuperTokensInterceptorWrapper extends Interceptor {
@override
void onRequest(
RequestOptions options, RequestInterceptorHandler handler) async {
logDebugMessage('Intercepting request call')
if (!SuperTokens.isInitCalled) {
handler.reject(DioException(
requestOptions: options,
Expand All @@ -33,10 +35,13 @@ class SuperTokensInterceptorWrapper extends Interceptor {
}

if (!shouldRunDioInterceptor(options)) {
logDebugMessage('Skipping dio interceptor')
return super.onRequest(options, handler);
}

logDebugMessage('Running dio interceptor')
if (Client.cookieStore == null) {
logDebugMessage('Initializing cookie store')
Client.cookieStore = SuperTokensCookieStore();
}

Expand Down Expand Up @@ -70,6 +75,7 @@ class SuperTokensInterceptorWrapper extends Interceptor {

// If the request already has a "cookie" header, combine it with persistent cookies
if (existingCookieHeader != null) {
logDebugMessage('Combining cookie header values')
options.headers[HttpHeaders.cookieHeader] =
"$existingCookieHeader;${newCookiesToAdd ?? ""}";
} else {
Expand All @@ -90,9 +96,13 @@ class SuperTokensInterceptorWrapper extends Interceptor {

@override
void onResponse(Response response, ResponseInterceptorHandler handler) async {
logDebugMessage('Intercepting response call')
if (!shouldRunDioInterceptor(response.requestOptions)) {
logDebugMessage('Skipping dio interceptor')
return handler.next(response);
}

logDebugMessage('Running dio interceptor')
_refreshAPILock.acquireWrite();
await saveTokensFromHeaders(response);
String? frontTokenFromResponse =
Expand Down Expand Up @@ -122,6 +132,7 @@ class SuperTokensInterceptorWrapper extends Interceptor {
requestOptions.extra["__supertokensSessionRefreshAttempts"] ?? 0;
if (sessionRefreshAttempts >=
SuperTokens.config.maxRetryAttemptsForSessionRefresh) {
logDebugMessage('Max attempts of ${SuperTokens.config.maxRetryAttemptsForSessionRefresh} reached for refreshing, cannot continue')
handler.reject(
DioException(
requestOptions: response.requestOptions,
Expand All @@ -139,6 +150,7 @@ class SuperTokensInterceptorWrapper extends Interceptor {
UnauthorisedResponse shouldRetry =
await Client.onUnauthorisedResponse(_preRequestLocalSessionState);
if (shouldRetry.status == UnauthorisedStatus.RETRY) {
logDebugMessage('Refreshing attempt: ${sessionRefreshAttempts + 1}')
requestOptions.headers[HttpHeaders.cookieHeader] = userSetCookie;

requestOptions.extra["__supertokensSessionRefreshAttempts"] =
Expand Down
4 changes: 4 additions & 0 deletions lib/src/supertokens.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class SuperTokens {
static Future<bool> doesSessionExist() async {
Map<String, dynamic>? tokenInfo = await FrontToken.getToken();

logDebugMessage('Got token info: ${jsonEncode(tokenInfo)}')
if (tokenInfo == null) {
return false;
}
Expand Down Expand Up @@ -120,6 +121,7 @@ class SuperTokens {
}

static Future<void> signOut({Function(Exception?)? completionHandler}) async {
logDebugMessage('Signing out user...')
if (!(await doesSessionExist())) {
SuperTokens.config.eventHandler(Eventype.SIGN_OUT);
if (completionHandler != null) {
Expand All @@ -139,6 +141,7 @@ class SuperTokens {
return;
}

logDebugMessage('Using signOutUrl: ${uri}')
http.Request signOut = http.Request('post', uri);
signOut = SuperTokens.config.preAPIHook(APIAction.SIGN_OUT, signOut);

Expand Down Expand Up @@ -174,6 +177,7 @@ class SuperTokens {
}

static Future<bool> attemptRefreshingSession() async {
logDebugMessage('Attempting to refresh session...')
LocalSessionState preRequestLocalSessionState =
await SuperTokensUtils.getLocalSessionState();
bool shouldRetry = false;
Expand Down

0 comments on commit 49c5ced

Please sign in to comment.