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

Fix: User's group memberships passed to PreTokenGeneration Lambda #288

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
17 changes: 17 additions & 0 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM node:14-alpine
WORKDIR /app

# dependencies
ADD package.json yarn.lock ./
RUN yarn --frozen-lockfile

# library code
ADD src src

# bindings
EXPOSE 9229
ENV HOST 0.0.0.0
ENV PORT 9229
VOLUME /app/.cognito

ENTRYPOINT ["yarn", "start:debug"]
22 changes: 20 additions & 2 deletions src/services/lambda.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,11 @@ describe("Lambda function invoker", () => {
clientMetadata: {
client: "metadata",
},
groupConfiguration: {
groupsToOverride: ["group1", "group2"],
iamRolesToOverride: ["role1", "role2"],
preferredRole: "preferredRole",
},
});

expect(mockLambdaClient.invoke).toHaveBeenCalledWith({
Expand All @@ -461,9 +466,22 @@ describe("Lambda function invoker", () => {
clientMetadata: {
client: "metadata",
},
groupConfiguration: {},
groupConfiguration: {
groupsToOverride: ["group1", "group2"],
iamRolesToOverride: ["role1", "role2"],
preferredRole: "preferredRole",
},
},
response: {
claimsOverrideDetails: {
claimsToAddOrOverride: {},
claimsToSuppress: [],
groupOverrideDetails: {
groupsToOverride: [],
iamRolesToOverride: [],
},
},
},
response: { claimsOverrideDetails: {} },
userName: "username",
}),
});
Expand Down
16 changes: 12 additions & 4 deletions src/services/lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ interface PreTokenGenerationEvent extends EventCommonParameters {
/**
* A list of the group names that are associated with the user that the identity token is issued for.
*/
groupsToOverride: readonly string[] | undefined;
groupsToOverride: string[] | undefined;

/**
* A list of the current IAM roles associated with these groups.
*/
iamRolesToOverride: readonly string[] | undefined;
iamRolesToOverride: string[] | undefined;

/**
* A string indicating the preferred IAM role.
Expand Down Expand Up @@ -362,11 +362,19 @@ export class LambdaService implements Lambda {
userName: event.username,
request: {
userAttributes: event.userAttributes,
groupConfiguration: {},
groupConfiguration: event.groupConfiguration,
clientMetadata: event.clientMetadata,
},
response: {
claimsOverrideDetails: {},
claimsOverrideDetails: {
claimsToAddOrOverride: {},
claimsToSuppress: [],
groupOverrideDetails: {
groupsToOverride: [],
iamRolesToOverride: [],
preferredRole: undefined,
},
},
},
};
}
Expand Down
30 changes: 30 additions & 0 deletions src/services/tokenGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,36 @@ describe("JwtTokenGenerator", () => {
});
});

it("can pass user's group memberships to the PreTokenGeneration lambda", async () => {
mockTriggers.enabled.mockImplementation((name) => {
return name === "PreTokenGeneration";
});

mockTriggers.preTokenGeneration.mockResolvedValue({
claimsOverrideDetails: {
claimsToAddOrOverride: {
newclaim: "value",
email: "something else",
},
},
});

await tokenGenerator.generate(
TestContext,
user,
["group1", "group2"],
TDB.appClient(),
{ client: "metadata" },
"RefreshTokens"
);

expect(mockTriggers.preTokenGeneration.mock.calls[0][1]).toMatchObject({
groupConfiguration: {
groupsToOverride: ["group1", "group2"],
},
});
});

it("can suppress claims in the id token", async () => {
mockTriggers.enabled.mockImplementation((name) => {
return name === "PreTokenGeneration";
Expand Down
13 changes: 8 additions & 5 deletions src/services/tokenGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export class JwtTokenGenerator implements TokenGenerator {
public async generate(
ctx: Context,
user: User,
userGroups: readonly string[],
userGroups: string[],
userPoolClient: AppClient,
clientMetadata: Record<string, string> | undefined,
source:
Expand Down Expand Up @@ -183,14 +183,17 @@ export class JwtTokenGenerator implements TokenGenerator {
userAttributes: user.Attributes,
username: user.Username,
groupConfiguration: {
// TODO: this should be populated from the user's groups
groupsToOverride: undefined,
iamRolesToOverride: undefined,
preferredRole: undefined,
groupsToOverride: userGroups,
iamRolesToOverride: [],
preferredRole: "",
},
userPoolId: userPoolClient.UserPoolId,
});

ctx.logger.info(
`claimsOverrideDetails: ${JSON.stringify(result.claimsOverrideDetails)}`
);

idToken = applyTokenOverrides(idToken, result.claimsOverrideDetails);
}

Expand Down
4 changes: 2 additions & 2 deletions src/services/triggers/preTokenGeneration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ export type PreTokenGenerationTrigger = Trigger<
/**
* A list of the group names that are associated with the user that the identity token is issued for.
*/
groupsToOverride: readonly string[] | undefined;
groupsToOverride: string[] | undefined;

/**
* A list of the current IAM roles associated with these groups.
*/
iamRolesToOverride: readonly string[] | undefined;
iamRolesToOverride: string[] | undefined;

/**
* A string indicating the preferred IAM role.
Expand Down