Skip to content

Commit

Permalink
enables typescript strict mode and fixes type errors
Browse files Browse the repository at this point in the history
  • Loading branch information
aarongranick-okta committed Jan 11, 2022
1 parent 4b22450 commit 85db423
Show file tree
Hide file tree
Showing 111 changed files with 668 additions and 487 deletions.
2 changes: 2 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"--no-cache",
"--collectCoverage=false",
"--config=jest.browser.js",
"--testTimeout=120000",
"${relativeFile}"
],
"console": "integratedTerminal",
Expand All @@ -45,6 +46,7 @@
"--no-cache",
"--collectCoverage=false",
"--config=jest.server.js",
"--testTimeout=120000",
"${relativeFile}"
],
"console": "integratedTerminal",
Expand Down
7 changes: 4 additions & 3 deletions lib/AuthStateManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export class AuthStateManager {
_authState: AuthState | null;
_prevAuthState: AuthState | null;
_logOptions: AuthStateLogOptions;
_lastEventTimestamp: number;

constructor(sdk: OktaAuth) {
if (!sdk.emitter) {
Expand All @@ -59,7 +58,8 @@ export class AuthStateManager {
this._pending = { ...DEFAULT_PENDING };
this._authState = INITIAL_AUTH_STATE;
this._logOptions = {};

this._prevAuthState = null;

// Listen on tokenManager events to start updateState process
// "added" event is emitted in both add and renew process
// Only listen on "added" event to update auth state
Expand Down Expand Up @@ -100,7 +100,8 @@ export class AuthStateManager {
};

const emitAuthStateChange = (authState) => {
if (isSameAuthState(this._authState, authState)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (isSameAuthState(this._authState!, authState)) {
devMode && log('unchanged');
return;
}
Expand Down
102 changes: 61 additions & 41 deletions lib/OktaAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ import {
SignoutRedirectUrlOptions,
HttpAPI,
FlowIdentifier,
GetWithRedirectAPI,
ParseFromUrlInterface,
GetWithRedirectFunction,
} from './types';
import {
transactionStatus,
Expand Down Expand Up @@ -133,7 +136,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
session: SessionAPI;
pkce: PkceAPI;
static features: FeaturesAPI;
features: FeaturesAPI;
features!: FeaturesAPI;
token: TokenAPI;
_tokenQueue: PromiseQueue;
emitter: typeof Emitter;
Expand All @@ -145,18 +148,20 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
_pending: { handleLogin: boolean };
constructor(args: OktaAuthOptions) {
const options = this.options = buildOptions(args);
this.storageManager = new StorageManager(options.storageManager, options.cookies, options.storageUtil);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.storageManager = new StorageManager(options.storageManager!, options.cookies!, options.storageUtil!);
this.transactionManager = new TransactionManager(Object.assign({
storageManager: this.storageManager,
}, options.transactionManager));
this._oktaUserAgent = new OktaUserAgent();

this.tx = {
status: transactionStatus.bind(null, this),
resume: resumeTransaction.bind(null, this),
exists: Object.assign(transactionExists.bind(null, this), {
_get: (name) => {
const storage = options.storageUtil.storage;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const storage = options.storageUtil!.storage;
return storage.get(name);
}
}),
Expand Down Expand Up @@ -213,13 +218,43 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
};

this._tokenQueue = new PromiseQueue();
const useQueue = (method) => {
return PromiseQueue.prototype.push.bind(this._tokenQueue, method, null);
};

// eslint-disable-next-line max-len
const getWithRedirectFn = useQueue(getWithRedirect.bind(null, this)) as GetWithRedirectFunction;
const getWithRedirectApi: GetWithRedirectAPI = Object.assign(getWithRedirectFn, {
// This is exposed so we can set window.location in our tests
_setLocation: function(url) {
window.location = url;
}
});
// eslint-disable-next-line max-len
const parseFromUrlFn = useQueue(parseFromUrl.bind(null, this)) as ParseFromUrlInterface;
const parseFromUrlApi: ParseFromUrlInterface = Object.assign(parseFromUrlFn, {
// This is exposed so we can mock getting window.history in our tests
_getHistory: function() {
return window.history;
},

// This is exposed so we can mock getting window.location in our tests
_getLocation: function() {
return window.location;
},

// This is exposed so we can mock getting window.document in our tests
_getDocument: function() {
return window.document;
}
});
this.token = {
prepareTokenParams: prepareTokenParams.bind(null, this),
exchangeCodeForTokens: exchangeCodeForTokens.bind(null, this),
getWithoutPrompt: getWithoutPrompt.bind(null, this),
getWithPopup: getWithPopup.bind(null, this),
getWithRedirect: getWithRedirect.bind(null, this),
parseFromUrl: parseFromUrl.bind(null, this),
getWithRedirect: getWithRedirectApi,
parseFromUrl: parseFromUrlApi,
decode: decodeToken,
revoke: revokeToken.bind(null, this),
renew: renewToken.bind(null, this),
Expand All @@ -230,37 +265,21 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
isLoginRedirect: isLoginRedirect.bind(null, this)
};
// Wrap all async token API methods using MethodQueue to avoid issues with concurrency
const syncMethods = ['decode', 'isLoginRedirect'];
const syncMethods = [
// sync methods
'decode',
'isLoginRedirect',
// already bound
'getWithRedirect',
'parseFromUrl'
];
Object.keys(this.token).forEach(key => {
if (syncMethods.indexOf(key) >= 0) { // sync methods should not be wrapped
return;
}
var method = this.token[key];
this.token[key] = PromiseQueue.prototype.push.bind(this._tokenQueue, method, null);
});

Object.assign(this.token.getWithRedirect, {
// This is exposed so we can set window.location in our tests
_setLocation: function(url) {
window.location = url;
}
});
Object.assign(this.token.parseFromUrl, {
// This is exposed so we can mock getting window.history in our tests
_getHistory: function() {
return window.history;
},

// This is exposed so we can mock getting window.location in our tests
_getLocation: function() {
return window.location;
},

// This is exposed so we can mock getting window.document in our tests
_getDocument: function() {
return window.document;
}
});

// IDX
this.idx = {
Expand All @@ -277,7 +296,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
setFlow: (flow: FlowIdentifier) => {
this.options.flow = flow;
},
getFlow: (): FlowIdentifier => {
getFlow: (): FlowIdentifier | undefined => {
return this.options.flow;
},
canProceed: canProceed.bind(null, this),
Expand Down Expand Up @@ -386,7 +405,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
}

// Ends the current Okta SSO session without redirecting to Okta.
closeSession(): Promise<object> {
closeSession(): Promise<unknown> {
return this.session.close() // DELETE /api/v1/sessions/me
.then(async () => {
// Clear all local tokens
Expand All @@ -402,7 +421,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
}

// Revokes the access token for the application session
async revokeAccessToken(accessToken?: AccessToken): Promise<object> {
async revokeAccessToken(accessToken?: AccessToken): Promise<unknown> {
if (!accessToken) {
accessToken = (await this.tokenManager.getTokens()).accessToken as AccessToken;
const accessTokenKey = this.tokenManager.getStorageKeyByType('accessToken');
Expand All @@ -416,7 +435,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
}

// Revokes the refresh token for the application session
async revokeRefreshToken(refreshToken?: RefreshToken): Promise<object> {
async revokeRefreshToken(refreshToken?: RefreshToken): Promise<unknown> {
if (!refreshToken) {
refreshToken = (await this.tokenManager.getTokens()).refreshToken as RefreshToken;
const refreshTokenKey = this.tokenManager.getStorageKeyByType('refreshToken');
Expand Down Expand Up @@ -542,7 +561,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
const { autoRenew, autoRemove } = this.tokenManager.getOptions();

if (accessToken && this.tokenManager.hasExpired(accessToken)) {
accessToken = null;
accessToken = undefined;
if (autoRenew) {
try {
accessToken = await this.tokenManager.renew('accessToken') as AccessToken;
Expand All @@ -555,7 +574,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
}

if (idToken && this.tokenManager.hasExpired(idToken)) {
idToken = null;
idToken = undefined;
if (autoRenew) {
try {
idToken = await this.tokenManager.renew('idToken') as IDToken;
Expand Down Expand Up @@ -611,7 +630,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
}
}

getOriginalUri(state?: string): string {
getOriginalUri(state?: string): string | undefined {
// Prefer shared storage (if state is available)
state = state || this.options.state;
if (state) {
Expand All @@ -624,7 +643,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {

// Try to load from session storage
const storage = browserStorage.getSessionStorage();
return storage ? storage.getItem(REFERRER_PATH_STORAGE_KEY) : undefined;
return storage ? storage.getItem(REFERRER_PATH_STORAGE_KEY) || undefined : undefined;
}

removeOriginalUri(state?: string): void {
Expand All @@ -636,7 +655,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
state = state || this.options.state;
if (state) {
const sharedStorage = this.storageManager.getOriginalUriStorage();
sharedStorage.removeItem(state);
sharedStorage.removeItem && sharedStorage.removeItem(state);
}
}

Expand Down Expand Up @@ -671,7 +690,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
const { restoreOriginalUri } = this.options;
if (restoreOriginalUri) {
await restoreOriginalUri(this, originalUri);
} else {
} else if (originalUri) {
window.location.replace(originalUri);
}
}
Expand Down Expand Up @@ -701,7 +720,8 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {

getIssuerOrigin(): string {
// Infer the URL from the issuer URL, omitting the /oauth2/{authServerId}
return this.options.issuer.split('/oauth2/')[0];
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.options.issuer!.split('/oauth2/')[0];
}

// { username, (relayState) }
Expand Down
2 changes: 1 addition & 1 deletion lib/OktaUserAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
*/

/* global SDK_VERSION */
import { isBrowser } from './features';

import { isBrowser } from './features';
export class OktaUserAgent {
private environments: string[];

Expand Down
7 changes: 4 additions & 3 deletions lib/PromiseQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ class PromiseQueue {
return;
}
this.running = true;
var queueItem = this.queue.shift();
var res = queueItem.method.apply(queueItem.thisObject, queueItem.args);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var queueItem = this.queue.shift()!;
var res = queueItem.method.apply(queueItem.thisObject, queueItem.args as never) as unknown;
if (isPromise(res)) {
res.then(queueItem.resolve, queueItem.reject).finally(() => {
(res as Promise<unknown>).then(queueItem.resolve, queueItem.reject).finally(() => {
this.running = false;
this.run();
});
Expand Down
8 changes: 5 additions & 3 deletions lib/StorageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default class StorageManager {
}

// generic method to get any available storage provider
// eslint-disable-next-line complexity
getStorage(options: StorageOptions): SimpleStorage {
options = Object.assign({}, this.cookieOptions, options); // set defaults

Expand All @@ -80,12 +81,13 @@ export default class StorageManager {
const idx = storageTypes.indexOf(storageType);
if (idx >= 0) {
storageTypes = storageTypes.slice(idx);
storageType = null;
storageType = undefined;
}
}

if (!storageType) {
storageType = this.storageUtil.findStorageType(storageTypes);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
storageType = this.storageUtil.findStorageType(storageTypes!);
}
return this.storageUtil.getStorageByType(storageType, options);
}
Expand Down Expand Up @@ -118,7 +120,7 @@ export default class StorageManager {
// intermediate idxResponse
// store for network traffic optimazation purpose
// TODO: revisit in auth-js 6.0 epic JIRA: OKTA-399791
getIdxResponseStorage(options?: StorageOptions): IdxResponseStorage {
getIdxResponseStorage(options?: StorageOptions): IdxResponseStorage | null {
let storage;
if (isBrowser()) {
// on browser side only use memory storage
Expand Down
14 changes: 8 additions & 6 deletions lib/TokenManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const EVENT_ERROR = 'error';

interface TokenManagerState {
expireTimeouts: Record<string, unknown>;
renewPromise: Promise<Token>;
renewPromise: Promise<Token | undefined> | null;
}
function defaultState(): TokenManagerState {
return {
Expand All @@ -70,7 +70,7 @@ export class TokenManager implements TokenManagerInterface {
private storage: StorageProvider;
private state: TokenManagerState;
private options: TokenManagerOptions;
private service: TokenService;
private service: TokenService | null;

on: (event: string, handler: TokenManagerErrorEventHandler | TokenManagerEventHandler, context?: object) => void;
off: (event: string, handler?: TokenManagerErrorEventHandler | TokenManagerEventHandler) => void;
Expand All @@ -81,7 +81,8 @@ export class TokenManager implements TokenManagerInterface {
if (!this.emitter) {
throw new AuthSdkError('Emitter should be initialized before TokenManager');
}

this.service = null;

options = Object.assign({}, DEFAULT_OPTIONS, removeNils(options));
if (isIE11OrLess()) {
options._storageEventDelay = options._storageEventDelay || 1000;
Expand Down Expand Up @@ -133,7 +134,8 @@ export class TokenManager implements TokenManagerInterface {
}

getExpireTime(token) {
var expireTime = token.expiresAt - this.options.expireEarlySeconds;
const expireEarlySeconds = this.options.expireEarlySeconds || 0;
var expireTime = token.expiresAt - expireEarlySeconds;
return expireTime;
}

Expand Down Expand Up @@ -385,15 +387,15 @@ export class TokenManager implements TokenManagerInterface {

// TODO: this methods is redundant and can be removed in the next major version OKTA-407224
async renewToken(token) {
return this.sdk.token.renew(token);
return this.sdk.token?.renew(token);
}
// TODO: this methods is redundant and can be removed in the next major version OKTA-407224
validateToken(token: Token) {
return validateToken(token);
}

// TODO: renew method should take no param, change in the next major version OKTA-407224
renew(key): Promise<Token> {
renew(key): Promise<Token | undefined> {
// Multiple callers may receive the same promise. They will all resolve or reject from the same request.
if (this.state.renewPromise) {
return this.state.renewPromise;
Expand Down
Loading

0 comments on commit 85db423

Please sign in to comment.