Skip to content

Commit

Permalink
Add more logs and make them have function as prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
deepjyoti30-st committed Sep 30, 2024
1 parent ae00a85 commit 2686977
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 23 deletions.
2 changes: 1 addition & 1 deletion lib/src/logger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ void disableLogging() {
void logDebugMessage(String message) {
if (_supertokensWebsiteLogging) {
print(
'$supertokensDebugNamespace {t: "${DateTime.now().toIso8601String()}", message: "$message", supertokens-react-native: "${Version.sdkVersion}"}');
'$supertokensDebugNamespace {t: "${DateTime.now().toIso8601String()}", message: "$message", supertokens-flutter: "${Version.sdkVersion}"}');
}
}
11 changes: 9 additions & 2 deletions lib/src/normalised-url-domain.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ class NormalisedURLDomain {
{bool ignoreProtocal = false}) {
String trimmedInput = input.trim();

logDebugMessage('Normalising url domain: ${input}');
logDebugMessage('NormalisedURLDomain.normaliseUrlDomainOrThrowError: Normalising url domain: ${input}');
try {
if (!trimmedInput.startsWith("http://") &&
!trimmedInput.startsWith("https://")) {
logDebugMessage('NormalisedURLDomain.normaliseUrlDomainOrThrowError: Does not start with http');
throw SuperTokensException("failable error");
}

Expand All @@ -26,18 +27,24 @@ class NormalisedURLDomain {
// Flutter returns one of these values if the URL does not have a port
bool hasNoPort = !Utils.doesUrlHavePort(uri);
String hostSuffix = hasNoPort ? hostName : hostName + ":${uri.port}";
logDebugMessage('NormalisedURLDomain.normaliseUrlDomainOrThrowError: hostName: ${hostName}');
logDebugMessage('NormalisedURLDomain.normaliseUrlDomainOrThrowError: scheme: ${scheme}');
logDebugMessage('NormalisedURLDomain.normaliseUrlDomainOrThrowError: hasNoPort: ${hasNoPort}');
logDebugMessage('NormalisedURLDomain.normaliseUrlDomainOrThrowError: hostSuffix: ${hostSuffix}');

if (ignoreProtocal) {
logDebugMessage('NormalisedURLDomain.normaliseUrlDomainOrThrowError: Ignoring protocol');
if (hostName.startsWith("localhost") || Utils.isIPAddress(input)) {
trimmedInput = "https://$hostSuffix";
} else {
trimmedInput = "https://" + hostSuffix;
}
} else {
logDebugMessage('NormalisedURLDomain.normaliseUrlDomainOrThrowError: Keeping protocol');
trimmedInput = scheme + "://" + hostSuffix;
}

logDebugMessage('Normalised value: ${trimmedInput}');
logDebugMessage('NormalisedURLDomain.normaliseUrlDomainOrThrowError: Normalised value: ${trimmedInput}');
return trimmedInput;
} catch (e) {}

Expand Down
11 changes: 8 additions & 3 deletions lib/src/normalised-url-path.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,24 @@ class NormalisedURLPath {
}

static String normaliseIRLPathOrThrowError(String input) {
logDebugMessage('Normalising URL path: ${input}');
logDebugMessage('NormalisedURLPath.normaliseIRLPathOrThrowError: Normalising URL path: ${input}');
String trimmedInput = input.trim();

try {
if (!trimmedInput.startsWith('http'))
if (!trimmedInput.startsWith('http')) {
logDebugMessage('NormalisedURLPath.normaliseIRLPathOrThrowError: Got invalid protocol');
throw SuperTokensException('Invalid protocol');
}

Uri url = Uri.parse(trimmedInput);
trimmedInput = url.path;
logDebugMessage('NormalisedURLPath.normaliseIRLPathOrThrowError: trimmedInput: ${trimmedInput}');

if (trimmedInput.endsWith('/')) {
return trimmedInput.substring(0, trimmedInput.length - 1);
}

logDebugMessage('Normalised value: ${trimmedInput}');
logDebugMessage('NormalisedURLPath.normaliseIRLPathOrThrowError: Normalised value: ${trimmedInput}');
return trimmedInput;
} catch (e) {}

Expand All @@ -34,6 +37,7 @@ class NormalisedURLPath {
!trimmedInput.startsWith('http://') &&
!trimmedInput.startsWith('https://')) {
trimmedInput = 'https://' + trimmedInput;
logDebugMessage('NormalisedURLPath.normaliseIRLPathOrThrowError: Determined to be a domain name');
return normaliseIRLPathOrThrowError(trimmedInput);
}

Expand All @@ -59,6 +63,7 @@ class NormalisedURLPath {

static bool isDomainGiven(String input) {
if (input.indexOf('.') == -1 || input.startsWith('/')) {
logDebugMessage('NormalisedURLPath.isDomainGiven: Not a domain');
return false;
}
try {
Expand Down
35 changes: 29 additions & 6 deletions lib/src/supertokens-http-client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ class Client extends http.BaseClient {

Future<http.StreamedResponse> _sendWithRetry(
CustomRequest customRequest) async {
logDebugMessage('Sending request');
logDebugMessage('Client._sendWithRetry: Sending request');
if (Client.cookieStore == null) {
logDebugMessage('Client._sendWithRetry: Initiating cookie store');
Client.cookieStore = SuperTokensCookieStore();
}

Expand All @@ -61,21 +62,21 @@ class Client extends http.BaseClient {

if (SuperTokensUtils.getApiDomain(customRequest.request.url.toString()) !=
SuperTokens.config.apiDomain) {
logDebugMessage('Not matching api domain, using inner client');
logDebugMessage('Client._sendWithRetry: Not matching api domain, using inner client');
return _innerClient.send(customRequest.request);
}

if (SuperTokensUtils.getApiDomain(customRequest.request.url.toString()) ==
SuperTokens.refreshTokenUrl) {
logDebugMessage('Refresh token URL matched');
logDebugMessage('Client._sendWithRetry: Refresh token URL matched');
return _innerClient.send(customRequest.request);
}

if (!Utils.shouldDoInterceptions(
customRequest.request.url.toString(),
SuperTokens.config.apiDomain,
SuperTokens.config.sessionTokenBackendDomain)) {
logDebugMessage('Skipping interceptions');
logDebugMessage('Client._sendWithRetry: Skipping interceptions');
return _innerClient.send(customRequest.request);
}

Expand All @@ -86,6 +87,7 @@ class Client extends http.BaseClient {
LocalSessionState preRequestLocalSessionState;
http.StreamedResponse response;
try {
logDebugMessage('Client._sendWithRetry: Copying request to use it');
copiedRequest = SuperTokensUtils.copyRequest(customRequest.request);
copiedRequest =
await _removeAuthHeaderIfMatchesLocalToken(copiedRequest);
Expand All @@ -95,15 +97,18 @@ class Client extends http.BaseClient {
preRequestLocalSessionState.lastAccessTokenUpdate);

if (antiCSRFToken != null) {
logDebugMessage('Client._sendWithRetry: antiCSRFtoken found, setting it');
copiedRequest.headers[antiCSRFHeaderKey] = antiCSRFToken;
}

SuperTokensTokenTransferMethod tokenTransferMethod =
SuperTokens.config.tokenTransferMethod;
logDebugMessage('Client._sendWithRetry: Setting st-auth-mode');
copiedRequest.headers["st-auth-mode"] =
tokenTransferMethod.getValue();

// Adding Authorization headers
logDebugMessage('Client._sendWithRetry: Adding authorization headers');
copiedRequest =
await Utils.setAuthorizationHeaderIfRequired(copiedRequest);

Expand All @@ -115,9 +120,11 @@ class Client extends http.BaseClient {

// If the request already has a "cookie" header, combine it with persistent cookies
if (existingCookieHeader != null && existingCookieHeader != "") {
logDebugMessage('Client._sendWithRetry: Combining cookies with existing ones');
copiedRequest.headers[HttpHeaders.cookieHeader] =
_generateCookieHeader(existingCookieHeader, newCookiesToAdd);
} else {
logDebugMessage('Client._sendWithRetry: Adding new cookies: ${newCookiesToAdd}');
copiedRequest.headers[HttpHeaders.cookieHeader] =
newCookiesToAdd ?? "";
}
Expand All @@ -134,6 +141,7 @@ class Client extends http.BaseClient {
);

// Save cookies from the response
logDebugMessage('Client._sendWithRetry: Saving cookies from the response');
String? setCookieFromResponse =
response.headers[HttpHeaders.setCookieHeader];
await Client.cookieStore?.saveFromSetCookieHeader(
Expand All @@ -150,12 +158,12 @@ class Client extends http.BaseClient {
*/
if (customRequest.sessionRefreshAttempts >=
SuperTokens.config.maxRetryAttemptsForSessionRefresh) {
logDebugMessage('Max attempts of ${SuperTokens.config.maxRetryAttemptsForSessionRefresh} reached for refreshing, cannot continue');
logDebugMessage('Client._sendWithRetry: Max attempts of ${SuperTokens.config.maxRetryAttemptsForSessionRefresh} reached for refreshing, cannot continue');
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++;
logDebugMessage('Refreshing attempt: ${customRequest.sessionRefreshAttempts}');
logDebugMessage('Client._sendWithRetry: Refreshing attempt: ${customRequest.sessionRefreshAttempts}');

customRequest.request =
await _removeAuthHeaderIfMatchesLocalToken(copiedRequest);
Expand All @@ -164,6 +172,7 @@ class Client extends http.BaseClient {
await onUnauthorisedResponse(preRequestLocalSessionState);
if (shouldRetry.status == UnauthorisedStatus.RETRY) {
// Here we use the original request because it wont contain any of the modifications we make
logDebugMessage('Client._sendWithRetry: Got RETRY status, retrying...');
return await _sendWithRetry(customRequest);
} else {
if (shouldRetry.exception != null) {
Expand Down Expand Up @@ -192,6 +201,7 @@ class Client extends http.BaseClient {
if (accessToken != null &&
refreshToken != null &&
authValue == "Bearer $accessToken") {
logDebugMessage('Client._removeAuthHeaderIfMatchesLocalToken: Removing authorization headers');
mutableRequest.headers.remove("Authorization");
mutableRequest.headers.remove("authorization");
}
Expand All @@ -208,6 +218,7 @@ class Client extends http.BaseClient {
await SuperTokensUtils.getLocalSessionState();
if (postLockLocalSessionState.status ==
LocalSessionStateStatus.NOT_EXISTS) {
logDebugMessage('Client.onUnauthorisedResponse: local session state does not exist, throwing unauthorised error');
SuperTokens.config.eventHandler(Eventype.UNAUTHORISED);
return UnauthorisedResponse(status: UnauthorisedStatus.SESSION_EXPIRED);
}
Expand All @@ -218,6 +229,7 @@ class Client extends http.BaseClient {
LocalSessionStateStatus.EXISTS &&
postLockLocalSessionState.lastAccessTokenUpdate !=
preRequestLocalSessionState.lastAccessTokenUpdate)) {
logDebugMessage('Client.onUnauthorisedResponse: Retry required, throwing retry error');
return UnauthorisedResponse(status: UnauthorisedStatus.RETRY);
}
Uri refreshUrl = Uri.parse(SuperTokens.refreshTokenUrl);
Expand All @@ -228,21 +240,26 @@ class Client extends http.BaseClient {

if (preRequestLocalSessionState.status ==
LocalSessionStateStatus.EXISTS) {
logDebugMessage('Client.onUnauthorisedResponse: preRequestLocalSessionState exists');
String? antiCSRFToken = await AntiCSRF.getToken(
preRequestLocalSessionState.lastAccessTokenUpdate);
if (antiCSRFToken != null) {
logDebugMessage('Client.onUnauthorisedResponse: Setting antiCSRF token');
refreshReq.headers[antiCSRFHeaderKey] = antiCSRFToken;
}
}

logDebugMessage('Client.onUnauthorisedResponse: Setting rid and fdi-version headers');
refreshReq.headers['rid'] = SuperTokens.rid;
refreshReq.headers['fdi-version'] = Version.supported_fdi.join(',');
// Add cookies to request headers
logDebugMessage('Client.onUnauthorisedResponse: Adding cookies to headers');
String? newCookiesToAdd =
await Client.cookieStore?.getCookieHeaderStringForRequest(refreshUrl);
refreshReq.headers[HttpHeaders.cookieHeader] = newCookiesToAdd ?? "";
SuperTokensTokenTransferMethod tokenTransferMethod =
SuperTokens.config.tokenTransferMethod;
logDebugMessage('Client.onUnauthorisedResponse: Setting st-auth-mode');
refreshReq.headers
.addAll({'st-auth-mode': tokenTransferMethod.getValue()});
refreshReq =
Expand All @@ -259,9 +276,11 @@ class Client extends http.BaseClient {

bool isUnauthorised =
response.statusCode == SuperTokens.config.sessionExpiredStatusCode;
logDebugMessage('Client.onUnauthorisedResponse: isUnauthorised: ${isUnauthorised}');

String? frontTokenInHeaders = response.headers[frontTokenHeaderKey];
if (isUnauthorised && frontTokenInHeaders == null) {
logDebugMessage('Client.onUnauthorisedResponse: Removing frontToken by setting remove');
await FrontToken.setItem("remove");
}

Expand Down Expand Up @@ -290,6 +309,7 @@ class Client extends http.BaseClient {
// this is a result of the refresh API returning a session expiry, which
// means that the frontend did not know for sure that the session existed
// in the first place.
logDebugMessage('Client.onUnauthorisedResponse: local session state does not exist');
return UnauthorisedResponse(status: UnauthorisedStatus.SESSION_EXPIRED);
}

Expand All @@ -309,6 +329,7 @@ class Client extends http.BaseClient {
}

static String _generateCookieHeader(String oldCookie, String? newCookie) {
logDebugMessage('Client._generateCookieHeader: Generating cookie header');
if (newCookie == null) {
return oldCookie;
}
Expand All @@ -317,6 +338,8 @@ class Client extends http.BaseClient {
List<Cookie> newCookies =
SuperTokensCookieStore.getCookieListFromHeader(newCookie);
Iterable newCookiesNames = newCookies.map((e) => e.name);
logDebugMessage('Client._generateCookieHeader: oldCookies found: ${oldCookies.length}');
logDebugMessage('Client._generateCookieHeader: newCookies found: ${newCookies.length}');
oldCookies.removeWhere((element) => newCookiesNames.contains(element.name));
newCookies.addAll(oldCookies);
return newCookies.map((e) => e.toString()).join(';');
Expand Down
30 changes: 20 additions & 10 deletions lib/src/supertokens.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class SuperTokens {
enableLogging();
}

logDebugMessage("init: Started SuperTokens with debug logging (supertokens.init called)");
logDebugMessage("SuperTokens.init: Started SuperTokens with debug logging (supertokens.init called)");

SuperTokens.config = NormalisedInputType.normaliseInputType(
apiDomain,
Expand All @@ -74,17 +74,17 @@ class SuperTokens {
postAPIHook,
);

logDebugMessage('config: ${jsonEncode(config.toJson())}');
logDebugMessage('SuperTokens.init: config: ${jsonEncode(config.toJson())}');

SuperTokens.refreshTokenUrl =
config.apiDomain + (config.apiBasePath ?? '') + "/session/refresh";
SuperTokens.signOutUrl =
config.apiDomain + (config.apiBasePath ?? '') + "/signout";
SuperTokens.rid = "session";

logDebugMessage('refreshTokenUrl: ${refreshTokenUrl}');
logDebugMessage('signOutUrl: ${signOutUrl}');
logDebugMessage('rid: ${rid}');
logDebugMessage('SuperTokens.init: refreshTokenUrl: ${refreshTokenUrl}');
logDebugMessage('SuperTokens.init: signOutUrl: ${signOutUrl}');
logDebugMessage('SuperTokens.init: rid: ${rid}');

SuperTokens.isInitCalled = true;
}
Expand All @@ -93,15 +93,17 @@ class SuperTokens {
static Future<bool> doesSessionExist() async {
Map<String, dynamic>? tokenInfo = await FrontToken.getToken();

logDebugMessage('Got token info: ${jsonEncode(tokenInfo)}');
logDebugMessage('SuperTokens.doesSessionExist: Got token info: ${jsonEncode(tokenInfo)}');
if (tokenInfo == null) {
logDebugMessage('SuperTokens.doesSessionExist: token info is null');
return false;
}

int now = DateTime.now().millisecondsSinceEpoch;
int accessTokenExpiry = tokenInfo["ate"];

if (accessTokenExpiry != null && accessTokenExpiry < now) {
logDebugMessage('SuperTokens.doesSessionExist: access token has expired');
LocalSessionState preRequestLocalSessionState =
await SuperTokensUtils.getLocalSessionState();

Expand All @@ -121,10 +123,12 @@ class SuperTokens {
}

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

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

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

static Future<bool> attemptRefreshingSession() async {
logDebugMessage('Attempting to refresh session');
logDebugMessage('SuperTokens.attemptRefreshingSession: Attempting to refresh session');
LocalSessionState preRequestLocalSessionState =
await SuperTokensUtils.getLocalSessionState();
bool shouldRetry = false;
Expand All @@ -186,10 +190,13 @@ class SuperTokens {
dynamic resp =
await Client.onUnauthorisedResponse(preRequestLocalSessionState);
if (resp is UnauthorisedResponse) {
logDebugMessage('SuperTokens.attemptRefreshingSession: Got unauthorised response');
if (resp.status == UnauthorisedStatus.API_ERROR) {
logDebugMessage('SuperTokens.attemptRefreshingSession: Got API error');
exception = resp.error as SuperTokensException;
} else {
shouldRetry = resp.status == UnauthorisedStatus.RETRY;
logDebugMessage('SuperTokens.attemptRefreshingSession: shouldRetry: ${shouldRetry}');
}
}
if (exception != null) {
Expand All @@ -213,10 +220,13 @@ class SuperTokens {
Map<String, dynamic> userPayload = frontToken['up'] as Map<String, dynamic>;

if (accessTokenExpiry < DateTime.now().millisecondsSinceEpoch) {
logDebugMessage('SuperTokens.getAccessTokenPayloadSecurely: access token has expired, trying to refresh');
bool retry = await SuperTokens.attemptRefreshingSession();

if (retry)
if (retry) {
logDebugMessage('SuperTokens.getAccessTokenPayloadSecurely: Retry was successful, extracting payload');
return getAccessTokenPayloadSecurely();
}
else
throw SuperTokensException("Could not refresh session");
}
Expand Down
Loading

0 comments on commit 2686977

Please sign in to comment.