Search code examples
androidamazon-web-servicesaws-lambdaaws-amplify

How to query user pool from cognito with lambda functions using Amplify-android AWS


I have this function signature on schema.graphql, can I used it in order to call to lambda function that retrieve user list from Cognito server?

type Query 
{
  echo(msg: String): String @function(name: "getUsers-${env}")
}

How can I call it from Android ?

Do I need Apollo ?

Does Amplify library it's enough ?


Solution

  • Basically you can't query users from Cognito Amazon server directly using the schema.

    In the Android application you must create and use the following Amplify plugins, you can read more about it from here: https://docs.amplify.aws/start/q/integration/android

    You must create lambda function as describe here:

    const AWS = require('aws-sdk');
    const cognito = new AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18', region: 'eu-central-1'});
    
    exports.handler = async (event) => {
        // TODO implement
        let users = [];
        let roles = ['admin', 'user' ];
    
        try
        {
            // (let i=0, len=roles.length; i<len; i++) 
            //{
                //const role = roles[i];
                let more = true;
                let nextToken = '';
        
                while (more) 
                {
                    let params = {
                      UserPoolId: "your pool id",
                      //GroupName: role,
                      Limit: 60
                    };
                    
                    if (nextToken !== '')
                    {
                        params.NextToken = nextToken;
                    } 
                    
                    const rawUsers = await cognito.listUsers(params).promise();
                    const mapUsers = rawUsers.Users.map(user => {
                    
                        let atts = {};
            
                        for (const att of user.Attributes) 
                        {
                            atts[att.Name] = att.Value;
                        }
            
                        return {
                            username: user.Username,
                            name: atts.hasOwnProperty('name') ? atts.name : '',
                            email: atts.hasOwnProperty('email') ? atts.email : '',
                            status: user.UserStatus,
                            //role: role
                        };
                  
                    
                    });
                
                    users= users.concat(mapUsers);
                    if (rawUsers.hasOwnProperty('NextToken')) {
                      nextToken = rawUsers.NextToken;
                    } else {
                      more = false;
                    }
                        }
                
                
           // }
            
            const response = {
                statusCode: 200,
            //  Uncomment below to enable CORS requests
            //  headers: {
            //      "Access-Control-Allow-Origin": "*"
            //  }, 
                body: JSON.stringify(users),
            };
            return response;
       
        }
        catch(e)
        {
            const response = {
                statusCode: 500,
            //  Uncomment below to enable CORS requests
            //  headers: {
            //      "Access-Control-Allow-Origin": "*"
            //  }, 
                body: e,
            };
            return response;
        }
    };
    
    

    Then create REST api: Use the terminal Amplify CLI commands and connect it to the lambda function that was created including "Authenticated users only". Run:

    amplify add api
    C:\DOV_AWS>amplify api add
    ? Please select from one of the below mentioned services: REST
    ? Provide a friendly name for your resource to be used as a label for this category in the
     project: users
    ? Provide a path (e.g., /book/{isbn}):
    C:\DOV_AWS>amplify api add
    ? Please select from one of the below mentioned services: REST
    ? Provide a friendly name for your resource to be used as a label for this category in the
     project: DOV
    ? Provide a path (e.g., /book/{isbn}): /users
    ? Choose a Lambda source Use a Lambda function already added in the current Amplify projec
    t
    ? Choose the Lambda function to invoke by this path getUsers
    ? Restrict API access Yes
    ? Who should have access? Authenticated users only
    ? What kind of access do you want for Authenticated users? create, read, update, delete
    ? Do you want to add another path? No
    Successfully added resource DOV locally
    
    

    Use the amplify push command: amplify push

    In order to update the API on the cloud.

    Run the following code in your app in order to fetch the users.

    
       RestOptions options = RestOptions.builder()
                            .addPath("/users")
                            .build();
    
                            Amplify.API.get("Users", options, response -> 
                            Log.i("MyAmplifyApp", " ! ! ! ! ! Data Respond ! ! ! ! !" 
                            + response.getData().asString()),
                            error -> Log.e("MyAmplifyApp", "GET failed", error)
       );
    
                                          
    

    You must add permission rule for Cognito server in the lambda function in order to fetch the user data.

    The authentication method will include IAM rule