Reputation: 3137
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;
Upvotes: 14
Views: 14542
Reputation: 786
Anyone wondering how to run @honkskillet 's code in node 18+, below is the one I used. Which is of course based on his answer. All the permission configuration mentioned in his answer is still valid. (https://stackoverflow.com/a/50003946/6686446)
const { CognitoIdentityProviderClient, AdminAddUserToGroupCommand } = require("@aws-sdk/client-cognito-identity-provider"); // CommonJS import
exports.handler = async (event, context, callback) => {
var client = new CognitoIdentityProviderClient();
var params = {
GroupName: 'clients', //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")
}
try {
const command = new AdminAddUserToGroupCommand(params);
const response = await client.send(command);
callback(null, event); // successful response
} catch (err) {
callback(err) // an error occurred
}
};
and install @aws-sdk/client-cognito-identity-provider": "^3.462.0
Upvotes: 0
Reputation: 51
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
Upvotes: 5
Reputation: 106
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/
Upvotes: 0
Reputation: 3137
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": "*"
}
]
}
Upvotes: 24
Reputation: 2553
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.
Upvotes: 7