Skip to content

Commit

Permalink
enables typescript strict mode and fixes type errors
Browse files Browse the repository at this point in the history
OKTA-459135
<<<Jenkins Check-In of Tested SHA: d1acf90 for eng_productivity_ci_bot_okta@okta.com>>>
Artifact: okta-auth-js
Files changed count: 114
PR Link: "#1057"
  • Loading branch information
aarongranick-okta authored and eng-prod-CI-bot-okta committed Jan 14, 2022
1 parent d209c7c commit da468b4
Show file tree
Hide file tree
Showing 114 changed files with 903 additions and 657 deletions.
2 changes: 2 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"--collectCoverage=false",
"--testTimeout=120000",
"--config=jest.browser.js",
"--testTimeout=120000",
"${relativeFile}"
],
"console": "integratedTerminal",
Expand All @@ -47,6 +48,7 @@
"--collectCoverage=false",
"--testTimeout=120000",
"--config=jest.server.js",
"--testTimeout=120000",
"${relativeFile}"
],
"console": "integratedTerminal",
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
- [#1050](https://github.com/okta/okta-auth-js/pull/1050) Removes `userAgent` field from oktaAuth instance
- [#1014](https://github.com/okta/okta-auth-js/pull/1014) Shared transaction storage is automatically cleared on success and error states. Storage is not cleared for "terminal" state which is neither success nor error.
- [#1051](https://github.com/okta/okta-auth-js/pull/1051) Removes `useMultipleCookies` from CookieStorage options
- [#1059](https://github.com/okta/okta-auth-js/pull/1059)
- [#1059](https://github.com/okta/okta-auth-js/pull/1059)
- Removes signOut option `clearTokensAfterRedirect`
- Adds signOut option `clearTokensBeforeRedirect` (default: `false`) to remove local tokens before logout redirect happen
- [#1057](https://github.com/okta/okta-auth-js/pull/1057) Strict checks are now enabled in the Typescript compiler options. Some type signatures have been changed to match current behavior.

### Features

Expand Down
6 changes: 3 additions & 3 deletions lib/AuthStateManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const EVENT_AUTH_STATE_CHANGE = 'authStateChange';
const MAX_PROMISE_CANCEL_TIMES = 10;

// only compare first level of authState
const isSameAuthState = (prevState: AuthState, state: AuthState) => {
const isSameAuthState = (prevState: AuthState | null, state: AuthState) => {
// initial state is null
if (!prevState) {
return false;
Expand All @@ -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
106 changes: 63 additions & 43 deletions lib/OktaAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ import {
IdxAPI,
SignoutRedirectUrlOptions,
HttpAPI,
FlowIdentifier
FlowIdentifier,
GetWithRedirectAPI,
ParseFromUrlInterface,
GetWithRedirectFunction,
} from './types';
import {
transactionStatus,
Expand Down Expand Up @@ -136,7 +139,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 @@ -148,18 +151,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
const boundStartTransaction = startTransaction.bind(null, this);
Expand Down Expand Up @@ -294,11 +313,11 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
getTransactionMeta: getTransactionMeta.bind(null, this),
saveTransactionMeta: saveTransactionMeta.bind(null, this),
clearTransactionMeta: clearTransactionMeta.bind(null, this),
isTransactionMetaValid: isTransactionMetaValid.bind(null, this),
isTransactionMetaValid,
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 @@ -387,7 +406,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 @@ -403,7 +422,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 @@ -417,7 +436,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 @@ -543,7 +562,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 @@ -556,7 +575,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 @@ -612,7 +631,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 @@ -625,7 +644,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 @@ -637,7 +656,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 @@ -672,7 +691,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 @@ -702,7 +721,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 @@ -63,10 +63,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

0 comments on commit da468b4

Please sign in to comment.