Skip to content

Commit 1189628

Browse files
fixed merge conflicts
2 parents c11ec7d + d472261 commit 1189628

27 files changed

+630
-847
lines changed

packages/cognito/src/authorize.ts

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,11 @@ import {Logger} from "@aws-lambda-powertools/logger"
22
import {APIGatewayProxyEvent, APIGatewayProxyResult} from "aws-lambda"
33
import {injectLambdaContext} from "@aws-lambda-powertools/logger/middleware"
44

5-
import {DynamoDBClient} from "@aws-sdk/client-dynamodb"
6-
import {DynamoDBDocumentClient} from "@aws-sdk/lib-dynamodb"
7-
85
import {MiddyErrorHandler} from "@cpt-ui-common/middyErrorHandler"
96

107
import middy from "@middy/core"
118
import inputOutputLogger from "@middy/input-output-logger"
129

13-
import {createHash} from "crypto"
14-
15-
import {insertStateMapping} from "@cpt-ui-common/dynamoFunctions"
16-
1710
/*
1811
* Expects the following environment variables to be set:
1912
*
@@ -24,24 +17,18 @@ import {insertStateMapping} from "@cpt-ui-common/dynamoFunctions"
2417
*
2518
* FULL_CLOUDFRONT_DOMAIN
2619
*
27-
* StateMappingTableName
28-
*
2920
*/
3021

3122
// Environment variables
3223
const authorizeEndpoint = process.env["IDP_AUTHORIZE_PATH"] as string
3324
const cis2ClientId = process.env["OIDC_CLIENT_ID"] as string
3425
const userPoolClientId = process.env["COGNITO_CLIENT_ID"] as string
3526
const cloudfrontDomain = process.env["FULL_CLOUDFRONT_DOMAIN"] as string
36-
const stateMappingTableName = process.env["StateMappingTableName"] as string
3727

3828
const logger = new Logger({serviceName: "authorize"})
3929
const errorResponseBody = {message: "A system error has occurred"}
4030
const middyErrorHandler = new MiddyErrorHandler(errorResponseBody)
4131

42-
const dynamoClient = new DynamoDBClient()
43-
const documentClient = DynamoDBDocumentClient.from(dynamoClient)
44-
4532
const lambdaHandler = async (
4633
event: APIGatewayProxyEvent
4734
): Promise<APIGatewayProxyResult> => {
@@ -50,14 +37,12 @@ const lambdaHandler = async (
5037
authorizeEndpoint,
5138
cis2ClientId,
5239
userPoolClientId,
53-
cloudfrontDomain,
54-
stateMappingTableName
40+
cloudfrontDomain
5541
}})
5642

5743
// Validate required environment variables
5844
if (!authorizeEndpoint) throw new Error("Authorize endpoint environment variable not set")
5945
if (!cloudfrontDomain) throw new Error("Cloudfront domain environment variable not set")
60-
if (!stateMappingTableName) throw new Error("State mapping table name environment variable not set")
6146
if (!userPoolClientId) throw new Error("Cognito user pool client ID environment variable not set")
6247
if (!cis2ClientId) throw new Error("OIDC client ID environment variable not set")
6348

