'AWS assumed role not authorised to perform cognito-idp:AdminCreateUser

I am using serverless-framework for my app. I have one PreSignUp lambda function. When user will create an account, after press the submit button that lambda function will trigger.

In my serverless.yaml file IAM role policy I attached the cognito-idp:AdminCreateUser.

When ever I press submit button, I got this error: Unrecognizable lambda output. In my cloudwatch shows me this error:

"User: arn:aws:sts::... is not authorized to perform: cognito-idp:AdminCreateUser on resource: arn:aws:cognito-idp:..... because no identity-based policy allows the cognito-idp:AdminCreateUser action"

I don't understand what I am doing wrong.

This is my lambda function

import AWS from 'aws-sdk';
import joi from 'joi';

const Cognito = new AWS.CognitoIdentityServiceProvider();

const PreSignUp = async (event: any, context: any) => {
  // NOTE: Cognito expects Username to be the user's email

  /**
   * @param This process.env.COGNITO coming from serverless.yaml file. line: 18
   */
  const userPoolId = process.env.COGNITO ? process.env.COGNITO : '';

  const UNSAFE_EMAIL = event.request.userAttributes.email;
  const test = event.request.userAttributes;

  console.log({ UNSAFE_EMAIL, userPoolId, event, test });

  // Normalize email and language
  const UNSAFE_TRIMMED_EMAIL = UNSAFE_EMAIL.trim();

  const schema = joi.object().keys({
    email: joi.string().trim().email({ minDomainSegments: 2 }).required(),
  });

  const validationResult = schema.validate({
    email: UNSAFE_TRIMMED_EMAIL,
  });

  if (validationResult.error) {
    console.log(JSON.stringify(validationResult.error, null, 2));
  }

  console.log('finish the validation error');

  // Validation successful, change variable names to reflect
  const VALIDATED_EMAIL = UNSAFE_TRIMMED_EMAIL;
  // const VALIDATED_LANGUAGE = UNSAFE_TRIMMED_LANGUAGE;

  // Cognito params
  // Username is the user's email
  // email is also required in UserAttributes in order to send confirmation
  // DesiredDeliveryMediums is required to send confirmation
  const params = {
    UserPoolId: userPoolId,
    Username: VALIDATED_EMAIL,
    UserAttributes: [
      {
        Name: 'email',
        Value: VALIDATED_EMAIL,
      },
    ],
    DesiredDeliveryMediums: ['EMAIL'],
    ClientMetadata: {
      role: 'customer',
    },
  };

  // Attempt to create user in Cognito
  try {
    const authRes = await Cognito.adminCreateUser(params).promise();
    console.log('Success: ', JSON.stringify(authRes, null, 2));
    // callback(null, event);
    context.done(null, event);
  } catch (err) {
    console.log('Error: ', JSON.stringify(err, null, 2));
    return {
      statusCode: 400,
      body: JSON.stringify({
        error: true,
        error_message: err.message,
      }),
    };
  }
};

export default PreSignUp;

This is my YAML file

service: graphql-book

