Skip to content

Commit

Permalink
Refresh authToken when it expires
Browse files Browse the repository at this point in the history
Access tokens have lifetimes that might end before the user wants to end
their authenticated session. Hence, we need to refresh the user access token
after an expiry detection.

Resolves: #175

Signed-off-by: fenn-cs <[email protected]>
  • Loading branch information
nfebe committed Aug 6, 2023
1 parent eb4fb69 commit f2cc872
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ PERMANENT_API_BASE_PATH=${LOCAL_TEMPORARY_AUTH_TOKEN}
# See https://fusionauth.io/docs/v1/tech/apis/api-keys
FUSION_AUTH_HOST=${FUSION_AUTH_HOST}
FUSION_AUTH_KEY=${FUSION_AUTH_KEY}
FUSION_AUTH_APP_ID=${FUSION_AUTH_APP_ID}
35 changes: 35 additions & 0 deletions src/classes/AuthenticationSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,16 @@ enum FusionAuthStatusCode {
export class AuthenticationSession {
public authToken = '';

public refreshToken = '';

private authTokenExpiresAt = 0;

public readonly authContext;

private readonly fusionAuthClient;

private readonly fusionAuthAppId = process.env.FUSION_AUTH_APP_ID ?? '';

private twoFactorId = '';

private twoFactorMethods: TwoFactorMethod[] = [];
Expand All @@ -32,6 +38,32 @@ export class AuthenticationSession {
this.promptForPassword();
}

public obtainNewAuthTokenUsingRefreshToken(): void {
this.fusionAuthClient.exchangeRefreshTokenForAccessToken(this.refreshToken, '', '', '', '')
.then((clientResponse) => {
this.authToken = clientResponse.response.access_token ?? '';
})
.catch((clientResponse: unknown) => {
const message = isPartialClientResponse(clientResponse)
? clientResponse.exception.message
: '';
logger.warn(`Error obtaining refresh token : ${message}`);
this.authContext.reject();
});
}

public tokenExpired(): boolean {
const expirationDate = new Date(this.authTokenExpiresAt);
return expirationDate <= new Date();
}

public tokenWouldExpireSoon(xMinutes = 5): boolean {
const expirationDate = new Date(this.authTokenExpiresAt);
const currentTime = new Date();
const timeDifferenceMinutes = (expirationDate.getTime() - currentTime.getTime()) / (1000 * 60);
return timeDifferenceMinutes <= xMinutes;
}

private promptForPassword(): void {
this.authContext.prompt(
{
Expand All @@ -46,6 +78,7 @@ export class AuthenticationSession {

private processPasswordResponse([password]: string[]): void {
this.fusionAuthClient.login({
applicationId: this.fusionAuthAppId,
loginId: this.authContext.username,
password,
}).then((clientResponse) => {
Expand All @@ -57,6 +90,8 @@ export class AuthenticationSession {
username: this.authContext.username,
});
this.authToken = clientResponse.response.token;
this.authTokenExpiresAt = clientResponse.response.tokenExpirationInstant ?? 0;
this.refreshToken = clientResponse.response.refreshToken ?? '';
this.authContext.accept();
return;
}
Expand Down
3 changes: 3 additions & 0 deletions src/classes/SftpSessionHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,9 @@ export class SftpSessionHandler {
}

private getCurrentPermanentFileSystem(): PermanentFileSystem {
if (this.authenticationSession.tokenExpired() || this.authenticationSession.tokenWouldExpireSoon()) {
this.authenticationSession.obtainNewAuthTokenUsingRefreshToken();
}
return this.permanentFileSystemManager
.getCurrentPermanentFileSystemForUser(
this.authenticationSession.authContext.username,
Expand Down

0 comments on commit f2cc872

Please sign in to comment.