13

I am using AWS Amplify library to sign up and perform Auth for an AppSync project. This uses Cognito. However, when a new user signs up via Amplify/Cognito, the new user isn't assigned to any specific group in the cognito pool. I am using the Amplify higher order component for login/signup.

import { withAuthenticator } from 'aws-amplify-react';

which I wrap over a component

class Authenticator extends React.Component {
   //... basically empty component, only exists so I can wrap it w/ the HOC
}
export default withAuthenticator(Authenticator)

Amplify is set up in index.js

import config from './aws-exports';
import Amplify from 'aws-amplify';
Amplify.configure(config);

aws-exports.js was autogenerated by AWS Mobile Hub CLI. Looks like...

const awsmobile = {
    'aws_app_analytics': 'enable',
    'aws_cognito_identity_pool_id': 'us-west-2:XXX',
    'aws_cognito_region': 'us-west-2',
    'aws_content_delivery': 'enable',
    'aws_content_delivery_bucket': 'flashcards-hosting-mobilehub-XXX',
    'aws_content_delivery_bucket_region': 'us-west-2',
    'aws_content_delivery_cloudfront': 'enable',
    'aws_content_delivery_cloudfront_domain': 'XXX.cloudfront.net',
    'aws_mandatory_sign_in': 'enable',
    'aws_mobile_analytics_app_id': 'XXX',
    'aws_mobile_analytics_app_region': 'us-east-1',
    'aws_project_id': 'XXX',
    'aws_project_name': 'flash-cards',
    'aws_project_region': 'us-west-2',
    'aws_resource_name_prefix': 'flashcards-mobilehub-XXX',
    'aws_sign_in_enabled': 'enable',
    'aws_user_pools': 'enable',
    'aws_user_pools_id': 'us-west-2_XXX',
    'aws_user_pools_mfa_type': 'OFF',
    'aws_user_pools_web_client_id': 'XXX',
}
export default awsmobile;
honkskillet
  • 3,007
  • 6
  • 31
  • 47

4 Answers4

23

I got it working. As mentioned by Vladamir in the comments this needs to be done server side, in a Post Confirmation lambda trigger. Here is the lambda function.

'use strict';
var AWS = require('aws-sdk');
module.exports.addUserToGroup = (event, context, callback) => {
  // console.log("howdy!",event);
  var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
  var params = {
    GroupName: 'users', //The name of the group in you cognito user pool that you want to add the user to
    UserPoolId: event.userPoolId, 
    Username: event.userName 
  };
  //some minimal checks to make sure the user was properly confirmed
  if(! (event.request.userAttributes["cognito:user_status"]==="CONFIRMED" && event.request.userAttributes.email_verified==="true") )
    callback("User was not properly confirmed and/or email not verified")
  cognitoidentityserviceprovider.adminAddUserToGroup(params, function(err, data) {
    if (err) {
      callback(err) // an error occurred
    }
    callback(null, event);           // successful response
  });  
};

You will also have to set the policy for the lambda function role. In the IAM console, find the role for this lambda and added this inline policy. This give the lambda the keys to the castle for everything cognito so make yours more restrictive.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cognito-identity:*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cognito-sync:*"
            ],
            "Resource": "*"
        },
        { //this might be the only one you really need
            "Effect": "Allow",
            "Action": [
                "cognito-idp:*"
            ],
            "Resource": "*"
        }
    ]
}
honkskillet
  • 3,007
  • 6
  • 31
  • 47
  • 1
    Hi, how do you point to that lambda function? In Federated Identities, under Facebook, Cognito Events -> Sync Trigger? I did this, but the lambda function never triggered. – Ahmet Cetin Nov 04 '18 at 20:26
  • Thank you for sharing! Have not added federated yet, but for user pools it is in fact as easy as adding the lambda function, selecting it in cognito triggers, adding the role policy (the statement you commented was enough). Signed up a new user, boom – working. – tobiv Dec 15 '18 at 17:33
7

Cognito won't know which group a newly signed-up user needs to be a part of. You have to programmatically (or manually) assign the user to a specific group. Once your code places the user into a specific group, the JWT ID token will contain a list of all of the relevant groups/IAM roles that this users is a part of.

More info on groups here.

Vladimir
  • 2,481
  • 4
  • 31
  • 41
  • 1
    btw, you can use a Post confirmation Lambda hook to "automatically" add the user to a Cognito group, but you'll need to write the code and make sure you understand what the logic is behind which users go into which group. – Vladimir Apr 23 '18 at 16:02
  • 1
    How do you programmatically set the group? – honkskillet Apr 23 '18 at 17:22
  • 1
    I don't see how to do it is the Amplify Auth docs https://aws.github.io/aws-amplify/api/classes/authclass.html – honkskillet Apr 23 '18 at 17:27
  • 1
    This isn't something you can achieve via Amplify. As Vladimir mentioned you can configure a Post Confirmation lambda trigger for your user pool and call the ListGroups and AdminAddUserToGroup Cognito UserPool APIs to achieve that https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-lambda-trigger-syntax-post-confirmation.html – Ionut Trestian Apr 23 '18 at 22:31
  • Got it. I'll try to hook it up tomorrow. – honkskillet Apr 24 '18 at 00:20
  • Started on this by adding a Post Confirmation trigger lambda function. Currently, no matter what I do inside the lambda I get the error "Unrecognizable lambda output", which is strange because I don't think cognito is expecting any response. What should my lambda function return? – honkskillet Apr 24 '18 at 03:40
  • 1
    Here's a bunch of samples for you: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-lambda-trigger-examples.html – Vladimir Apr 24 '18 at 04:36
  • 1
    Great. Accept my answer when you have a chance then ;) – Vladimir Apr 24 '18 at 14:48
5

AWS Amplify has added support for adding users to groups using amplify cli. Details are given here https://aws.amazon.com/blogs/mobile/amplify-framework-adds-supports-for-aws-lambda-triggers-in-auth-and-storage-categories/

Also this article explains bit more details https://medium.com/@dantasfiles/multi-tenant-aws-amplify-method-2-cognito-groups-38b40ace2e9e

Passing group name from client side to you lamda function you can use Post Confirmation Lambda Trigger Parameter clientMetadata object like below.

  await Auth.signUp({
          username: this.email,
          password: this.password,
          attributes: {
            given_name: this.firstname,
            family_name: this.lastname
          },
          clientMetadata: {
            key: value
          }
        })

If you are using ready made amplify auth UI then you need to customize withAuthenticator component and write your own component for signup or preferrable ConfirmSignUp (plz check if you can pass clientMetadata from there)

Within lamda function you can get passed group name like this

event.request.clientMetadata.groupName
WEBDEV
  • 51
  • 1
  • 2
0

You must first add admin queries using amplify cli, running amplify update auth, after that you must block admin queries only for admin users, you will see the output code in amplify/backend/function/

and after you push your changes, you can use:

async function addToGroup() { 
    let apiName = 'AdminQueries';
    let path = '/addUserToGroup';
    let myInit = {
        body: {
          "username" : "username",
          "groupname": "groupname"
        }, 
        headers: {
          'Content-Type' : 'application/json',
          Authorization: `${(await Auth.currentSession()).getAccessToken().getJwtToken()}`
        } 
    }
    return await API.post(apiName, path, myInit);
}

In order to add a user to role using amplify, check for user id's in case of sign up with just email. Documentation of this change in amplify is availible here https://aws.amazon.com/es/blogs/mobile/amplify-framework-adds-supports-for-aws-lambda-triggers-in-auth-and-storage-categories/

MartenCatcher
  • 2,713
  • 8
  • 26
  • 39