@@ -74,34 +59,18 @@ const lambdaHandler = async (
7459
queryParams.scope = "openid profile nhsperson nationalrbacaccess associatedorgs"
7560

7661
// Ensure the state parameter is provided
77-
const originalState = queryParams.state
78-
if (!originalState) throw new Error("Missing state parameter")
79-
80-
// Generate the hashed state value
81-
const cis2State = createHash("sha256").update(originalState).digest("hex")
82-
83-
// Set TTL for 5 minutes from now
84-
const stateTtl = Math.floor(Date.now() / 1000) + 300
62+
const state = queryParams.state
63+
if (!state) throw new Error("Missing state parameter")
8564

8665
// Build the callback URI for redirection
8766
const callbackUri = `https://${cloudfrontDomain}/oauth2/callback`
8867

89-
// Store original state mapping in DynamoDB
90-
const item = {
91-
State: cis2State,
92-
CognitoState: originalState,
93-
ExpiryTime: stateTtl
94-
}
95-
96-
await insertStateMapping(documentClient, stateMappingTableName, item, logger)
97-
logger.debug("State mapping inserted", {item})
98-
9968
// Build the redirect parameters for CIS2
10069
const responseParameters = {
10170
response_type: queryParams.response_type as string,
10271
scope: queryParams.scope as string,
10372
client_id: cis2ClientId,
104-
state: cis2State,
73+
state,
10574
redirect_uri: callbackUri,
10675
prompt: "login"
10776
}

packages/cognito/src/authorizeMock.ts

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,11 @@ import {Logger} from "@aws-lambda-powertools/logger"
22
import {APIGatewayProxyEvent, APIGatewayProxyResult} from "aws-lambda"
33
import {injectLambdaContext} from "@aws-lambda-powertools/logger/middleware"
44

5-
import {DynamoDBClient} from "@aws-sdk/client-dynamodb"
6-
import {DynamoDBDocumentClient} from "@aws-sdk/lib-dynamodb"
7-
85
import {MiddyErrorHandler} from "@cpt-ui-common/middyErrorHandler"
96

107
import middy from "@middy/core"
118
import inputOutputLogger from "@middy/input-output-logger"
129

13-
import {createHash} from "crypto"
14-
15-
import {insertStateMapping} from "@cpt-ui-common/dynamoFunctions"
16-
1710
/*
1811
* Expects the following environment variables to be set:
1912
*
@@ -23,25 +16,19 @@ import {insertStateMapping} from "@cpt-ui-common/dynamoFunctions"
2316
*
2417
* FULL_CLOUDFRONT_DOMAIN
2518
*
26-
* StateMappingTableName
27-
*
2819
*/
2920

3021
// Environment variables
3122
const authorizeEndpoint = process.env["IDP_AUTHORIZE_PATH"] as string
3223
const cis2ClientId = process.env["OIDC_CLIENT_ID"] as string
3324
const userPoolClientId = process.env["COGNITO_CLIENT_ID"] as string
3425
const cloudfrontDomain = process.env["FULL_CLOUDFRONT_DOMAIN"] as string
35-
const stateMappingTableName = process.env["StateMappingTableName"] as string
3626
const apigeeApiKey = process.env["APIGEE_API_KEY"] as string
3727

3828
const logger = new Logger({serviceName: "authorize"})
3929
const errorResponseBody = {message: "A system error has occurred"}
4030
const middyErrorHandler = new MiddyErrorHandler(errorResponseBody)
4131

42-
const dynamoClient = new DynamoDBClient()
43-
const documentClient = DynamoDBDocumentClient.from(dynamoClient)
44-
4532
const lambdaHandler = async (
4633
event: APIGatewayProxyEvent
4734
): Promise<APIGatewayProxyResult> => {
@@ -56,14 +43,12 @@ const lambdaHandler = async (
5643
cis2ClientId,
5744
userPoolClientId,
5845
cloudfrontDomain,
59-
stateMappingTableName,
6046
apigeeApiKey
6147
}})
6248

