Skip to content

Commit

Permalink
Fixes the refresh token race condition (#33)
Browse files Browse the repository at this point in the history
Co-authored-by: cetipoo
  • Loading branch information
segfaultdoc authored Jul 2, 2024
1 parent 77c9d8f commit 54beda1
Showing 1 changed file with 33 additions and 21 deletions.
54 changes: 33 additions & 21 deletions src/sdk/block-engine/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export class AuthProvider {
private readonly authKeypair: Keypair;
private accessToken: Jwt | undefined;
private refreshToken: Jwt | undefined;
private refreshing: Promise<void> | null = null;

constructor(client: AuthServiceClient, authKeypair: Keypair) {
this.client = client;
Expand Down Expand Up @@ -89,34 +90,45 @@ export class AuthProvider {
return;
}

this.refreshAccessToken(callback);
if (!this.refreshing) {
this.refreshing = this.refreshAccessToken().finally(() => {
this.refreshing = null;
});
}

this.refreshing.then(() => {
if (this.accessToken) {
callback(this.accessToken);
}
});
}

// Refresh access token and inject into callback.
private refreshAccessToken(callback: (accessToken: Jwt) => void) {
this.client.refreshAccessToken(
{
refreshToken: this.refreshToken?.token,
} as RefreshAccessTokenRequest,
async (e: ServiceError | null, resp: RefreshAccessTokenResponse) => {
if (e) {
throw e;
}
// Refresh access token.
private async refreshAccessToken() {
return new Promise<void>((resolve, reject) => {
this.client.refreshAccessToken(
{
refreshToken: this.refreshToken?.token,
} as RefreshAccessTokenRequest,
async (e: ServiceError | null, resp: RefreshAccessTokenResponse) => {
if (e) {
return reject(e);
}

if (!AuthProvider.isValidToken(resp.accessToken)) {
throw `received invalid access token ${resp.accessToken}`;
}
callback(
new Jwt(
if (!AuthProvider.isValidToken(resp.accessToken)) {
return reject(`received invalid access token ${resp.accessToken}`);
}
this.accessToken = new Jwt(
resp.accessToken?.value || '',
unixTimestampFromDate(resp.accessToken?.expiresAtUtc || new Date())
)
);
}
);
);
resolve();
}
);
});
}

// Creates an AuthService object, and asynchronously performs full authentication flow.
// Creates an AuthProvider object, and asynchronously performs full authentication flow.
public static async create(
client: AuthServiceClient,
authKeypair: Keypair
Expand Down

0 comments on commit 54beda1

Please sign in to comment.