package:
  individually: true
  include:
    - src/**

provider:
  name: aws
  profile: ${env:profile}
  runtime: nodejs14.x
  stage: ${env:stage}
  region: eu-north-1
  timeout: 30
  apiName: ${self:service.name}-${self:provider.stage}
  environment:
    ITEM_TABLE: ${self:service}-items-${self:provider.stage}
    COGNITO: ${self:service.name}-pool
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
        - lambda:InvokeFunction # Added this like mentioned above
      Resource: 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.ITEM_TABLE}'
    - Effect: Allow
      Action:
        - dynamodb:Query
      Resource: 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.ITEM_TABLE}/index/*'
      ## Cognito roles
    - Effect: Allow
      Action:
        - cognito-idp:CreateUserPoolClient
        - cognito-idp:DeleteUserPoolClient
        - cognito-idp:AdminConfirmSignUp
        - cognito-idp:AdminInitiateAuth
        - cognito-idp:AdminAddUserToGroup
        - cognito-idp:AdminDeleteUser
        - cognito-idp:AdminCreateUser
        - cognito-idp:AdminSetUserPassword
        - lambda:InvokeFunction
      Resource: 'arn:aws:cognito-idp:eu-north-1:****:userpool/eu-north-1_*******'

  apiGateway:
    shouldStartNameWithService: true

custom:
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true
    packager: 'npm' # Packager that will be used to package your external modules
  warmup:
    enabled: true
    events:
      - schedule: rate(5 minutes)
    prewarm: true
    concurrency: 1

functions:
  graphql:
    handler: src/handlers/graphql.default
    events:
      - http:
          path: ${env:api_prefix}/graphql
          method: get
          cors: true
      - http:
          path: ${env:api_prefix}/graphql
          method: post
          cors: true
          authorizer: AuthFunction
  ## Authorization function
  AuthFunction:
    handler: src/auth/auth.default

  ## Create user
  PreSignUp: ## THIS IS THE LAMBDA FUNCTION
    handler: src/handlers/PreSignUp.default
    events:
      - cognitoUserPool:
          pool: ${self:provider.environment.COGNITO}
          trigger: PreSignUp

    ## post Confirmation
  PostConfirmation:
    handler: src/handlers/postConfirmation.default
    events:
      - cognitoUserPool:
          pool: ${self:provider.environment.COGNITO}
          trigger: PostConfirmation

resources:
  Resources:
    ItemsTable:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        AttributeDefinitions:
          - AttributeName: PK
            AttributeType: S
          - AttributeName: SK
            AttributeType: S
          - AttributeName: GSI1PK
            AttributeType: S
          - AttributeName: GSI1SK
            AttributeType: S
        KeySchema:
          - AttributeName: PK
            KeyType: HASH
          - AttributeName: SK
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        GlobalSecondaryIndexes:
          - IndexName: GSI1
            KeySchema:
              - AttributeName: GSI1PK
                KeyType: HASH
              - AttributeName: GSI1SK
                KeyType: RANGE
            Projection:
              ProjectionType: ALL
            ProvisionedThroughput:
              ReadCapacityUnits: 1
              WriteCapacityUnits: 1
        TableName: ${self:provider.environment.ITEM_TABLE}

    CognitoUserPool:
      Type: AWS::Cognito::UserPool
      Properties:
        MfaConfiguration: OFF ## Multi factor Authentocation
        UserPoolName: ${self:provider.environment.COGNITO}
        AutoVerifiedAttributes:
          - email
        UsernameAttributes:
          - email
        Policies:
          PasswordPolicy:
            MinimumLength: 6
            RequireLowercase: False
            RequireNumbers: True
            RequireSymbols: False
            RequireUppercase: True

    CognitoUserPoolGroupA:
      Type: AWS::Cognito::UserPoolGroup
      Properties:
        Description: 'Description for group A'
        GroupName: 'admin'
        UserPoolId:
          Ref: CognitoUserPool #Refers to the user pool created above

    CognitoUserPoolClient:
      Type: AWS::Cognito::UserPoolClient
      Properties:
        ClientName: ${self:provider.environment.COGNITO}
        UserPoolId:
          Ref: CognitoUserPool
        ExplicitAuthFlows:
          - ADMIN_NO_SRP_AUTH
        GenerateSecret: false

plugins:
  - serverless-webpack
  - serverless-offline
  - serverless-plugin-warmup
  - serverless-dotenv-plugin
# Outputs:
#   CognitoUserPoolId:
#     Description: 'Cognito User Pool Id'
#     Value: !Ref CognitoUserPool

#   CognitoUserPoolClientId:
#     Description: 'Cognito User Pool Client Id'
#     Value: !Ref CognitoUserPoolClient


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source