Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DCMAW-9802: Refactor session creation #44

Merged
merged 11 commits into from
Jul 25, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,7 @@ describe("Async Credential", () => {
);

expect(mockLogger.getLogMessages()[0].logMessage.sessionId).toEqual(
expect.any(String),
"mockSessionId",
);

expect(result).toStrictEqual({
Expand Down Expand Up @@ -1164,8 +1164,8 @@ class MockSessionServiceGetSessionBySubFailure
return errorResponse("Mock failing DB call");
};

createSession = async (): Promise<ErrorOrSuccess<null>> => {
return successResponse(null);
createSession = async (): Promise<ErrorOrSuccess<string>> => {
return successResponse("mockSessionId");
};
}

Expand All @@ -1183,8 +1183,8 @@ class MockSessionServiceNoActiveSession
return successResponse(null);
};

createSession = async (): Promise<ErrorOrSuccess<null>> => {
return successResponse(null);
createSession = async (): Promise<ErrorOrSuccess<string>> => {
return successResponse("mockSessionId");
};
}

Expand All @@ -1203,8 +1203,8 @@ class MockSessionServiceActiveSessionFound
return successResponse("mockSessionId");
};

createSession = async (): Promise<ErrorOrSuccess<null>> => {
return successResponse(null);
createSession = async (): Promise<ErrorOrSuccess<string>> => {
return successResponse("mockSessionId");
};
}

Expand All @@ -1223,7 +1223,7 @@ class MockSessionServiceFailToCreateSession
return successResponse(null);
};

createSession = async (): Promise<ErrorOrSuccess<null>> => {
createSession = async (): Promise<ErrorOrSuccess<string>> => {
return errorResponse("Mock error");
};
}
Expand All @@ -1243,7 +1243,7 @@ class MockSessionServiceSessionCreated
return successResponse(null);
};

