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 d76e362
Show file tree
Hide file tree
Showing 3 changed files with 42 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 = '';

public readonly authContext;

private authTokenExpiresAt = 0;

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(minutes = 5): boolean {
const expirationDate = new Date(this.authTokenExpiresAt);
const currentTime = new Date();
const timeDifferenceMinutes = (expirationDate.getTime() - currentTime.getTime()) / (1000 * 60);
return timeDifferenceMinutes <= minutes;
}

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
6 changes: 6 additions & 0 deletions src/classes/SftpSessionHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,12 @@ 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 d76e362

Please sign in to comment.