Skip to content

Commit

Permalink
Merge pull request #61 from supertokens/fix/remove_redundant_removeTo…
Browse files Browse the repository at this point in the history
…kens

fix: remove redundant remove tokens
  • Loading branch information
rishabhpoddar authored Jul 24, 2024
2 parents 2d9b7c3 + 67c6703 commit 6bdfaaf
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 123 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.6.1] - 2024-07-12

### Changes

- Removed redundant calls to `removeToken`

## [0.6.0] - 2024-06-05

### Changes
Expand Down
7 changes: 0 additions & 7 deletions lib/src/dio-interceptor-wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,6 @@ class SuperTokensInterceptorWrapper extends Interceptor {
type: DioExceptionType.unknown,
error: e),
);
} finally {
LocalSessionState localSessionState =
await SuperTokensUtils.getLocalSessionState();
if (localSessionState.status == LocalSessionStateStatus.NOT_EXISTS) {
await AntiCSRF.removeToken();
await FrontToken.removeToken();
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions lib/src/front-token.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:mutex/mutex.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:supertokens_flutter/src/utilities.dart';
import 'package:supertokens_flutter/supertokens.dart';
import 'package:supertokens_flutter/src/anti-csrf.dart';

class FrontToken {
static String? tokenInMemory;
Expand Down Expand Up @@ -148,6 +149,7 @@ class FrontToken {
await _removeTokenFromStorage();
await Utils.setToken(TokenType.ACCESS, "");
await Utils.setToken(TokenType.REFRESH, "");
await AntiCSRF.removeToken()
if (_tokenInfoMutex.isLocked) {
_tokenInfoMutex.release();
}
Expand Down
201 changes: 87 additions & 114 deletions lib/src/supertokens-http-client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,107 +74,98 @@ class Client extends http.BaseClient {
return _innerClient.send(customRequest.request);
}

try {
while (true) {
await _refreshAPILock.acquireRead();
// http package does not allow retries with the same request object, so we clone the request when making the network call
http.BaseRequest copiedRequest;
LocalSessionState preRequestLocalSessionState;
http.StreamedResponse response;
try {
copiedRequest = SuperTokensUtils.copyRequest(customRequest.request);
copiedRequest =
await _removeAuthHeaderIfMatchesLocalToken(copiedRequest);
preRequestLocalSessionState =
await SuperTokensUtils.getLocalSessionState();
String? antiCSRFToken = await AntiCSRF.getToken(
preRequestLocalSessionState.lastAccessTokenUpdate);

if (antiCSRFToken != null) {
copiedRequest.headers[antiCSRFHeaderKey] = antiCSRFToken;
}

SuperTokensTokenTransferMethod tokenTransferMethod =
SuperTokens.config.tokenTransferMethod;
copiedRequest.headers["st-auth-mode"] =
tokenTransferMethod.getValue();

// Adding Authorization headers
copiedRequest =
await Utils.setAuthorizationHeaderIfRequired(copiedRequest);

// Add cookies to request headers
String? newCookiesToAdd = await Client.cookieStore
?.getCookieHeaderStringForRequest(copiedRequest.url);
String? existingCookieHeader =
copiedRequest.headers[HttpHeaders.cookieHeader];

// If the request already has a "cookie" header, combine it with persistent cookies
if (existingCookieHeader != null && existingCookieHeader != "") {
copiedRequest.headers[HttpHeaders.cookieHeader] =
_generateCookieHeader(existingCookieHeader, newCookiesToAdd);
} else {
copiedRequest.headers[HttpHeaders.cookieHeader] =
newCookiesToAdd ?? "";
}

// http package does not allow retries with the same request object, so we clone the request when making the network call
response = await _innerClient.send(copiedRequest);
await Utils.saveTokenFromHeaders(response);
String? frontTokenInHeaders = response.headers[frontTokenHeaderKey];
SuperTokensUtils.fireSessionUpdateEventsIfNecessary(
wasLoggedIn: preRequestLocalSessionState.status ==
LocalSessionStateStatus.EXISTS,
status: response.statusCode,
frontTokenFromResponse: frontTokenInHeaders,
);

// Save cookies from the response
String? setCookieFromResponse =
response.headers[HttpHeaders.setCookieHeader];
await Client.cookieStore?.saveFromSetCookieHeader(
copiedRequest.url, setCookieFromResponse);
} finally {
_refreshAPILock.release();
while (true) {
await _refreshAPILock.acquireRead();
// http package does not allow retries with the same request object, so we clone the request when making the network call
http.BaseRequest copiedRequest;
LocalSessionState preRequestLocalSessionState;
http.StreamedResponse response;
try {
copiedRequest = SuperTokensUtils.copyRequest(customRequest.request);
copiedRequest =
await _removeAuthHeaderIfMatchesLocalToken(copiedRequest);
preRequestLocalSessionState =
await SuperTokensUtils.getLocalSessionState();
String? antiCSRFToken = await AntiCSRF.getToken(
preRequestLocalSessionState.lastAccessTokenUpdate);

if (antiCSRFToken != null) {
copiedRequest.headers[antiCSRFHeaderKey] = antiCSRFToken;
}

if (response.statusCode == SuperTokens.sessionExpiryStatusCode) {
/**
* An API may return a 401 error response even with a valid session, causing a session refresh loop in the interceptor.
* To prevent this infinite loop, we break out of the loop after retrying the original request a specified number of times.
* The maximum number of retry attempts is defined by maxRetryAttemptsForSessionRefresh config variable.
*/
if (customRequest.sessionRefreshAttempts >=
SuperTokens.config.maxRetryAttemptsForSessionRefresh) {
throw SuperTokensException(
"Received a 401 response from ${customRequest.request.url}. Attempted to refresh the session and retry the request with the updated session tokens ${SuperTokens.config.maxRetryAttemptsForSessionRefresh} times, but each attempt resulted in a 401 error. The maximum session refresh limit has been reached. Please investigate your API. To increase the session refresh attempts, update maxRetryAttemptsForSessionRefresh in the config.");
}
customRequest.sessionRefreshAttempts++;

customRequest.request =
await _removeAuthHeaderIfMatchesLocalToken(copiedRequest);

UnauthorisedResponse shouldRetry =
await onUnauthorisedResponse(preRequestLocalSessionState);
if (shouldRetry.status == UnauthorisedStatus.RETRY) {
// Here we use the original request because it wont contain any of the modifications we make
return await _sendWithRetry(customRequest);
} else {
if (shouldRetry.exception != null) {
throw SuperTokensException(shouldRetry.exception!.message);
} else
return response;
}
SuperTokensTokenTransferMethod tokenTransferMethod =
SuperTokens.config.tokenTransferMethod;
copiedRequest.headers["st-auth-mode"] =
tokenTransferMethod.getValue();

// Adding Authorization headers
copiedRequest =
await Utils.setAuthorizationHeaderIfRequired(copiedRequest);

// Add cookies to request headers
String? newCookiesToAdd = await Client.cookieStore
?.getCookieHeaderStringForRequest(copiedRequest.url);
String? existingCookieHeader =
copiedRequest.headers[HttpHeaders.cookieHeader];

// If the request already has a "cookie" header, combine it with persistent cookies
if (existingCookieHeader != null && existingCookieHeader != "") {
copiedRequest.headers[HttpHeaders.cookieHeader] =
_generateCookieHeader(existingCookieHeader, newCookiesToAdd);
} else {
return response;
copiedRequest.headers[HttpHeaders.cookieHeader] =
newCookiesToAdd ?? "";
}

// http package does not allow retries with the same request object, so we clone the request when making the network call
response = await _innerClient.send(copiedRequest);
await Utils.saveTokenFromHeaders(response);
String? frontTokenInHeaders = response.headers[frontTokenHeaderKey];
SuperTokensUtils.fireSessionUpdateEventsIfNecessary(
wasLoggedIn: preRequestLocalSessionState.status ==
LocalSessionStateStatus.EXISTS,
status: response.statusCode,
frontTokenFromResponse: frontTokenInHeaders,
);

// Save cookies from the response
String? setCookieFromResponse =
response.headers[HttpHeaders.setCookieHeader];
await Client.cookieStore?.saveFromSetCookieHeader(
copiedRequest.url, setCookieFromResponse);
} finally {
_refreshAPILock.release();
}
} finally {
LocalSessionState localSessionState =
await SuperTokensUtils.getLocalSessionState();
if (localSessionState.status == LocalSessionStateStatus.NOT_EXISTS) {
await AntiCSRF.removeToken();
await FrontToken.removeToken();

if (response.statusCode == SuperTokens.sessionExpiryStatusCode) {
/**
* An API may return a 401 error response even with a valid session, causing a session refresh loop in the interceptor.
* To prevent this infinite loop, we break out of the loop after retrying the original request a specified number of times.
* The maximum number of retry attempts is defined by maxRetryAttemptsForSessionRefresh config variable.
*/
if (customRequest.sessionRefreshAttempts >=
SuperTokens.config.maxRetryAttemptsForSessionRefresh) {
throw SuperTokensException(
"Received a 401 response from ${customRequest.request.url}. Attempted to refresh the session and retry the request with the updated session tokens ${SuperTokens.config.maxRetryAttemptsForSessionRefresh} times, but each attempt resulted in a 401 error. The maximum session refresh limit has been reached. Please investigate your API. To increase the session refresh attempts, update maxRetryAttemptsForSessionRefresh in the config.");
}
customRequest.sessionRefreshAttempts++;

customRequest.request =
await _removeAuthHeaderIfMatchesLocalToken(copiedRequest);

UnauthorisedResponse shouldRetry =
await onUnauthorisedResponse(preRequestLocalSessionState);
if (shouldRetry.status == UnauthorisedStatus.RETRY) {
// Here we use the original request because it wont contain any of the modifications we make
return await _sendWithRetry(customRequest);
} else {
if (shouldRetry.exception != null) {
throw SuperTokensException(shouldRetry.exception!.message);
} else
return response;
}
} else {
return response;
}
}
}
Expand Down Expand Up @@ -302,28 +293,10 @@ class Client extends http.BaseClient {
status: UnauthorisedStatus.API_ERROR,
error: SuperTokensException("Some unknown error occured"));
} finally {
LocalSessionState localSessionState =
await SuperTokensUtils.getLocalSessionState();

if (localSessionState.status == LocalSessionStateStatus.NOT_EXISTS) {
await FrontToken.removeToken();
await AntiCSRF.removeToken();
}

_refreshAPILock.release();
}
}

static Future clearTokensIfRequired() async {
LocalSessionState preRequestLocalSessionState =
await SuperTokensUtils.getLocalSessionState();
if (preRequestLocalSessionState.status ==
LocalSessionStateStatus.NOT_EXISTS) {
await AntiCSRF.removeToken();
await FrontToken.removeToken();
}
}

static String _cookieMapToHeaderString(Map<String, dynamic> cookieMap) {
return cookieMap.keys.map((e) => "$e=${cookieMap[e]}").join(";");
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/version.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ class Version {
"2.0",
"3.0"
];
static String sdkVersion = "0.6.0";
static String sdkVersion = "0.6.1";
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: supertokens_flutter
description: SuperTokens SDK for Flutter apps
version: 0.6.0
version: 0.6.1
homepage: https://supertokens.com/
repository: https://github.com/supertokens/supertokens-flutter
issue_tracker: https://github.com/supertokens/supertokens-flutter/issues
Expand Down

0 comments on commit 6bdfaaf

Please sign in to comment.