Skip to content

Commit

Permalink
chore: [IOPID-2515] - Add SECURITY_LEVEL_MISMATCH event (#6460)
Browse files Browse the repository at this point in the history
## Short description
This PR adds `SECURITY_LEVEL_MISMATCH` event

## List of changes proposed in this pull request
- Added `SECURITY_LEVEL_MISMATCH` event  

## How to test
The current implementation requires the `CieID` app to perform an `L2`
login; if the `CieID` app is configured to allow only login with the
`CIE` (L3), an `L3` login will be executed.
  • Loading branch information
ChrisMattew authored Nov 28, 2024
1 parent 170b99e commit 99f0f97
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 1 deletion.
7 changes: 7 additions & 0 deletions ts/features/cieLogin/analytics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ export const trackCieIdNoWhitelistUrl = (url: string) => {
buildEventProperties("KO", undefined, { url })
);
};

export const trackCieIdSecurityLevelMismatch = () => {
void mixpanelTrack(
"SECURITY_LEVEL_MISMATCH",
buildEventProperties("TECH", undefined)
);
};
32 changes: 32 additions & 0 deletions ts/features/cieLogin/sagas/trackLevelSecuritySaga.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { select } from "typed-redux-saga/macro";
import * as O from "fp-ts/Option";
import { pipe } from "fp-ts/lib/function";
import { sequenceT } from "fp-ts/lib/Apply";
import { cieIDSelectedSecurityLevelSelector } from "../store/selectors";
import { idpSelector } from "../../../store/reducers/authentication";
import { IdpCIE_ID } from "../../../hooks/useNavigateToLoginMethod";
import { trackCieIdSecurityLevelMismatch } from "../analytics";
import { PublicSession } from "../../../../definitions/session_manager/PublicSession";

export function* shouldTrackLevelSecurityMismatchSaga(
maybeSessionInformation: O.Option<PublicSession>
) {
const selectedSecurityLevel = yield* select(
cieIDSelectedSecurityLevelSelector
);
const idpSelected = yield* select(idpSelector);
const selectedLevelMismatches = pipe(
sequenceT(O.Monad)(maybeSessionInformation, idpSelected),
O.chainNullableK(
([session, idp]) =>
selectedSecurityLevel &&
idp.id === IdpCIE_ID.id &&
!session.spidLevel?.includes(selectedSecurityLevel)
),
O.getOrElse(() => false)
);

if (selectedLevelMismatches) {
trackCieIdSecurityLevelMismatch();
}
}
7 changes: 6 additions & 1 deletion ts/features/cieLogin/store/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ActionType, createStandardAction } from "typesafe-actions";
import { SpidLevel } from "../../utils";

export const cieLoginEnableUat = createStandardAction("CIE_LOGIN_ENABLE_UAT")();

