aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

How to add user to Group #1213

Closed davidgatti closed 5 years ago

davidgatti commented 6 years ago

I went over the README.md, and I don't see a way to singUp a user and attach this user to a group. Could someone update the README explaining how to go about this, or provide a link to a full documentation.

powerful23 commented 6 years ago

For now Amplify doesn't support this feature. Mark as feature request.

davidgatti commented 6 years ago

o_O What? then what that feature exists in the dashboard?

powerful23 commented 6 years ago

Can you give me a link about what you are looking at?

davidgatti commented 6 years ago

screen shot 2018-07-11 at 8 40 13 pm

powerful23 commented 6 years ago

@davidgatti the AWS Cognito has this feature but our client side js library hasn't implemented the corresponding API yet.

davidgatti commented 6 years ago

Hmmm :D hmmm :D how to say this... you got the order backwards. I think there is no much use doing it by hand in production ;)

I love you AWS 😙❤️

powerful23 commented 6 years ago

@davidgatti thanks! We will have this in our backlog and hopefully bring it out ASAP.

alexchro93 commented 6 years ago

I agree that it would be nice to specify a group for the user during sign up. That being said, is there any way to programmatically add a user to a group?

undefobj commented 6 years ago

@davidgatti @alexchro93 how would you imagine the approval for a user to be added to a group working for a feature like this? I agree with the point around not wanting to necessarily do this by hand, however just opening up a feature in Amplify, which is designed for client side programming, that interacts with Admin APIs has potential security implications that must be evaluated.

For example, if an Admin is needed to add a user to a group (like it is today with Cognito) and a user is to be added to a group when they sign up, but that user isn't an Admin then just arbitrarily adding them to a group could introduce a security hole. Would you be looking to introduce some sort of post registration rules validation based on the user and a lookup in a database table? Or would you want a "pending" status of some sort for Admin approval?

There's workflow in this process that needs to be evaluated and designed. This could potentially be done via Lambda post-signup triggers that we could help automate, but better understanding your requirements and use cases would help us in the request.

davidgatti commented 6 years ago

@undefobj Hmm, lets maybe start to see what groups actually are and what are their purpose. To me a group is just a way to organize different groups of people. So then based on that I can for example show a different image.

But it seams that in this case groups here are more like groups in IAM, where policies get attached to those groups which then allow access to AWS resources, in this case, I would do it similarly to how identity Pools work? You allow a unauthorized access to a group, but what if you have 2 groups and depending on the "registration" page you ether go in to one drop or the other, how do you force the user in the front to one group.

Hmm... so yes, what is the exact purpose of groups from your perspective, and how should they be used?

alexchro93 commented 6 years ago

@undefobj is the security hole that, given amplify is designed for client side programming, introducing the ability to specify a group during sign up would allow someone to modify code such that they are added to the incorrect group? For example, I'd like all people who sign up on my website to be added to a generic free_users group. If i also have a group for paying_users, someone could easily modify my client side code so that they are added to the paying_users group.

Given the above, I'm now leaning towards some post-signup hook for programmatic adding of users to groups. I don't need/want admin approval before adding users to this default group, as it's part of my application's design.

undefobj commented 6 years ago

@alexchro93 it's not so much around code modification or a "hole" but rather a chicken vs egg question. Suppose you have groups of "Editors" and "Authors" in your CMS app with Amplify, and when signing up customers can specify the group to be added. What if they specify "Editors"? I would imagine you'd want an approval process of sorts to add them or a check on their email, etc., from a database. So to your point yes you might want some sort of a post-signing hook like the Lambda triggers in Cognito to do this.

Now that's not to say we (AWS) cannot help make this easier for you in both Amplify as well as our related tooling. That's why I'm asking yourself and @davidgatti what type of use cases/requirements you might be looking for rather than the implementation, so that we can work backwards from that.

davidgatti commented 6 years ago

So if your concern is not people editing JS on the browser and (since they can just select a different option in the drop down for example), your asking if we as developers that will use this feature will care for epople to just select be saved and be done or if you'd like an extra step for an admin to double check if the right person is in the right group.

If this is the case I'd be happy with a post group add event, where I can react, make a URL, and send it to an admin for him or her to click to confirm. Either on our custom page, or in AWS Dashboard.

But I also would like to have an option to select that "this" groups are public, and I don't want to confirm anything. The user is free to join whichever group, they will just have access to different resources.

I hope this makes sense.

alexchro93 commented 6 years ago

Thanks @undefobj for the explanationj. My use case is fairly straightforward - Upon signing up, depending on the client used, I'd be looking to add users to a default group, call it generic_users_mobile or generic_users_desktop. Originally, I thought it made the most sense to specify the group to which a user belongs during sign up.

In my application, the group you're in dictates the APIs to which you have access. As you begin paying for features, for example, you'd be placed in a different group. Those users who strictly use the mobile version of the application would have access to different APIs than those who strictly use the browser version of the application.

