Skip to content

Commit

Permalink
Merge branch '6.4' into ag-backport-6-4-3
Browse files Browse the repository at this point in the history
  • Loading branch information
aarongranick-okta committed Apr 18, 2022
2 parents 420c254 + da8612f commit 5151e31
Show file tree
Hide file tree
Showing 50 changed files with 1,013 additions and 470 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 6.4.3

### Fixes

- [#1182](https://github.com/okta/okta-auth-js/pull/1182) Fixes security question verification to accept `credentials.answer`
- [#1184](https://github.com/okta/okta-auth-js/pull/1184) Fixes type declarations: `ApiError`, `responseType`, `responseMode`
- [#1185](https://github.com/okta/okta-auth-js/pull/1185) Fixes "cancel" and "skip" action called after receiving a terminal or error response

## 6.4.2

### Fixes
Expand Down
3 changes: 2 additions & 1 deletion lib/OktaAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {
GetWithRedirectFunction,
RequestOptions,
IsAuthenticatedOptions,
OAuthResponseType,
} from './types';
import {
transactionStatus,
Expand Down Expand Up @@ -729,7 +730,7 @@ class OktaAuth implements OktaAuthInterface, SigninAPI, SignoutAPI {
return !!this.options.pkce;
}

hasResponseType(responseType: string): boolean {
hasResponseType(responseType: OAuthResponseType): boolean {
let hasResponseType = false;
if (Array.isArray(this.options.responseType) && this.options.responseType.length) {
hasResponseType = this.options.responseType.indexOf(responseType) >= 0;
Expand Down
33 changes: 24 additions & 9 deletions lib/TransactionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {
TransactionMetaOptions,
TransactionManagerOptions,
CookieStorage,
SavedIdxResponse
SavedIdxResponse,
IntrospectOptions
} from './types';
import { isRawIdxResponse } from './idx/types/idx-js';
import { warn } from './util';
Expand All @@ -36,7 +37,8 @@ import {
} from './util/sharedStorage';

export interface ClearTransactionMetaOptions extends TransactionMetaOptions {
clearSharedStorage?: boolean;
clearSharedStorage?: boolean; // true by default
clearIdxResponse?: boolean; // true by default
}
export default class TransactionManager {
options: TransactionManagerOptions;
Expand Down Expand Up @@ -68,17 +70,18 @@ export default class TransactionManager {
// Clear primary storage (by default, sessionStorage on browser)
transactionStorage.clearStorage();

// clear IDX response storage
this.clearIdxResponse();

// Usually we want to also clear shared storage unless another tab may need it to continue/complete a flow
if (this.enableSharedStorage && options.clearSharedStorage !== false) {
const state = options.state || meta?.state;
if (state) {
clearTransactionFromSharedStorage(this.storageManager, state);
}
}


if (options.clearIdxResponse !== false) {
this.clearIdxResponse();
}

if (!this.legacyWidgetSupport) {
return;
}
Expand Down Expand Up @@ -307,18 +310,19 @@ export default class TransactionManager {
// throw new AuthSdkError('Unable to parse the ' + REDIRECT_OAUTH_PARAMS_NAME + ' value from storage');
}

saveIdxResponse({ rawIdxResponse, requestDidSucceed }: SavedIdxResponse): void {
saveIdxResponse(data: SavedIdxResponse): void {
if (!this.saveLastResponse) {
return;
}
const storage = this.storageManager.getIdxResponseStorage();
if (!storage) {
return;
}
storage.setStorage({ rawIdxResponse, requestDidSucceed });
storage.setStorage(data);
}

loadIdxResponse(): SavedIdxResponse | null {
// eslint-disable-next-line complexity
loadIdxResponse(options?: IntrospectOptions): SavedIdxResponse | null {
if (!this.saveLastResponse) {
return null;
}
Expand All @@ -330,6 +334,17 @@ export default class TransactionManager {
if (!storedValue || !isRawIdxResponse(storedValue.rawIdxResponse)) {
return null;
}

if (options) {
const { stateHandle, interactionHandle } = options;
if (stateHandle && storedValue.stateHandle !== stateHandle) {
return null;
}
if (interactionHandle && storedValue.interactionHandle !== interactionHandle) {
return null;
}
}

return storedValue;
}

Expand Down
4 changes: 2 additions & 2 deletions lib/errors/AuthApiError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
*/

import CustomError from './CustomError';
import { APIError, HttpResponse } from '../types';
import { APIError, FieldError, HttpResponse } from '../types';

export default class AuthApiError extends CustomError implements APIError {
errorSummary: string;
errorCode?: string;
errorLink?: string;
errorId?: string;
errorCauses?: string[];
errorCauses?: Array<FieldError>;
xhr?: HttpResponse;

constructor(err: APIError, xhr?: HttpResponse) {
Expand Down
4 changes: 2 additions & 2 deletions lib/errors/AuthSdkError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
*/

import CustomError from './CustomError';
import { APIError } from '../types';
import { APIError, FieldError } from '../types';

export default class AuthSdkError extends CustomError implements APIError {
errorSummary: string;
errorCode: string;
errorLink: string;
errorId: string;
errorCauses: string[];
errorCauses: Array<FieldError>;
xhr?: XMLHttpRequest;

constructor(msg: string, xhr?: XMLHttpRequest) {
Expand Down
22 changes: 2 additions & 20 deletions lib/idx/authenticate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,11 @@

import {
OktaAuthInterface,
IdxOptions,
IdxTransaction,
AuthenticatorKey
AuthenticatorKey,
AuthenticationOptions
} from '../types';
import { run } from './run';
import {
IdentifyValues,
SelectAuthenticatorAuthenticateValues,
ChallengeAuthenticatorValues,
ReEnrollAuthenticatorValues,
AuthenticatorEnrollmentDataValues,
SelectAuthenticatorEnrollValues,
EnrollAuthenticatorValues,
} from './remediators';

export type AuthenticationOptions = IdxOptions
& IdentifyValues
& SelectAuthenticatorAuthenticateValues
& SelectAuthenticatorEnrollValues
& ChallengeAuthenticatorValues
& ReEnrollAuthenticatorValues
& AuthenticatorEnrollmentDataValues
& EnrollAuthenticatorValues;

export async function authenticate(
authClient: OktaAuthInterface, options: AuthenticationOptions = {}
Expand Down
2 changes: 1 addition & 1 deletion lib/idx/authenticator/SecurityQuestionEnrollment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class SecurityQuestionEnrollment extends Authenticator<SecurityQuestionEn

mapCredentials(values: SecurityQuestionEnrollValues): Credentials | undefined {
const { questionKey, question, answer } = values;
if (!questionKey && !question && !answer) {
if (!answer || (!questionKey && !question)) {
return;
}
return {
Expand Down
8 changes: 7 additions & 1 deletion lib/idx/authenticator/SecurityQuestionVerification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ import { Authenticator, Credentials } from './Authenticator';

export interface SecurityQuestionVerificationValues {
answer?: string;
credentials?: Credentials;
}

export class SecurityQuestionVerification extends Authenticator<SecurityQuestionVerificationValues> {
canVerify(values: SecurityQuestionVerificationValues) {
return !!values.answer;
const { credentials } = values;
if (credentials && credentials.answer) {
return true;
}
const { answer } = values;
return !!answer;
}

mapCredentials(values: SecurityQuestionVerificationValues): Credentials | undefined {
Expand Down
4 changes: 1 addition & 3 deletions lib/idx/cancel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@
* See the License for the specific language governing permissions and limitations under the License.
*/

import { OktaAuthInterface, IdxOptions, IdxTransactionMeta } from '../types';
import { OktaAuthInterface, CancelOptions, IdxTransactionMeta } from '../types';
import { run } from './run';
import { getFlowSpecification } from './flow';

export type CancelOptions = IdxOptions;

export async function cancel (authClient: OktaAuthInterface, options?: CancelOptions) {
const meta = authClient.transactionManager.load() as IdxTransactionMeta;
const flowSpec = getFlowSpecification(authClient, meta.flow);
Expand Down
10 changes: 4 additions & 6 deletions lib/idx/idxState/v1/generateIdxAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@
*/

/* eslint-disable max-len, complexity */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import { httpRequest } from '../../../http';
import { OktaAuthInterface } from '../../../types'; // auth-js/types
import { IdxActionParams } from '../../types/idx-js';
import { IdxActionFunction, IdxActionParams, IdxResponse, IdxToPersist } from '../../types/idx-js';
import { divideActionParamsByMutability } from './actionParser';
import { makeIdxState } from './makeIdxState';
import AuthApiError from '../../../errors/AuthApiError';
Expand All @@ -24,8 +22,8 @@ const generateDirectFetch = function generateDirectFetch(authClient: OktaAuthInt
actionDefinition,
defaultParamsForAction = {},
immutableParamsForAction = {},
toPersist = {}
}) {
toPersist = {} as IdxToPersist
}): IdxActionFunction {
const target = actionDefinition.href;
return async function(params: IdxActionParams = {}): Promise<IdxResponse> {
const headers = {
Expand Down Expand Up @@ -90,7 +88,7 @@ const generateDirectFetch = function generateDirectFetch(authClient: OktaAuthInt
// };
// };

const generateIdxAction = function generateIdxAction( authClient: OktaAuthInterface, actionDefinition, toPersist ) {
const generateIdxAction = function generateIdxAction( authClient: OktaAuthInterface, actionDefinition, toPersist ): IdxActionFunction {
// TODO: leaving this here to see where the polling is EXPECTED to drop into the code, but removing any accidental trigger of incomplete code
// const generator = actionDefinition.refresh ? generatePollingFetch : generateDirectFetch;
const generator = generateDirectFetch;
Expand Down
20 changes: 2 additions & 18 deletions lib/idx/interact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,13 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
/* eslint complexity:[0,8] */
import { OktaAuthInterface, IdxTransactionMeta } from '../types';
import { OktaAuthInterface, IdxTransactionMeta, InteractOptions, InteractResponse } from '../types';
import { getSavedTransactionMeta, saveTransactionMeta } from './transactionMeta';
import { getOAuthBaseUrl } from '../oidc';
import { createTransactionMeta } from '.';
import { removeNils } from '../util';
import { httpRequest } from '../http';

export interface InteractOptions {
withCredentials?: boolean;
state?: string;
scopes?: string[];
codeChallenge?: string;
codeChallengeMethod?: string;
activationToken?: string;
recoveryToken?: string;
clientSecret?: string;
}

export interface InteractResponse {
state?: string;
interactionHandle: string;
meta: IdxTransactionMeta;
}

/* eslint-disable camelcase */
export interface InteractParams {
Expand Down Expand Up @@ -92,7 +76,7 @@ export async function interact (
const url = `${baseUrl}/v1/interact`;
const params = {
client_id: clientId,
scope: scopes.join(' '),
scope: scopes!.join(' '),
redirect_uri: redirectUri,
code_challenge: codeChallenge,
code_challenge_method: codeChallengeMethod,
Expand Down
11 changes: 2 additions & 9 deletions lib/idx/introspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,13 @@
*/

import { makeIdxState, validateVersionConfig } from './idxState';
import { OktaAuthInterface } from '../types';
import { IntrospectOptions, OktaAuthInterface } from '../types';
import { IdxResponse, isRawIdxResponse } from './types/idx-js';
import { getOAuthDomain } from '../oidc';
import { IDX_API_VERSION } from '../constants';
import { httpRequest } from '../http';
import { isAuthApiError } from '../errors';

export interface IntrospectOptions {
withCredentials?: boolean;
interactionHandle?: string;
stateHandle?: string;
version?: string;
}

export async function introspect (
authClient: OktaAuthInterface,
options: IntrospectOptions = {}
Expand All @@ -34,7 +27,7 @@ export async function introspect (
let requestDidSucceed;

// try load from storage first
const savedIdxResponse = authClient.transactionManager.loadIdxResponse();
const savedIdxResponse = authClient.transactionManager.loadIdxResponse(options);
if (savedIdxResponse) {
rawIdxResponse = savedIdxResponse.rawIdxResponse;
requestDidSucceed = savedIdxResponse.requestDidSucceed;
Expand Down
17 changes: 1 addition & 16 deletions lib/idx/proceed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,12 @@
import {
OktaAuthInterface,
IdxTransaction,
ProceedOptions,
} from '../types';
import { run } from './run';
import { AuthenticationOptions } from './authenticate';
import {
EnrollPollValues as EnrollPollOptions,
SelectEnrollmentChannelValues as SelectEnrollmentChannelOptions
} from './remediators';
import { RegistrationOptions } from './register';
import { PasswordRecoveryOptions } from './recoverPassword';
import { AccountUnlockOptions } from './unlockAccount';
import { getSavedTransactionMeta } from './transactionMeta';
import { AuthSdkError } from '../errors';

export type ProceedOptions = AuthenticationOptions
& RegistrationOptions
& PasswordRecoveryOptions
& AccountUnlockOptions
& EnrollPollOptions
& SelectEnrollmentChannelOptions
& { step?: string };

export function canProceed(authClient: OktaAuthInterface, options: ProceedOptions = {}): boolean {
const meta = getSavedTransactionMeta(authClient, options);
return !!(meta || options.stateHandle);
Expand Down
18 changes: 1 addition & 17 deletions lib/idx/recoverPassword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,13 @@


import { run } from './run';
import {
IdentifyValues,
SelectAuthenticatorAuthenticateValues,
ChallengeAuthenticatorValues,
AuthenticatorVerificationDataValues,
ResetAuthenticatorValues,
ReEnrollAuthenticatorValues,
} from './remediators';
import { getFlowSpecification } from './flow';
import {
OktaAuthInterface,
IdxOptions,
PasswordRecoveryOptions,
IdxTransaction,
} from '../types';

export type PasswordRecoveryOptions = IdxOptions
& IdentifyValues
& SelectAuthenticatorAuthenticateValues
& ChallengeAuthenticatorValues
& ResetAuthenticatorValues
& AuthenticatorVerificationDataValues
& ReEnrollAuthenticatorValues;

export async function recoverPassword(
authClient: OktaAuthInterface, options: PasswordRecoveryOptions = {}
): Promise<IdxTransaction> {
Expand Down
Loading

0 comments on commit 5151e31

Please sign in to comment.