3

in order to list all users of a cognito user-pool, I thought of using boto3's client.list_users()-function including pagination.

However, if I call print(client.can_paginate('list_users')), False is returned since this function list_users() is not pageable.

Is there an alternative to listing all users of a cognito user-pool without filtering those users out that have already been selected?

My current code without pagination looks this:

client = boto3.client('cognito-idp',
                         region_name=aws_region,
                         aws_access_key_id=aws_access_key,
                         aws_secret_access_key=aws_secret_key,
                         config=config)

response = client.list_users(
UserPoolId=userpool_id,
AttributesToGet=[
    'email','sub'
] 
)

Many thanks in advance!

C.Tomas
  • 451
  • 2
  • 7
  • 15
  • refer https://stackoverflow.com/questions/39201093/how-to-use-boto3-pagination . https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Paginator.ListUsers – Gani VastHad Mar 17 '20 at 16:33

2 Answers2

5

Faced with the same problem, was also surprised that there is no paginator for the Cognito list_user API, so I've built something like this:

import boto3


def boto3_paginate(method_to_paginate, **params_to_pass):
    response = method_to_paginate(**params_to_pass)
    yield response
    while response.get('PaginationToken', None):
        response = method_to_paginate(PaginationToken=response['PaginationToken'], **params_to_pass)
        yield response



class CognitoIDPClient:
    def __init__(self):
        self.client = boto3.client('cognito-idp', region_name=settings.COGNITO_AWS_REGION)

    ...

    def get_all_users(self):
        """
        Fetch all users from cognito
        """
        # sadly, but there is no paginator for 'list_users' which is ... weird
        # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html?highlight=list_users#paginators
        users = []
        # if `Limit` is not provided - the api will return 60 items, which is maximum
        for page in boto3_paginate(self.client.list_users, UserPoolId=settings.COGNITO_USER_POOL):
            users += page['Users']
        return users
Gleb
  • 731
  • 1
  • 8
  • 14
  • I appreciate your answer @Gleb, and tried to implement this, but it is not paginating results, could you expand on this? – Rob Jul 26 '21 at 14:59
  • hi @RobMcelvenny. It's hard to say from your comment what might go wrong. In our product, we still using the code above. I'd suggest you to debug step by step and check which response you're getting from aws, and does it returns a PaginationToken. Maybe you're doing request to wrong cognito pool, or for some reason, there is no next page. You can try to play with boto3 request from 'python manage.py shell' to understand what's going on. https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.list_users – Gleb Jul 28 '21 at 07:48
  • no worries, I found out that there was pagination finally built into cognito ` paginator = cognito.get_paginator('list_users')` and maybe I need some more practice using pagination in general. I got my task completed though, so thanks for the help! – Rob Sep 03 '21 at 22:39
2

This worked for me, it seems there is a Paginator for list_user in boto3 cognito idp documentation:

def get_cognito_users(**kwargs) -> [dict]:
    # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html?highlight=list_users#CognitoIdentityProvider.Paginator.ListUsers
    paginator = cognito_idp_client.get_paginator('list_users')
    pages = paginator.paginate(**kwargs)
    for page in pages:
        users = []
        for obj in page.get('Users', []):
            users.append(obj)
        yield users
lmiguelmh
  • 3,074
  • 1
  • 37
  • 53