undefobj commented 6 years ago

Great this is helpful for us. We're still working on things in the backlog, but we have this on the roadmap that will be made easier with some new tooling that we're releasing soon. What you outline is a bit more than just the Amplify library, so we'll incorporate this with some future plans. In the meantime we'll keep this issue open for others to comment with use cases as well.

davidgatti commented 6 years ago

Part of this functionality could be in the regular AWS-SDK, to add people in the admin group in a programmatic way, and then the rest in this SDK? :)

mayteio commented 5 years ago

👆

Also, we have achieved this using the Post Confirmation Lambda trigger.

Very simplified from our implementation, however, here's the general gist:

export function afterConfirmationTrigger(event, context, callback) {
  const params = {
    GroupName: "Owners",
    UserPoolId: event.userPoolId,
    Username: event.userName
  };

  CognitoIdentityServiceProvider.adminAddUserToGroup(params)
    .promise()
    .then(res => callback(null, event))
    .catch(err => callback(err, event));
}

It's important your Lambda has an IAM policy that specifies Allow cognito-idp:AdminAddUserToGroup too.

davidgatti commented 5 years ago

Wait!, so there is an API for working with groups o_O. In this case this is OK with me :D

mayteio commented 5 years ago

There is. Not intuitive at all, from docs either. But it's all good - aws is a spaghetti - beautiful spaghetti.

On Thu, 25 Oct 2018 at 7:16 pm, David Gatti notifications@github.com wrote:

Wait!, so there is an API for working with groups o_O. In this case this is OK with me :D

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/aws-amplify/amplify-js/issues/1213#issuecomment-432957358, or mute the thread https://github.com/notifications/unsubscribe-auth/Ap8BtANwZc7ALSf5YhLU-Ep2st8ZCOQqks5uoXNdgaJpZM4VL1Ay .

--

Cheers

Harley Alexander Head of digital 0422 808 381 - LinkedIn https://www.linkedin.com/in/harleytalexander/

davidgatti commented 5 years ago

Amazing, thank you @mayteio!

flowirtz commented 5 years ago

I don't think this issue should be closed as it still is a valid feature request and the solution provided by @mayteio is more a workaround and not using Amplify directly.

KhaledSoliman commented 5 years ago

I think a post signup trigger is a very good idea, would allow us to let users define their role on signup too, currently our users have to signup, confirm, login and then choose whether they want to be a client or a company.

undefobj commented 5 years ago

@KhaledSoliman @FWirtz @davidgatti @mayteio @alexchro93 please see the following RFC for some new enhancements we are looking to add which may address this use case: https://github.com/aws-amplify/amplify-cli/issues/766

rfdc commented 5 years ago

Is this feature supported yet?

If not, how do we deal with groups on API?

type Salary @model @auth(rules: [{allow: groups, groups: ["Admin"]}]) {
  id: ID!
  wage: Int
  currency: String
}

Thanks

gl2748 commented 5 years ago

@rfdc depends on the API you are using, but in AppSync you can use resolvers to filter by the group in the identity context per: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html

CodySwannGT commented 5 years ago

As stated above, you need to add the appropriate policy permissions to the auth role created by Amplify, but then you can do this:

import CognitoIdentityServiceProvider from 'aws-sdk/clients/cognitoidentityserviceprovider';
import { Auth } from 'aws-amplify';

Promise.resolve(Auth.currentAuthenticatedUser())
.then(user =>
  Auth.currentCredentials()
      .then(credentials =>
        Promise.resolve(
          new CognitoIdentityServiceProvider({
            apiVersion: '2016-04-18',
            credentials: Auth.essentialCredentials(credentials),
            region: "us-east-1"
          })
        )
      )
      .then(client =>
        client.adminAddUserToGroup({
          GroupName: "Admins",
          UserPoolId: user.pool.userPoolId,
          Username: user.username
        })
        .promise()  
      )
)
Muhammad-Soban commented 5 years ago
import * as AWS from 'aws-sdk';
import CognitoIdentityServiceProvider from 'aws-sdk/clients/cognitoidentityserviceprovider';

const addUserToGroup = (name, username) => {
  AWS.config.region = process.env.REGION;
  const cognitoIdentityServiceProvider = new CognitoIdentityServiceProvider();
  const params = {
    GroupName: name,
    UserPoolId: process.env.USER_POOL_ID,
    Username: username,
  };

  return cognitoIdentityServiceProvider.adminAddUserToGroup(params).promise();
};
ravnarayan commented 5 years ago

Tried using link: https://github.com/notifications/unsubscribe-auth/Ap8BtANwZc7ALSf5YhLU-Ep2st8ZCOQqks5uoXNdgaJpZM4VL1Ay

But does not work.

Also, can’t we just run “amplify add auth”, once created in Cognito dash, go in and customize, including adding group to amplify created user pool, along with a manual api gateway with authorizer? Would this work?

