Aws cognito indentity js has a method listUsers() to get the list of all users in a user pool. Does this package has a similar method? I tried to find one but nothing was found. I wanted to get all the users in a user pool and, if possible, with some filters.
For now it's not implemented. We will mark this as feature request.
Any workaround for this?
This function will solve our problems, just use the aws key and secret, user pool region and id and call the function getUsers().
You can use filters in params to do a more specific request. If you need more help, tell me and I will provide an example with filters too. https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#listUsers-property
```javascript
var AWS = require('aws-sdk');
exports.getUsers= () => {
var params = {
UserPoolId: USER_POOL_ID
AttributesToGet: [
'ATTRIBUTE_NAME',
],
};
return new Promise((resolve, reject) => {
AWS.config.update({ region: USER_POOL_REGION, 'accessKeyId': AWS_ACCESS_KEY_ID, 'secretAccessKey': AWS_SECRET_KEY });
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
cognitoidentityserviceprovider.listUsers(params, (err, data) => {
if (err) {
console.log(err);
reject(err)
}
else {
console.log("data", data);
resolve(data)
}
})
});
}
@PedroS11 are you storing the access key and secret key in your front end code?
No, I'm storing in the backend. For example when the front end does a request to /listUsers, in the backend I call that function and return the list
@PedroS11 - if you had the credentials in ~/.aws/credentials.. it should pick it up without having to pass them explicitly. Not 100% certain.
@powerful23 - has this been implemented yet?
Any update on this? Need this functionality for my web application.
@stayingcool my workaround works, while this isn't implemented you can give it a try
@PedroS11
I am trying to follow your above code for getting user list in Cognito User Pool. So I put that code in Lambda API. And I have got one error as follow:
parsing error: unexpected token AttributesToGet
Do you have any idea how can I fix it?
It has been fixed by self. Thanks.
It has been fixed by self. Thanks.
I didn't use Lambda API but I'm glad you fixed, post your fix, it could help someone in the future
@PedroS11 the main problem that I have with this is that I need to pass the access key and secret access key (in a way that also works in local and in production as well) without commiting them to the repo, and since I'm using Amplify with AppSync I really don't have a backend, I'm trying to do this as a frontend function.
To me, the ideal solution would be to "reuse" the authentication that Amplify already did, for example, for changing a password you can do it with the Auth class, yet this also ends up making calls through the AWS SDK, hence it should have done some sort of authentication to have permission to do it.
Anyway, any idea on how to keep the secrets out of the code repo while being able to do this?
Thanks.
@PedroS11 the main problem that I have with this is that I need to pass the access key and secret access key (in a way that also works in local and in production as well) without commiting them to the repo, and since I'm using Amplify with AppSync I really don't have a backend, I'm trying to do this as a frontend function.
To me, the ideal solution would be to "reuse" the authentication that Amplify already did, for example, for changing a password you can do it with the Auth class, yet this also ends up making calls through the AWS SDK, hence it should have done some sort of authentication to have permission to do it.
Anyway, any idea on how to keep the secrets out of the code repo while being able to do this?Thanks.
you will need some sort of back end. create a lambda and add an API gateway to it, then add your cognito user group as an authentication method for the gateway. then you can pass the user's cognito token as a header to your lambda to auth the request. unfortunately I think this only works for the entire group and doesn't allow you to provide access based on usergroups
I thought so :/ Anyway, thanks!
May be useful, works for me
Make sure to update permission on Role
// with Vue
Vue.use(AmplifyPlugin, AmplifyModules)
Vue.prototype.$Auth = AmplifyModules.Auth
const AWS = require("aws-sdk")
// Call this method for listUsers
this.$Auth.currentCredentials().then(credentials => {
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({
apiVersion: "2016-04-18", region: "
credentials: this.$Auth.essentialCredentials(credentials) })
cognitoidentityserviceprovider.listUsers({ UserPoolId: "<YOUR_USER_POOL_ID>" }, (err, data) => {
if (err) {
console.log(err)
} else {
console.log("data", data)
}
})
})
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This got marked as a feature request, now marked as stale, is it on the roadmap? I am going to try the recommended alternative above, but it does seem like a valuable addition to Amplify.
This got marked as a feature request!!!
We are tracking this as part of the "Admin Queries" section of this RFC: https://github.com/aws-amplify/amplify-cli/issues/766
This function will solve our problems, just use the aws key and secret, user pool region and id and call the function getUsers().
You can use filters in params to do a more specific request. If you need more help, tell me and I will provide an example with filters too. https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#listUsers-propertyvar AWS = require('aws-sdk'); exports.getUsers= () => { var params = { UserPoolId: USER_POOL_ID AttributesToGet: [ 'ATTRIBUTE_NAME', ], }; return new Promise((resolve, reject) => { AWS.config.update({ region: USER_POOL_REGION, 'accessKeyId': AWS_ACCESS_KEY_ID, 'secretAccessKey': AWS_SECRET_KEY }); var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider(); cognitoidentityserviceprovider.listUsers(params, (err, data) => { if (err) { console.log(err); reject(err) } else { console.log("data", data); resolve(data) } }) }); }
How would I implement this in React?
This function will solve our problems, just use the aws key and secret, user pool region and id and call the function getUsers().
You can use filters in params to do a more specific request. If you need more help, tell me and I will provide an example with filters too. https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#listUsers-propertyvar AWS = require('aws-sdk'); exports.getUsers= () => { var params = { UserPoolId: USER_POOL_ID AttributesToGet: [ 'ATTRIBUTE_NAME', ], }; return new Promise((resolve, reject) => { AWS.config.update({ region: USER_POOL_REGION, 'accessKeyId': AWS_ACCESS_KEY_ID, 'secretAccessKey': AWS_SECRET_KEY }); var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider(); cognitoidentityserviceprovider.listUsers(params, (err, data) => { if (err) { console.log(err); reject(err) } else { console.log("data", data); resolve(data) } }) }); }
How would I implement this in React?
the above code will work in react but you should not use it ina public facing app because your AWS keys will be exposed in the source code
Why not adding this much requested feature as an amplify lambda template that could be deployed with the CLI ?
Any new on this? I believe this's a very common need...
We are working on a feature for this that is in PR here: https://github.com/aws-amplify/amplify-cli/pull/2443
When this releases you'll have an API that you can call from your app and perform Cognito Admin actions, such as listing all users in the User Pool. You'll also be able to restrict it down to specific Groups in the User Pool, and assign fine grained IAM permissions to those Groups if you wish.
Great news, those features are really needed here.
Could REALLY use this feature... like right now. lol Any update on the Pull Request?
This is my Lambda function for solving this problem, delivering a complete user list. It has some assumptions, like one role per user and a known set of group names. It handles where there might be more than 60 users in a particular group. I don't know what would happen with tens of thousands of users.
import AWS from "aws-sdk";
import { success, failure } from "Libs/response-lib";
export async function main(event, context) {
const cognito = new AWS.CognitoIdentityServiceProvider();
try {
let users = [];
let roles = ['admin', 'user', 'viewer'];
for (let i=0, len=roles.length; i<len; i++) {
const role = roles[i];
let more = true;
let nextToken = '';
while (more) {
let params = {
UserPoolId: process.env.userPoolId,
GroupName: role,
Limit: 60
}
if (nextToken !== '') {
params.NextToken = nextToken;
}
const rawUsers = await cognito.listUsersInGroup(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 = Array.concat(users, mapUsers);
if (rawUsers.hasOwnProperty('NextToken')) {
nextToken = rawUsers.NextToken;
} else {
more = false;
}
}
users.sort((a,b) => (a.name.localeCompare(b.name)));
}
return success(users);
} catch (e) {
console.log(e);
return failure({ status: false, error: e });
}
}
to be honest, what I would really like here is for Cognito interaction to be exposed through GraphQL... and if amplify could handle all of the queries, mutations, lambda functions, etc, that would be great!
I'm sure there are plenty of people that are probably struggling with this so I'm posting what I'm using with React to create my admin table. Note that I don't include the code for the actual table as that is beyond the scope. The code below will get you an array of user objects that can easily be mapped over with BootstrapTable or MDBootstrap table.
import React, { useState, useEffect } from 'react';
import AWS from 'aws-sdk';
const UserList = () => {
const [users, setUsers] = useState([]);
const getUsers = async () => {
try {
let allUsers = [];
let more = true;
let paginationToken = '';
while (more) {
let params = {
UserPoolId: process.env.REACT_APP_USER_POOL_ID,
Limit: 60
};
if (paginationToken !== '') {
params.PaginationToken = paginationToken;
}
AWS.config.update({
region: process.env.REACT_APP_USER_POOL_REGION,
accessKeyId: process.env.REACT_APP_ACCESS_KEY_ID,
secretAccessKey: process.env.REACT_APP_SECRET_KEY
});
const cognito = new AWS.CognitoIdentityServiceProvider();
const rawUsers = await cognito.listUsers(params).promise();
allUsers = allUsers.concat(rawUsers.Users);
console.log(allUsers);
if (rawUsers.PaginationToken) {
paginationToken = rawUsers.PaginationToken;
} else {
more = false;
}
}
setUsers(allUsers);
} catch (e) {
console.log(e);
}
};
useEffect(() => {
getUsers();
}, []);
Huge thanks to @AaronOverton for posting his Lambda function.
Any updates respectively a date, when this feature will be implemented?
you can pass in your cognito token to your config options.
I'm pretty sure you can get it from amplify
import { Auth } from 'aws-amplify';
// Auth.currentAuthenticatedUser() should return an object with a token somewhere inside
@sbussard The accessKeyId and secretAccessKey are being passed in as environmental variables in Amplify.
currentAuthenticatedUser does not solve this issue.
Could really do with a nice simple amplify listUsers()
function right about now. Wondering if there is any update on this feature making it into amplify?
I am building an app with Quasar and haven't yet had to use aws-sdk. Looks like I might need it to implement one of the above workarounds!
This functionality was released last year but the issue wasn't closed. You can find Admin operations and sample app code here:
https://docs.amplify.aws/cli/auth/admin#admin-queries-api
Most helpful comment
I'm sure there are plenty of people that are probably struggling with this so I'm posting what I'm using with React to create my admin table. Note that I don't include the code for the actual table as that is beyond the scope. The code below will get you an array of user objects that can easily be mapped over with BootstrapTable or MDBootstrap table.
Huge thanks to @AaronOverton for posting his Lambda function.