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
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/
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
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": "*"
}
]
}
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.