6349
// Validate required environment variables
6450
if (!authorizeEndpoint) throw new Error("Authorize endpoint environment variable not set")
6551
if (!cloudfrontDomain) throw new Error("Cloudfront domain environment variable not set")
66-
if (!stateMappingTableName) throw new Error("State mapping table name environment variable not set")
6752
if (!userPoolClientId) throw new Error("Cognito user pool client ID environment variable not set")
6853
if (!cis2ClientId) throw new Error("OIDC client ID environment variable not set")
6954
if (!apigeeApiKey) throw new Error("apigee api key environment variable not set")
@@ -81,12 +66,6 @@ const lambdaHandler = async (
8166
const originalState = queryParams.state
8267
if (!originalState) throw new Error("Missing state parameter")
8368

84-
// Generate the hashed state value
85-
const cis2State = createHash("sha256").update(originalState).digest("hex")
86-
87-
// Set TTL for 5 minutes from now
88-
const stateTtl = Math.floor(Date.now() / 1000) + 300
89-
9069
// Build the callback URI for redirection
9170
// for pull requests we pack the real callback url for this pull request into the state
9271
// the callback lambda then decodes this and redirects to the callback url for this pull request
@@ -96,19 +75,10 @@ const lambdaHandler = async (
9675
const newStateJson = {
9776
isPullRequest: true,
9877
redirectUri: realCallbackUri,
99-
originalState: cis2State
78+
originalState
10079
}
10180
const newState = Buffer.from(JSON.stringify(newStateJson)).toString("base64")
10281

103-
// Store original state mapping in DynamoDB
104-
const item = {
105-
State: cis2State,
106-
CognitoState: originalState,
107-
ExpiryTime: stateTtl
108-
}
109-
110-
await insertStateMapping(documentClient, stateMappingTableName, item, logger)
111-
11282
// Build the redirect parameters for CIS2
11383
const responseParameters = {
11484
redirect_uri: callbackUri,

packages/cognito/src/callback.ts

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
import {Logger} from "@aws-lambda-powertools/logger"
22
import {APIGatewayProxyEvent, APIGatewayProxyResult} from "aws-lambda"
33
import {injectLambdaContext} from "@aws-lambda-powertools/logger/middleware"
4-
import {DynamoDBClient} from "@aws-sdk/client-dynamodb"
5-
import {DynamoDBDocumentClient} from "@aws-sdk/lib-dynamodb"
64
import {MiddyErrorHandler} from "@cpt-ui-common/middyErrorHandler"
75
import middy from "@middy/core"
86
import inputOutputLogger from "@middy/input-output-logger"
9-
import {deleteStateMapping, getStateMapping} from "@cpt-ui-common/dynamoFunctions"
7+
import {buildCallbackRedirect} from "./helpers"
108

119
/*
1210
* Expects the following environment variables to be set:
1311
*
14-
* StateMappingTableName
1512
* COGNITO_CLIENT_ID
1613
* COGNITO_DOMAIN
1714
* PRIMARY_OIDC_ISSUER
@@ -23,17 +20,12 @@ const errorResponseBody = {message: "A system error has occurred"}
2320
const middyErrorHandler = new MiddyErrorHandler(errorResponseBody)
2421

2522
// Environment variables
26-
const stateMappingTableName = process.env["StateMappingTableName"] as string
2723
const fullCognitoDomain = process.env["COGNITO_DOMAIN"] as string
2824

29-
const dynamoClient = new DynamoDBClient()
30-
const documentClient = DynamoDBDocumentClient.from(dynamoClient)
31-
3225
const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
3326
logger.appendKeys({"apigw-request-id": event.requestContext?.requestId})
3427

3528
// Destructure and validate required query parameters
36-
// TODO: investigate if session_state is needed at all for this function
3729
const {state, code, session_state} = event.queryStringParameters || {}
3830
if (!state || !code) {
3931
logger.error(
@@ -44,27 +36,7 @@ const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayPro
4436
}
4537
logger.info("Incoming query parameters", {state, code})
4638

47-
const cognitoStateItem = await getStateMapping(documentClient, stateMappingTableName, state, logger)
48-
await deleteStateMapping(documentClient, stateMappingTableName, state, logger)
49-
50-
// Build response parameters for redirection
51-
const responseParams = {
52-
state: cognitoStateItem.CognitoState,
53-
session_state: session_state || "",
54-
code
55-
}
56-
57-
const redirectUri = `https://${fullCognitoDomain}/oauth2/idpresponse` +
58-
`?${new URLSearchParams(responseParams).toString()}`
59-
60-
logger.info("Redirecting to Cognito", {redirectUri})
61-
62-
return {
63-
statusCode: 302,
64-
headers: {Location: redirectUri},
65-
isBase64Encoded: false,
66-
body: JSON.stringify({})
67-
}
39+
return buildCallbackRedirect(logger, state, code, session_state, fullCognitoDomain)
6840
}
6941

7042
export const handler = middy(lambdaHandler)

packages/cognito/src/callbackMock.ts

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
import {Logger} from "@aws-lambda-powertools/logger"
22
import {APIGatewayProxyEvent, APIGatewayProxyResult} from "aws-lambda"
33
import {injectLambdaContext} from "@aws-lambda-powertools/logger/middleware"
4-
import {DynamoDBClient} from "@aws-sdk/client-dynamodb"
5-
import {DynamoDBDocumentClient} from "@aws-sdk/lib-dynamodb"
64
import {MiddyErrorHandler} from "@cpt-ui-common/middyErrorHandler"
75
import middy from "@middy/core"
86
import inputOutputLogger from "@middy/input-output-logger"
9-
import {createHash, randomBytes} from "crypto"
10-
import {deleteStateMapping, getStateMapping, insertSessionState} from "@cpt-ui-common/dynamoFunctions"
7+
import {buildCallbackRedirect} from "./helpers"
118

129
/*
1310
* Expects the following environment variables to be set:
1411
*
15-
* StateMappingTableName
1612
* COGNITO_CLIENT_ID
1713
* COGNITO_DOMAIN
1814
* MOCK_OIDC_ISSUER
@@ -25,13 +21,8 @@ const errorResponseBody = {message: "A system error has occurred"}
2521
const middyErrorHandler = new MiddyErrorHandler(errorResponseBody)
2622

2723
// Environment variables
28-
const stateMappingTableName = process.env["StateMappingTableName"] as string
29-
const SessionStateMappingTableName = process.env["SessionStateMappingTableName"] as string
3024
const fullCognitoDomain = process.env["COGNITO_DOMAIN"] as string
3125

32-
const dynamoClient = new DynamoDBClient()
33-
const documentClient = DynamoDBDocumentClient.from(dynamoClient)
34-
3526
const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
3627
logger.appendKeys({"apigw-request-id": event.requestContext?.requestId})
3728

@@ -72,56 +63,7 @@ const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayPro
7263
// Continue with regular flow
7364
}
7465

75-
// TODO: remove session state mapping we can just use the state mapping
76-
//TODO: make sure to update the logic that currently points to the session state mapping table
77-
// If not a PR redirect, continue with the standard Cognito flow
78-
// Get the original Cognito state from DynamoDB
79-
logger.debug("trying to get data from session state table", {
80-
stateMappingTableName,
81-
state
82-
})
83-
const cognitoStateItem = await getStateMapping(documentClient, stateMappingTableName, state, logger)
84-
await deleteStateMapping(documentClient, stateMappingTableName, state, logger)
85-
86-
// we need to generate a session state param and store it along with code returned
87-
// as that will be used in the token lambda
88-
// Generate the hashed state value
89-
const sessionState = createHash("sha256").update(state).digest("hex")
90-
const localCode = randomBytes(20).toString("hex")
91-
92-
const sessionStateExpiryTime = Math.floor(Date.now() / 1000) + 300
93-
94-
const item = {
95-
LocalCode: localCode,
96-
SessionState: sessionState,
97-
ApigeeCode: code,
98-
ExpiryTime: sessionStateExpiryTime
99-
}
100-
101-
logger.debug("going to insert into session state mapping table", {
102-
SessionStateMappingTableName,
103-
item
104-
})
105-
await insertSessionState(documentClient, SessionStateMappingTableName, item, logger)
106-
107-
// Build response parameters for redirection
108-
const responseParams = {
109-
state: cognitoStateItem.CognitoState,
110-
session_state: sessionState,
111-
code: localCode
112-
}
113-
114-
const redirectUri = `https://${fullCognitoDomain}/oauth2/idpresponse` +
115-
`?${new URLSearchParams(responseParams).toString()}`
116-
117-
logger.info("Redirecting to Cognito", {redirectUri})
118-
119-
return {
120-
statusCode: 302,
121-
headers: {Location: redirectUri},
122-
isBase64Encoded: false,
123-
body: JSON.stringify({})
124-
}
66+
return buildCallbackRedirect(logger, state, code, session_state, fullCognitoDomain)
12567
}
12668

12769
export const handler = middy(lambdaHandler)

packages/cognito/src/helpers.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,29 @@ export function rewriteRequestBody(
3939
delete objectBodyParameters.client_secret
4040
return objectBodyParameters
4141
}
42+
43+
export function buildCallbackRedirect(
44+
logger: Logger,
45+
state: string,
46+
code: string,
47+
session_state: string | undefined,
48+
fullCognitoDomain: string
49+
) {
50+
const responseParams = {
51+
state,
52+
session_state: session_state || "",
53+
code
54+
}
55+
56+
const redirectUri = `https://${fullCognitoDomain}/oauth2/idpresponse` +
57+
`?${new URLSearchParams(responseParams).toString()}`
58+
59+
logger.info("Redirecting to Cognito", {redirectUri})
60+
61+
return {
62+
statusCode: 302,
63+
headers: {Location: redirectUri},
64+
isBase64Encoded: false,
65+
body: JSON.stringify({})
66+
}
67+
}

0 commit comments

Comments
 (0)