Skip to content

Commit

Permalink
Merge pull request #1417 from govuk-one-login/AUT-2439/add-common-pas…
Browse files Browse the repository at this point in the history
…swords-to-AIS-flow

AUT-2439: Accounted for AIS in Common Passwords User Journey
  • Loading branch information
alhcomer authored Feb 29, 2024
2 parents 5f8e2c9 + b8ad976 commit efea425
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 4 deletions.
7 changes: 7 additions & 0 deletions src/components/common/state-machine/state-machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const USER_JOURNEY_EVENTS = {
TEMPORARILY_BLOCKED_INTERVENTION: "TEMP_SUSPENSION_INTERVENTION",
PERMANENTLY_BLOCKED_INTERVENTION: "PERMANENTLY_BLOCKED_INTERVENTION",
PASSWORD_RESET_INTERVENTION: "PASSWORD_RESET_INTERVENTION",
COMMON_PASSWORD_AND_AIS_STATUS: "COMMON_PASSWORD_AND_AIS_STATUS",
};

const authStateMachine = createMachine(
Expand Down Expand Up @@ -209,6 +210,9 @@ const authStateMachine = createMachine(
},
[PATH_NAMES.ENTER_PASSWORD_ACCOUNT_EXISTS]: {
on: {
[USER_JOURNEY_EVENTS.COMMON_PASSWORD_AND_AIS_STATUS]: [
PATH_NAMES.RESET_PASSWORD_CHECK_EMAIL,
],
[USER_JOURNEY_EVENTS.CREDENTIALS_VALIDATED]: [
{
target: [PATH_NAMES.RESET_PASSWORD_REQUIRED],
Expand Down Expand Up @@ -355,6 +359,9 @@ const authStateMachine = createMachine(
},
[PATH_NAMES.ENTER_PASSWORD]: {
on: {
[USER_JOURNEY_EVENTS.COMMON_PASSWORD_AND_AIS_STATUS]: [
PATH_NAMES.RESET_PASSWORD_CHECK_EMAIL,
],
[USER_JOURNEY_EVENTS.CREDENTIALS_VALIDATED]: [
{
target: [PATH_NAMES.RESET_PASSWORD_2FA_SMS],
Expand Down
39 changes: 37 additions & 2 deletions src/components/enter-password/enter-password-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@ import { MFA_METHOD_TYPE } from "../../app.constants";
import xss from "xss";
import { EnterEmailServiceInterface } from "../enter-email/types";
import { enterEmailService } from "../enter-email/enter-email-service";
import { support2FABeforePasswordReset, support2hrLockout } from "../../config";
import {
support2FABeforePasswordReset,
supportAccountInterventions,
support2hrLockout,
} from "../../config";
import { getJourneyTypeFromUserSession } from "../common/journey/journey";
import { accountInterventionService } from "../account-intervention/account-intervention-service";
import { AccountInterventionsInterface } from "../account-intervention/types";

const ENTER_PASSWORD_TEMPLATE = "enter-password/index.njk";
const ENTER_PASSWORD_VALIDATION_KEY_OLD =
Expand Down Expand Up @@ -91,7 +97,8 @@ export function enterPasswordAccountExistsGet(
export function enterPasswordPost(
fromAccountExists = false,
service: EnterPasswordServiceInterface = enterPasswordService(),
mfaCodeService: MfaServiceInterface = mfaService()
mfaCodeService: MfaServiceInterface = mfaService(),
accountInterventionsService: AccountInterventionsInterface = accountInterventionService()
): ExpressRouteFunc {
return async function (req: Request, res: Response) {
const { email } = req.session.user;
Expand Down Expand Up @@ -154,6 +161,34 @@ export function enterPasswordPost(
userLogin.data.latestTermsAndConditionsAccepted;
req.session.user.isPasswordChangeRequired = isPasswordChangeRequired;

if (
req.session.user.isPasswordChangeRequired &&
supportAccountInterventions()
) {
const accountInterventionsResponse =
await accountInterventionsService.accountInterventionStatus(
sessionId,
email,
req.ip,
clientSessionId,
persistentSessionId
);
if (
accountInterventionsResponse.data.passwordResetRequired ||
accountInterventionsResponse.data.temporarilySuspended
) {
return res.redirect(
getNextPathAndUpdateJourney(
req,
req.path,
USER_JOURNEY_EVENTS.COMMON_PASSWORD_AND_AIS_STATUS,
null,
sessionId
)
);
}
}

if (
userLogin.data.mfaRequired &&
userLogin.data.mfaMethodVerified &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
import { EnterEmailServiceInterface } from "../../enter-email/types";
import { ERROR_CODES } from "../../common/constants";
import * as journey from "../../common/journey/journey";
import { accountInterventionsFakeHelper } from "../../../../test/helpers/account-interventions-helpers";
import { supportAccountInterventions } from "../../../config";

describe("enter password controller", () => {
let req: RequestOutput;
Expand All @@ -33,6 +35,7 @@ describe("enter password controller", () => {
log: { info: sinon.fake() },
});
res = mockResponse();
supportAccountInterventions();
});

afterEach(() => {
Expand Down Expand Up @@ -342,6 +345,13 @@ describe("enter password controller", () => {
});

it("should redirect to reset-password-required when the existing password is common and supportPasswordResetRequired() is enabled", async () => {
const fakeAccountInterventionsService = accountInterventionsFakeHelper(
"[email protected]",
false,
false,
false
);

const fakeService: EnterPasswordServiceInterface = {
loginUser: sinon.fake.returns({
data: {
Expand Down Expand Up @@ -374,7 +384,8 @@ describe("enter password controller", () => {
await enterPasswordPost(
false,
fakeService,
fakeMfaService
fakeMfaService,
fakeAccountInterventionsService
)(req as Request, res as Response);

expect(res.redirect).to.have.calledWith(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import { AxiosResponse } from "axios";
import { createApiResponse } from "../../../utils/http";
import { CheckReauthServiceInterface } from "../../check-reauth-users/types";
import { DefaultApiResponse } from "../../../types";
import {
noInterventions,
setupAccountInterventionsResponse,
} from "../../../../test/helpers/account-interventions-helpers";

describe("Integration::enter password", () => {
let token: string | string[];
Expand Down Expand Up @@ -62,7 +66,6 @@ describe("Integration::enter password", () => {
return { checkReauthUsers };
});

process.env.SUPPORT_2FA_B4_PASSWORD_RESET = "1";
app = await require("../../../app").createApp();
baseApi = process.env.FRONTEND_API_BASE_URL;

Expand All @@ -76,12 +79,16 @@ describe("Integration::enter password", () => {
});

beforeEach(() => {
process.env.SUPPORT_2FA_B4_PASSWORD_RESET = "1";
process.env.SUPPORT_ACCOUNT_INTERVENTIONS = "1";
nock.cleanAll();
});

after(() => {
sinon.restore();
app = undefined;
delete process.env.SUPPORT_ACCOUNT_INTERVENTIONS;
delete process.env.SUPPORT_2FA_B4_PASSWORD_RESET;
});

it("should return enter password page", (done) => {
Expand Down Expand Up @@ -146,6 +153,8 @@ describe("Integration::enter password", () => {
passwordChangeRequired: true,
});

setupAccountInterventionsResponse(baseApi, noInterventions);

request(app)
.post(ENDPOINT)
.type("form")
Expand All @@ -165,6 +174,8 @@ describe("Integration::enter password", () => {
passwordChangeRequired: true,
});

setupAccountInterventionsResponse(baseApi, noInterventions);

request(app)
.post(ENDPOINT)
.type("form")
Expand Down

0 comments on commit efea425

Please sign in to comment.