@yash101/schwab-api-client
Version:
A TypeScript client library for interacting with the Charles Schwab Brokerage APIs.
165 lines • 5.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutoRefreshAuthTokens = exports.AuthTokens = void 0;
const auth_1 = require("./auth");
const idtoken_1 = require("./idtoken");
/**
* Represents a set of authentication tokens, including access and refresh tokens,
* along with their expiration times. Provides methods to retrieve, set, and check
* the expiration status of these tokens.
*/
class AuthTokens {
accessToken = '';
refreshToken = '';
scope = '';
idToken;
atExpiresAt;
rtExpiresAt;
getAccessToken() {
return this.accessToken;
}
getRefreshToken() {
return this.refreshToken;
}
getAccessTokenExpiresAt() {
return this.atExpiresAt || new Date();
}
getRefreshTokenExpiresAt() {
return this.rtExpiresAt || new Date();
}
getUserId() {
return this.idToken;
}
getScope() {
return this.scope;
}
isAccessTokenExpired() {
return (!this.atExpiresAt) || this.atExpiresAt <= new Date();
}
isRefreshTokenExpired() {
return (!this.rtExpiresAt) || this.rtExpiresAt <= new Date();
}
setAccessToken(token) {
this.accessToken = token;
}
setRefreshToken(token) {
this.refreshToken = token;
}
setAccessTokenExpiresAt(expiresAt) {
this.atExpiresAt = expiresAt;
}
setRefreshTokenExpiresAt(expiresAt) {
this.rtExpiresAt = expiresAt;
}
setIdToken(token) {
this.idToken = token;
}
setScope(scope) {
this.scope = scope;
}
getAuthHeader() {
return `Bearer ${this.accessToken}`;
}
}
exports.AuthTokens = AuthTokens;
/**
* Represents a set of authentication tokens with automatic refresh capabilities.
* Inherits from AuthTokens and adds functionality to refresh the access token
* using the refresh token at regular intervals.
*/
class AutoRefreshAuthTokens extends AuthTokens {
refreshInterval;
appConfig;
refreshIntervalTimer;
onRefreshTokenChanged = () => { };
constructor(appConfig, refreshToken, accessToken, refreshInterval = 1000 * 60 * 20) {
super();
this.refreshToken = refreshToken;
this.accessToken = accessToken || '';
this.appConfig = appConfig;
this.refreshIntervalTimer = refreshInterval;
}
// Method to refresh the access token using the refresh token
doRefreshAccessToken(retries) {
if (retries && retries > 5) {
console.error('Failed to refresh access token after 5 retries. No longer attempting to refresh.');
clearInterval(this.refreshInterval);
return;
}
// Perform API call to refresh the access token
(0, auth_1.getNewAccessToken)({
authTokens: this,
appConfig: this.appConfig,
})
.then((response) => {
this.setAccessToken(response.accessToken);
this.setAccessTokenExpiresAt(response.accessTokenExpiresAt);
this.setIdToken((0, idtoken_1.decodeIdToken)(Buffer.from(response.id_token, 'base64')));
if (response.refreshToken && response.refreshToken !== this.refreshToken) {
this.setRefreshToken(response.refreshToken);
this.setRefreshTokenExpiresAt(new Date(Date.now() + 1000 * 60 * 60 * 24 * 7));
this.onRefreshTokenChanged(this);
}
})
.catch(e => {
console.error(`Failed to refresh access token: ${e.message}`);
// Try again
setTimeout(() => {
if (!retries) {
retries = 0;
}
this.doRefreshAccessToken(retries + 1);
}, 60 * 1000);
});
}
// Method to start the automatic refresh interval
start() {
if (this.refreshInterval) {
this.stop();
}
// every 20 minutes
this.refreshInterval = setInterval(() => {
this.doRefreshAccessToken();
}, this.refreshIntervalTimer);
return this;
}
stop() {
clearInterval(this.refreshInterval);
this.refreshInterval = undefined;
return this;
}
refreshImmediately() {
this.doRefreshAccessToken();
return this;
}
setRefreshInterval(interval) {
this.refreshIntervalTimer = interval;
if (this.refreshInterval) {
this.stop();
this.start();
}
return this;
}
setOnRefreshTokenChanged(callback) {
this.onRefreshTokenChanged = callback;
return this;
}
static async fromAuthCode(code, appConfig, apiUri) {
if (!apiUri) {
apiUri = 'https://api.schwabapi.com/v1/oauth/token';
}
const initialAuth = await (0, auth_1.getInitialTokensFromAuthorizationCode)({
authCode: code,
appConfig,
apiUri,
});
const tokens = new AutoRefreshAuthTokens(appConfig, initialAuth.refreshToken, initialAuth.accessToken);
tokens.setAccessTokenExpiresAt(initialAuth.accessTokenExpiresAt);
tokens.setRefreshTokenExpiresAt(initialAuth.refreshTokenExpiresAt);
tokens.setIdToken((0, idtoken_1.decodeIdToken)(Buffer.from(initialAuth.id_token, 'base64')));
tokens.setScope(initialAuth.scope);
return tokens;
}
}
exports.AutoRefreshAuthTokens = AutoRefreshAuthTokens;
//# sourceMappingURL=tokens.js.map