Skip to content

Commit 05d4418

Browse files
feat: add support for PreTokenGeneration trigger with multiple lambda versions in Cognito User Pool
1 parent e2127ef commit 05d4418

File tree

3 files changed

+87
-3
lines changed

3 files changed

+87
-3
lines changed

docs/events/cognito-user-pool.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,45 @@ function handler(event, context, callback) {
140140
}
141141
```
142142

143+
### PreTokenGeneration Trigger
144+
145+
The PreTokenGeneration trigger supports multiple lambda versions for enhanced token customization:
146+
147+
```yml
148+
functions:
149+
preTokenGenerationV1:
150+
handler: preToken.handler
151+
events:
152+
- cognitoUserPool:
153+
pool: MyUserPool
154+
trigger: PreTokenGeneration
155+
# No lambdaVersion = V1_0 behavior (ID token customization only)
156+
157+
preTokenGenerationV2:
158+
handler: preToken.handler
159+
events:
160+
- cognitoUserPool:
161+
pool: MyUserPool
162+
trigger: PreTokenGeneration
163+
lambdaVersion: V2_0 # ID + Access token customization
164+
165+
preTokenGenerationV3:
166+
handler: preToken.handler
167+
events:
168+
- cognitoUserPool:
169+
pool: MyUserPool
170+
trigger: PreTokenGeneration
171+
lambdaVersion: V3_0 # Includes M2M client-credentials grants
172+
```
173+
174+
**Lambda Version Support:**
175+
176+
- `V1_0` (default): ID token customization only
177+
- `V2_0`: ID and access token customization
178+
- `V3_0`: Includes machine-to-machine (M2M) client-credentials grants
179+
180+
**NOTE:** V2_0 and V3_0 require your user pool to be on the Essentials or Plus feature plan, as documented [by AWS](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html).
181+
143182
### Custom Message Trigger Handlers
144183

145184
For custom messages, you will need to check `event.triggerSource` type inside your handler function:

lib/plugins/aws/custom-resources/resources/cognito-user-pool/lib/user-pool.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ async function updateConfiguration(config) {
9191
LambdaVersion: poolConfig.LambdaVersion,
9292
};
9393
LambdaConfig.KMSKeyID = poolConfig.KMSKeyID;
94+
} else if (poolConfig.Trigger === 'PreTokenGeneration' && poolConfig.LambdaVersion) {
95+
LambdaConfig.PreTokenGenerationConfig = {
96+
LambdaArn: lambdaArn,
97+
LambdaVersion: poolConfig.LambdaVersion,
98+
};
9499
} else {
95100
LambdaConfig[poolConfig.Trigger] = lambdaArn;
96101
}
@@ -131,6 +136,9 @@ async function removeConfiguration(config) {
131136
function removeExistingLambdas(lambdaConfig, lambdaArn) {
132137
const res = Object.fromEntries(
133138
Object.entries(lambdaConfig).filter(([key, value]) => {
139+
if (key === 'PreTokenGenerationConfig' && value && value.LambdaArn === lambdaArn) {
140+
return false;
141+
}
134142
return (
135143
!(customSenderSources.includes(key) && value.LambdaArn === lambdaArn) && value !== lambdaArn
136144
);

lib/plugins/aws/package/compile/events/cognito-user-pool.js

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const validTriggerSources = [
2020
'UserMigration',
2121
].concat(customSenderSources);
2222

23-
const validLambdaVersions = ['V1_0'];
23+
const customSenderValidVersions = ['V1_0'];
24+
const preTokenGenerationValidVersions = ['V1_0', 'V2_0', 'V3_0'];
2425

2526
class AwsCompileCognitoUserPoolEvents {
2627
constructor(serverless, options) {
@@ -154,6 +155,8 @@ class AwsCompileCognitoUserPoolEvents {
154155
const { pool, trigger, forceDeploy, kmsKeyId, lambdaVersion } = event.cognitoUserPool;
155156
usesExistingCognitoUserPool = funcUsesExistingCognitoUserPool = true;
156157

158+
this.validateLambdaVersion(trigger, lambdaVersion);
159+
157160
if (!currentPoolName) {
158161
currentPoolName = pool;
159162
}
@@ -190,12 +193,14 @@ class AwsCompileCognitoUserPoolEvents {
190193
userPoolConfig = {
191194
...userPoolConfig,
192195
...{
193-
LambdaVersion: lambdaVersion || validLambdaVersions[0],
196+
LambdaVersion: lambdaVersion || customSenderValidVersions[0],
194197
},
195198
};
196199

197200
this.checkKmsArn(kmsKeyId, poolKmsIdMap, pool);
198201
userPoolConfig.KMSKeyID = kmsKeyId;
202+
} else if (trigger === 'PreTokenGeneration' && lambdaVersion) {
203+
userPoolConfig.LambdaVersion = lambdaVersion;
199204
}
200205

201206
if (numEventsForFunc === 1) {
@@ -310,6 +315,29 @@ class AwsCompileCognitoUserPoolEvents {
310315
poolKmsIdMap.set(currentPoolName, kmsKeyId);
311316
}
312317

318+
validateLambdaVersion(trigger, lambdaVersion) {
319+
if (customSenderSources.includes(trigger)) {
320+
if (lambdaVersion && !customSenderValidVersions.includes(lambdaVersion)) {
321+
throw new ServerlessError(
322+
`Invalid lambdaVersion "${lambdaVersion}" for trigger "${trigger}". Custom sender triggers only support: ${customSenderValidVersions.join(', ')}`,
323+
'COGNITO_INVALID_LAMBDA_VERSION'
324+
);
325+
}
326+
} else if (trigger === 'PreTokenGeneration') {
327+
if (lambdaVersion && !preTokenGenerationValidVersions.includes(lambdaVersion)) {
328+
throw new ServerlessError(
329+
`Invalid lambdaVersion "${lambdaVersion}" for trigger "${trigger}". PreTokenGeneration supports: ${preTokenGenerationValidVersions.join(', ')}`,
330+
'COGNITO_INVALID_LAMBDA_VERSION'
331+
);
332+
}
333+
} else if (lambdaVersion) {
334+
throw new ServerlessError(
335+
`lambdaVersion is not supported for trigger "${trigger}". It's only supported for: CustomSMSSender, CustomEmailSender, and PreTokenGeneration`,
336+
'COGNITO_LAMBDA_VERSION_NOT_SUPPORTED'
337+
);
338+
}
339+
}
340+
313341
findUserPoolsAndFunctions() {
314342
const userPools = [];
315343
const cognitoUserPoolTriggerFunctions = [];
@@ -323,6 +351,8 @@ class AwsCompileCognitoUserPoolEvents {
323351
if (event.cognitoUserPool) {
324352
if (event.cognitoUserPool.existing) return;
325353

354+
this.validateLambdaVersion(event.cognitoUserPool.trigger, event.cognitoUserPool.lambdaVersion);
355+
326356
// Save trigger functions so we can use them to generate
327357
// IAM permissions later
328358
cognitoUserPoolTriggerFunctions.push({
@@ -354,11 +384,18 @@ class AwsCompileCognitoUserPoolEvents {
354384
triggerObject = {
355385
[value.triggerSource]: {
356386
LambdaArn: resolveLambdaTarget(value.functionName, functionObj),
357-
LambdaVersion: value.lambdaVersion || validLambdaVersions[0],
387+
LambdaVersion: value.lambdaVersion || customSenderValidVersions[0],
358388
},
359389
};
360390
this.checkKmsArn(value.kmsKeyId, poolKmsIdMap, poolName);
361391
triggerObject.KMSKeyID = value.kmsKeyId;
392+
} else if (value.triggerSource === 'PreTokenGeneration' && value.lambdaVersion) {
393+
triggerObject = {
394+
PreTokenGenerationConfig: {
395+
LambdaArn: resolveLambdaTarget(value.functionName, functionObj),
396+
LambdaVersion: value.lambdaVersion,
397+
},
398+
};
362399
} else {
363400
triggerObject = {
364401
[value.triggerSource]: resolveLambdaTarget(value.functionName, functionObj),

0 commit comments

Comments
 (0)