## Serverless Framework

# [Cognito User Pool](/content/framework/docs/providers/aws/events/cognito-user-pool#cognito-user-pool/index.html)

## [Valid Triggers](/content/framework/docs/providers/aws/events/cognito-user-pool#valid-triggers/index.html)

Serverless supports all Cognito User Pool Triggers as specified [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-userpool-lambdaconfig.html). Use [this guide](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html) to understand the event objects that will be passed to your function.

## [Simple event definition](/content/framework/docs/providers/aws/events/cognito-user-pool#simple-event-definition/index.html)

This will create a Cognito User Pool with the specified name. You can reference the same pool multiple times.

```yml
functions:
  preSignUp:
    handler: preSignUp.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool
          trigger: PreSignUp
  customMessage:
    handler: customMessage.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool
          trigger: CustomMessage
```

## [Multiple pools event definitions](/content/framework/docs/providers/aws/events/cognito-user-pool#multiple-pools-event-definitions/index.html)

This will create multiple Cognito User Pools with their specified names:

```yml
functions:
  preSignUpForPool1:
    handler: preSignUp.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool1
          trigger: PreSignUp
  preSignUpForPool2:
    handler: preSignUp.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool2
          trigger: PreSignUp
```

You can also deploy the same function for different user pools:

```yml
functions:
  preSignUp:
    handler: preSignUp.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool1
          trigger: PreSignUp
      - cognitoUserPool:
          pool: MyUserPool2
          trigger: PreSignUp
```

## [Special Trigger Considerations](/content/framework/docs/providers/aws/events/cognito-user-pool#special-trigger-considerations/index.html)

### [Custom Sender Triggers](/content/framework/docs/providers/aws/events/cognito-user-pool#custom-sender-triggers/index.html)

There are two types of Custom Sender Triggers, `CustomSMSSender` and `CustomEmailSender`, both [documented by AWS](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-sender-triggers.html).

In order to use these triggers, you must supply a `kmsKeyId` and (optionally) the `lambdaVersion` of the function. Only 1 `kmsKeyId` can be supplied per Cognito User Pool.

```yml
functions:
  customSMSSenderFunction:
    handler: customSMSSender.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool1
          trigger: CustomSMSSender
          kmsKeyId: 'arn:aws:kms:eu-west-1:111111111111:key/12345678-9abc-def0-1234-56789abcdef1'
  customEmailSenderFunction:
    handler: customEmailSender.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool2
          trigger: CustomEmailSender
          kmsKeyId:
            Fn::GetAtt: ['kmsKey', 'Arn']
```

resources:
  Resources:
    kmsKey:
      Type: AWS::KMS::Key
      Properties:
        Description: MyKMSKey
        Enabled: true
        KeyPolicy:
          Version: '2012-10-17'
          Id: my-kms-key
          Statement:
            Sid: Enable IAM User Permissions
            Principal:
              AWS:
                - Fn::Sub: arn:aws:iam::${AWS::AccountId}:root
            Effect: Allow
            Action: kms:*
            Resource: '*'

CognitoUserPoolMyUserPool2:
      Type: AWS::Cognito::UserPool
      Properties:
        UsernameAttributes:
          - 'email'
        AutoVerifiedAttributes:
          - 'email'
        EmailVerificationMessage: 'email message: {####}'
        EmailVerificationSubject: 'email subject: {####}'

**NOTE:** The only supported value for lambdaVersion is `V1_0`, as documented [by AWS](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-userpool-customsmssender.html).

### [PreTokenGeneration Trigger](/content/framework/docs/providers/aws/events/cognito-user-pool#pretokengeneration-trigger/index.html)

The `PreTokenGeneration` trigger supports multiple Lambda contract versions, [documented by AWS](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html). Set `lambdaVersion` to opt into a newer contract:

- `V1_0` (default behavior when `lambdaVersion` is omitted): ID token customization only.
- `V2_0`: ID and access token customization.
- `V3_0`: Adds machine-to-machine (M2M) client-credentials grants.

```yml
functions:
  preTokenGenerationV2:
    handler: preToken.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool
          trigger: PreTokenGeneration
          lambdaVersion: V2_0
```

**NOTE:**`V2_0` and `V3_0` require the Cognito User Pool to be on the Essentials or Plus feature plan.

### [Custom Sender Triggers Handlers](/content/framework/docs/providers/aws/events/cognito-user-pool#custom-sender-triggers-handlers/index.html)

For custom senders, the `event.triggerSource` type does not get populated by the type of custom sender, rather may be populated by another trigger source. Instead, `event.request.type` is populated with either `customEmailSenderRequestV1` or `customSMSSenderRequestV1`, respectively documented by AWS [here](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-email-sender.html) and [here](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-sms-sender.html)

```js
// customSender.js
function handler(event, context, callback) {
  if (event.request.type === 'customEmailSenderRequestV1') {
    // ...
  }
  if (event.request.type === 'customSMSSenderRequestV1') {
    // ...
  }
}
```

### [Custom Message Trigger Handlers](/content/framework/docs/providers/aws/events/cognito-user-pool#custom-message-trigger-handlers/index.html)

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

```js
// customMessage.js
function handler(event, context, callback) {
  if (event.triggerSource === 'CustomMessage_AdminCreateUser') {
    // ...
  }
  if (event.triggerSource === 'CustomMessage_ResendCode') {
    // ...
  }
}
```

## [Using existing pools](/content/framework/docs/providers/aws/events/cognito-user-pool#using-existing-pools/index.html)

Sometimes you might want to attach Lambda functions to existing Cognito User Pools. In that case you just need to set the `existing` event configuration property to `true`. All the other config parameters can also be used on existing user pools:

**IMPORTANT:** You can only attach 1 existing Cognito User Pool per function.

**NOTE:** Using the `existing` config will add an additional Lambda function and IAM Role to your stack. The Lambda function backs-up the Custom Cognito User Pool Resource which is used to support existing user pools.

```yaml
functions:
  users:
    handler: users.handler
    events:
      - cognitoUserPool:
          pool: legacy-user-pool
          trigger: CustomMessage
          existing: true
```

## [Overriding a generated User Pool](/content/framework/docs/providers/aws/events/cognito-user-pool#overriding-a-generated-user-pool/index.html)

A Cognito User Pool created by an event can be overridden by using the [logical resource name](/content/framework/docs/providers/aws/guide/resources#aws-cloudformation-resource-reference/index.html) in `Resources`:

```yml
functions:
  preSignUp:
    handler: preSignUpForPool1.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool
          trigger: PreSignUp
  postConfirmation:
    handler: postConfirmation.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool
          trigger: PostConfirmation

resources:
  Resources:
    CognitoUserPoolMyUserPool:
      Type: AWS::Cognito::UserPool
```

## [Forcing deploying of triggers](/content/framework/docs/providers/aws/events/cognito-user-pool#forcing-deploying-of-triggers/index.html)

A Cognito User Pool with triggers attached may not be correctly updated by AWS Cloudformation on subsequent deployments. To circumvent this issue you can use the `forceDeploy` flag which will try to force Cloudformation to update the triggers no matter what. This flag has to be used in conjunction with the `existing: true` flag.

```yml
functions:
  preSignUp:
    handler: preSignUp.handler
    events:
      - cognitoUserPool:
          pool: MyUserPool1
          trigger: PreSignUp
          existing: true
          forceDeploy: true
```
