Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions packages/web-core/src/services/SessionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
AuthState,
base64decode,
CorbadoError,
NonRecoverableError,
PasskeyAlreadyExistsError,
type PasskeyDeleteError,
PasskeysNotSupported,
Expand Down Expand Up @@ -100,17 +101,18 @@ export class SessionService {
this.#sessionConfig = sessionConfig.val;
this.#refreshToken = SessionService.#getRefreshToken();
this.#sessionToken = SessionService.#getSessionToken();
this.#setApisV2(this.#refreshToken);

// if the session is valid, we emit it
if (this.#sessionToken && this.#sessionToken.isValidForXMoreSeconds(0)) {
log.debug('emit session-token', this.#sessionToken);
this.#onSessionTokenChange(this.#sessionToken);
} else {
await this.#handleRefreshRequest();
// the session-token cookie may have expired while a valid refresh session still exists
// (HTTP-only cookie) => attempt one recovery refresh, the server decides
await this.#refresh();
}

this.#setApisV2(this.#refreshToken);

// init scheduled session refresh
this.#refreshIntervalId = setInterval(() => {
void this.#handleRefreshRequest();
Expand Down Expand Up @@ -255,7 +257,8 @@ export class SessionService {
const sessionTokenModel = new SessionToken(sessionToken);

this.#setSessionToken(sessionTokenModel);
this.#setApisV2(refreshToken ?? '');
// a refresh response carries no new refresh-token => keep the stored one (payload mode has no cookie fallback)
this.#setApisV2(refreshToken ?? this.#refreshToken ?? '');

this.#onSessionTokenChange(sessionTokenModel);
this.#setRefreshToken(refreshToken);
Expand Down Expand Up @@ -456,9 +459,14 @@ export class SessionService {

this.setSession(response.data.sessionToken, undefined);
} catch (e) {
// if it's a network error, we should do a retry
// for all other errors, we should log out the user
log.warn(e);

// transient network failure (e.g. wake from sleep before the network is back up):
// keep the session, the scheduled refresh retries => log out only on real backend rejections
if (!navigator.onLine || (e instanceof NonRecoverableError && e.message.includes('no_data_in_response'))) {
return;
}

await this.logout();
}
}
Expand Down
Loading