Expand All @@ -13,9 +14,13 @@ export const cieIDFeatureSetEnabled = createStandardAction(
export const cieIDDisableTourGuide = createStandardAction(
"CIE_ID_DISABLE_TOUR_GUIDE"
)();
export const cieIDSetSelectedSecurityLevel = createStandardAction(
"CIE_ID_SET_SELECTED_SECURITY_LEVEL"
)<SpidLevel>();

export type CieLoginConfigActions =
| ActionType<typeof cieLoginDisableUat>
| ActionType<typeof cieLoginEnableUat>
| ActionType<typeof cieIDFeatureSetEnabled>
| ActionType<typeof cieIDDisableTourGuide>;
| ActionType<typeof cieIDDisableTourGuide>
| ActionType<typeof cieIDSetSelectedSecurityLevel>;
8 changes: 8 additions & 0 deletions ts/features/cieLogin/store/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@ import { merge } from "lodash";
import {
cieIDDisableTourGuide,
cieIDFeatureSetEnabled,
cieIDSetSelectedSecurityLevel,
cieLoginDisableUat,
cieLoginEnableUat
} from "../actions";
import { Action } from "../../../../store/actions/types";
import { isDevEnv } from "../../../../utils/environment";
import { SpidLevel } from "../../utils";

export type CieLoginState = {
useUat: boolean;
isCieIDFeatureEnabled: boolean;
isCieIDTourGuideEnabled: boolean;
cieIDSelectedSecurityLevel?: SpidLevel;
};

export const cieLoginInitialState = {
Expand Down Expand Up @@ -54,6 +57,11 @@ const cieLoginReducer = (
...state,
isCieIDTourGuideEnabled: false
};
case getType(cieIDSetSelectedSecurityLevel):
return {
...state,
cieIDSelectedSecurityLevel: action.payload
};
default:
return state;
}
Expand Down
3 changes: 3 additions & 0 deletions ts/features/cieLogin/store/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ export const isCieIDFFEnabledSelector = (state: GlobalState) =>
export const isCieIDTourGuideEnabledSelector = (state: GlobalState) =>
state.features.loginFeatures.cieLogin.isCieIDTourGuideEnabled &&
isCieIDFFEnabledSelector(state);

export const cieIDSelectedSecurityLevelSelector = (state: GlobalState) =>
state.features.loginFeatures.cieLogin.cieIDSelectedSecurityLevel;
2 changes: 2 additions & 0 deletions ts/hooks/useNavigateToLoginMethod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
ChosenIdentifier,
Identifier
} from "../screens/authentication/OptInScreen";
import { cieIDSetSelectedSecurityLevel } from "../features/cieLogin/store/actions";

export const IdpCIE: SpidIdp = {
id: "cie",
Expand Down Expand Up @@ -86,6 +87,7 @@ const useNavigateToLoginMethod = () => {
const navigateToCieIdLoginScreen = useCallback(
(spidLevel: SpidLevel = "SpidL2") => {
dispatch(idpSelected(IdpCIE_ID));
dispatch(cieIDSetSelectedSecurityLevel(spidLevel));

if (isCieIdAvailable(isCieUatEnabled) || cieFlowForDevServerEnabled) {
const params = {
Expand Down
3 changes: 3 additions & 0 deletions ts/sagas/__tests__/initializeApplicationSaga.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { trackKeychainFailures } from "../../utils/analytics";
import { checkSession } from "../startup/watchCheckSessionSaga";
import { formatRequestedTokenString } from "../../features/zendesk/utils";
import { checkPublicKeyAndBlockIfNeeded } from "../../features/lollipop/navigation";
import { userFromSuccessLoginSelector } from "../../features/login/info/store/selectors";

const aSessionToken = "a_session_token" as SessionToken;
const aSessionInfo = O.some({
Expand Down Expand Up @@ -293,6 +294,8 @@ describe("initializeApplicationSaga", () => {
.next()
.select(sessionInfoSelector)
.next(aSessionInfo)
.select(userFromSuccessLoginSelector)
.next()
.select(lollipopPublicKeySelector)
.next(aPublicKey)
.call(
Expand Down
8 changes: 8 additions & 0 deletions ts/sagas/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ import { handleApplicationStartupTransientError } from "../features/startup/saga
import { formatRequestedTokenString } from "../features/zendesk/utils";
import { isBlockingScreenSelector } from "../features/ingress/store/selectors";
import { watchLegacyTransactionSaga } from "../features/payments/transaction/store/saga";
import { userFromSuccessLoginSelector } from "../features/login/info/store/selectors";
import { shouldTrackLevelSecurityMismatchSaga } from "../features/cieLogin/sagas/trackLevelSecuritySaga";
import { startAndReturnIdentificationResult } from "./identification";
import { previousInstallationDataDeleteSaga } from "./installation";
import {
Expand Down Expand Up @@ -377,6 +379,12 @@ export function* initializeApplicationSaga(
}
}

const userFromSuccessLogin = yield* select(userFromSuccessLoginSelector);

if (userFromSuccessLogin) {
yield* call(shouldTrackLevelSecurityMismatchSaga, maybeSessionInformation);
}

const publicKey = yield* select(lollipopPublicKeySelector);

// #LOLLIPOP_CHECK_BLOCK2_START
Expand Down

0 comments on commit 99f0f97

Please sign in to comment.