createSession = async (): Promise<ErrorOrSuccess<null>> => {
return successResponse(null);
createSession = async (): Promise<ErrorOrSuccess<string>> => {
return successResponse("mockSessionId");
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
ICreateSession,
IGetActiveSession,
} from "./sessionService/sessionService";
import { randomUUID } from "crypto";
import { Logger } from "../services/logging/logger";
import { MessageName } from "./registeredLogs";
import { IGetClientCredentials } from "../asyncToken/ssmService/ssmService";
Expand Down Expand Up @@ -185,26 +184,12 @@ export async function lambdaHandler(
return activeSessionFoundResponse(requestBody.sub);
}

const { sub, client_id, govuk_signin_journey_id, redirect_uri, state } =
requestBody;
const { iss } = jwtPayload;

const sessionId = randomUUID();

const sessionConfig = {
sessionId,
state,
sub,
clientId: client_id,
govukSigninJourneyId: govuk_signin_journey_id,
redirectUri: redirect_uri,
issuer: iss,
issuedOn: Date.now().toString(),
sessionState: "ASYNC_AUTH_SESSION_CREATED",
};
const sessionServiceCreateSessionResult = await sessionService.createSession({
...requestBody,
issuer: jwtPayload.iss,
});

const sessionServiceCreateSessionResult =
await sessionService.createSession(sessionConfig);
const sessionId = sessionServiceCreateSessionResult.value;

const eventService = dependencies.eventService(config.SQS_QUEUE);

Expand All @@ -217,9 +202,9 @@ export async function lambdaHandler(

const writeEventResult = await eventService.writeGenericEvent({
eventName: "DCMAW_ASYNC_CRI_START",
sub,
sub: requestBody.sub,
sessionId,
govukSigninJourneyId: govuk_signin_journey_id,
govukSigninJourneyId: requestBody.govuk_signin_journey_id,
J-son1 marked this conversation as resolved.
Show resolved Hide resolved
getNowInMilliseconds: Date.now,
componentId: config.ISSUER,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,12 @@ describe("Session Service", () => {
dbMock.on(GetItemCommand).rejects("Mock DB Error");

const result = await service.createSession({
sessionId: "137d5a4b-3046-456d-986a-147e0469cf62",
state: "mockValidState",
sub: "mockSub",
clientId: "mockClientId",
govukSigninJourneyId: "mockJourneyId",
redirectUri: "https://mockRedirectUri.com",
client_id: "mockClientId",
govuk_signin_journey_id: "mockJourneyId",
redirect_uri: "https://mockRedirectUri.com",
issuer: "mockIssuer",
sessionState: "mockSessionState",
issuedOn: "mockIssuedOn",
});

expect(result.isError).toBe(true);
Expand All @@ -138,15 +135,12 @@ describe("Session Service", () => {
});

const result = await service.createSession({
sessionId: "137d5a4b-3046-456d-986a-147e0469cf62",
state: "mockValidState",
sub: "mockSub",
clientId: "mockClientId",
govukSigninJourneyId: "mockJourneyId",
redirectUri: "https://mockRedirectUri.com",
client_id: "mockClientId",
govuk_signin_journey_id: "mockJourneyId",
redirect_uri: "https://mockRedirectUri.com",
issuer: "mockIssuer",
sessionState: "mockSessionState",
issuedOn: "mockIssuedOn",
});

expect(result.isError).toBe(true);
Expand All @@ -163,15 +157,12 @@ describe("Session Service", () => {
dbMock.on(PutItemCommand).rejects("Mock DB Error");

const result = await service.createSession({
sessionId: "137d5a4b-3046-456d-986a-147e0469cf62",
state: "mockValidState",
sub: "mockSub",
clientId: "mockClientId",
govukSigninJourneyId: "mockJourneyId",
redirectUri: "https://mockRedirectUri.com",
client_id: "mockClientId",
govuk_signin_journey_id: "mockJourneyId",
redirect_uri: "https://mockRedirectUri.com",
issuer: "mockIssuer",
sessionState: "mockSessionState",
issuedOn: "mockIssuedOn",
});

expect(result.isError).toBe(true);
Expand All @@ -189,18 +180,15 @@ describe("Session Service", () => {
dbMock.on(PutItemCommand).resolves({});

const result = await service.createSession({
sessionId: "137d5a4b-3046-456d-986a-147e0469cf62",
state: "mockValidState",
sub: "mockSub",
clientId: "mockClientId",
govukSigninJourneyId: "mockJourneyId",
client_id: "mockClientId",
govuk_signin_journey_id: "mockJourneyId",
issuer: "mockIssuer",
sessionState: "mockSessionState",
issuedOn: "mockIssuedOn",
});

expect(result.isError).toBe(false);
expect(result.value).toEqual(null);
expect(typeof result.value).toBe("string");
});
});

Expand All @@ -211,19 +199,16 @@ describe("Session Service", () => {
dbMock.on(PutItemCommand).resolves({});

const result = await service.createSession({
sessionId: "137d5a4b-3046-456d-986a-147e0469cf62",
state: "mockValidState",
sub: "mockSub",
clientId: "mockClientId",
govukSigninJourneyId: "mockJourneyId",
redirectUri: "https://mockRedirectUri.com",
client_id: "mockClientId",
govuk_signin_journey_id: "mockJourneyId",
redirect_uri: "https://mockRedirectUri.com",
issuer: "mockIssuer",
sessionState: "mockSessionState",
issuedOn: "mockIssuedOn",
});

expect(result.isError).toBe(false);
expect(result.value).toEqual(null);
expect(typeof result.value).toBe("string");
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
errorResponse,
successResponse,
} from "../../types/errorOrValue";
import { randomUUID } from "crypto";

export class SessionService implements IGetActiveSession, ICreateSession {
readonly tableName: string;
Expand Down Expand Up @@ -72,31 +73,14 @@ export class SessionService implements IGetActiveSession, ICreateSession {
}

async createSession(
sessionConfig: IAuthSession,
): Promise<ErrorOrSuccess<null>> {
const config: IPutAuthSessionConfig = {
TableName: this.tableName,
Item: {
sessionId: { S: sessionConfig.sessionId },
state: { S: sessionConfig.state },
sub: { S: sessionConfig.sub },
clientId: { S: sessionConfig.clientId },
govukSigninJourneyId: { S: sessionConfig.govukSigninJourneyId },
issuer: { S: sessionConfig.issuer },
sessionState: { S: sessionConfig.sessionState },
issuedOn: { S: sessionConfig.issuedOn },
},
};

if (sessionConfig.redirectUri) {
config.Item.redirectUri = { S: sessionConfig.redirectUri };
}
config: ICreateSessionConfig,
): Promise<ErrorOrSuccess<string>> {
const sessionId = randomUUID();
const putSessionConfig = this.buildPutItemCommandInput(sessionId, config);

let doesSessionExist;
try {
doesSessionExist = await this.checkSessionsExists(
sessionConfig.sessionId,
);
doesSessionExist = await this.checkSessionsExists(sessionId);
} catch (error) {
return errorResponse(
"Unexpected error when querying session table to check if sessionId exists",
Expand All @@ -108,14 +92,14 @@ export class SessionService implements IGetActiveSession, ICreateSession {
}

try {
await this.putSessionInDb(config);
await this.putSessionInDb(putSessionConfig);
} catch (error) {
return errorResponse(
"Unexpected error when querying session table whilst creating a session",
);
}

return successResponse(null);
return successResponse(sessionId);
}

private hasValidSession(
Expand All @@ -129,6 +113,40 @@ export class SessionService implements IGetActiveSession, ICreateSession {
);
}

private buildPutItemCommandInput(
sessionId: string,
config: ICreateSessionConfig,
) {
const {
state,
sub,
client_id,
govuk_signin_journey_id,
redirect_uri,
issuer,
} = config;

const putSessionConfig: IPutSessionConfig = {
TableName: this.tableName,
Item: {
sessionId: { S: sessionId },
state: { S: state },
sub: { S: sub },
clientId: { S: client_id },
govukSigninJourneyId: { S: govuk_signin_journey_id },
issuer: { S: issuer },
sessionState: { S: "ASYNC_AUTH_SESSION_CREATED" },
issuedOn: { S: Date.now().toString() },
},
};

if (redirect_uri) {
putSessionConfig.Item.redirectUri = { S: redirect_uri };
}

return putSessionConfig;
}

private async checkSessionsExists(sessionId: string): Promise<boolean> {
const output = await dbClient.send(
new GetItemCommand({
Expand All @@ -142,24 +160,12 @@ export class SessionService implements IGetActiveSession, ICreateSession {
return output.Item != null;
}

private async putSessionInDb(config: IPutAuthSessionConfig) {
private async putSessionInDb(config: IPutSessionConfig) {
await dbClient.send(new PutItemCommand(config));
}
}

interface IAuthSession {
sessionId: string;
state: string;
sub: string;
clientId: string;
govukSigninJourneyId: string;
issuer: string;
sessionState: string;
issuedOn: string;
redirectUri?: string;
}

interface IPutAuthSessionConfig {
interface IPutSessionConfig {
TableName: string;
Item: {
sessionId: { S: string };
Expand All @@ -181,8 +187,19 @@ export interface IGetActiveSession {
) => Promise<ErrorOrSuccess<string | null>>;
}

interface ICreateSessionConfig {
state: string;
sub: string;
client_id: string;
govuk_signin_journey_id: string;
issuer: string;
redirect_uri?: string;
}

export interface ICreateSession {
createSession: (sessionConfig: IAuthSession) => Promise<ErrorOrSuccess<null>>;
createSession: (
config: ICreateSessionConfig,
) => Promise<ErrorOrSuccess<string>>;
}

type IQueryCommandOutputType = {
Expand Down