buixuanhai commented 4 years ago

This looks useful: https://aws.amazon.com/blogs/mobile/amplify-cli-enables-creating-amazon-cognito-user-pool-groups-configuring-fine-grained-permissions-on-groups-and-adding-user-management-capabilities-to-applications/

secretshardul commented 4 years ago

Amplify CLI now has an official way to add users to groups. Like @MainAero's answer Amplify performs this using a post-confirmation Lambda trigger.

hp% amplify auth update
 What do you want to do? Walkthrough all the auth configuration
? Do you want to configure Lambda Triggers for Cognito? Yes
? Which triggers do you want to enable for Cognito Post Confirmation
? What functionality do you want to use for Post Confirmation Add User To Group
? Enter the name of the group to which users will be added. Advertiser

Here's the generated Lambda code

/* eslint-disable-line */ const aws = require('aws-sdk');

exports.handler = async (event, context, callback) => {
  const cognitoidentityserviceprovider = new aws.CognitoIdentityServiceProvider({ apiVersion: '2016-04-18' });
  const groupParams = {
    GroupName: process.env.GROUP,
    UserPoolId: event.userPoolId,
  };

  const addUserParams = {
    GroupName: process.env.GROUP,
    UserPoolId: event.userPoolId,
    Username: event.userName,
  };

  try {
    await cognitoidentityserviceprovider.getGroup(groupParams).promise();
  } catch (e) {
    await cognitoidentityserviceprovider.createGroup(groupParams).promise();
  }

  try {
    await cognitoidentityserviceprovider.adminAddUserToGroup(addUserParams).promise();
    callback(null, event);
  } catch (e) {
    callback(e);
  }
};
Huetarded commented 4 years ago

@secretshardul Yes, I am using this and it works great at adding users to whichever group you'd like after they are verified.

However, I would add that there is a bit of a bug present when using this feature. The file that is created by Amplify is called "add-to-group.js", but the handler for that function that gets assigned in AWS is "index.handler". So, upon first push, I have found that I need to log into the console and fix the handler reference (change to "add-to-group.handler") before it will function correctly.

It would be great if Amplify would either name the file "index.js" or assign the correct handler to it when pushing the resources to AWS.

amplify-add-to-group-bug

secretshardul commented 4 years ago

@Huetarded at the time of writing this issue(#4475) seems to be fixed. Here's the Lambda function code

image

/*
  this file will loop through all js modules which are uploaded to the lambda resource,
  provided that the file names (without extension) are included in the "MODULES" env variable.
  "MODULES" is a comma-delimmited string.
*/

exports.handler = (event, context, callback) => {
  const modules = process.env.MODULES.split(',');
  for (let i = 0; i < modules.length; i += 1) {
    const { handler } = require(`./${modules[i]}`);
    handler(event, context, callback);
  }
};

image

The handler in index.js is invoked first. It calls add-to-group.js by looping through the modules environment variable.

image

Somtozech commented 4 years ago

Is there a way one can specify the group they want to add the user. All the examples am seeing are expecting you to add a user to a particular group pre-specified in the environment variables. How do I solve a use case where a user can be added to any of 3 groups eg manager, clerk, and customer at signup?.

Huetarded commented 4 years ago

@Somtozech - Assuming you are using the Auth classes to signup your users, you can take advantage of the "clientMetadata" property of the "SignUpParams" object to pass along additional information during the signup process. This data will get passed along to your Lambda function where you can put users in the correct group based on that data.

https://aws-amplify.github.io/amplify-js/api/classes/authclass.html#signup

Huetarded commented 4 years ago

@secretshardul - Yes, I'm seeing that it's fixed now as well. I just tried it the other day and I'm now seeing the same file structure you illustrated above!

duncangroenewald commented 3 years ago

Is there a way to setup the Cognito User Pool groups in AWS Amplify, prior to using this to setup the automatic allocation of the user to a group ?

Hmm ok I see in the script above there is an option for doing this but the script is not prompting for a group when I add the Lambda to do the Post Confirmation Add User to Group.

Also how can I just update the existing User Pool - when I run amplify auth update near the end of the script it tells me it will replace the existing user pool ? How can I just add features to the existing one ?

undefobj commented 3 years ago

Take a look at the following to add Group functionality to your apps: https://docs.amplify.aws/cli/auth/groups https://docs.amplify.aws/cli/auth/admin

nickfreemandesign commented 3 years ago

For anyone else going in circles on this, keep in mind that CognitoIdentityServiceProvider makes HTTP request under the hood, meaning if you have some lambda running this then your lambda needs access to the internet to make it happen. NAT Gateways allow you to achieve this but at a cost of like 30 bones per month

rajkinkhabwala commented 2 years ago

I am still not able to add a user to a group while the user is registering. I don't know it keeps showing me that user group exists. I tried the solutions mentioned in the above comments but non of them are working.

github-actions[bot] commented 1 year ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.