Create cognito admin user on server - amazon-web-services

I am using aws cognito for authenticating and on backend side I need something like admin account to connect with cognito and check user attributes. I found that code below should works, but I got user is not authorized to perform not authorized to perform on ...
How can I create user with such privileges ?
`
let cisp = new AWS.CognitoIdentityServiceProvider()
var params = {
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId: appConfig.ClientId,
UserPoolId: appConfig.UserPoolId,
AuthParameters: {
USERNAME: xxxxxxxxxxxxxxxxx,
PASSWORD: yyyyyyyyyyyyyyyyy
}
}
cisp.adminInitiateAuth(params, (err, data) => {
...
}
`

You can use the AWS cognito SDK and call the following method to get information about the identity.
describeIdentity(params = {}, callback) ⇒ AWS.Request
If your code runs in AWS EC2, ECS or Lambda, you can attach a IAM role that has access to Cognito so that you code can access the Cognito API through SDK.
Else you need to create a IAM user with Cognito permissions and use AccessKey and Secret to authenticate the SDK API calls impersonating the user.

Related

How can I attach an IoT Core policy to a Cognito Identity Id on a post authentication Lambda trigger for an Amplify deployed web application?

Situation:
I have a ReactJS web application that is deployed through AWS Amplify and uses Amplify Studio backend to handle authentication through Cognito services and aws-amplify sdk (sign in, sign up).
The web application also implements the use of react native aws-amplify sdk pubsub to subscribe to an MQTT topic in IoT Core and retrieve messages but only to authenticated users.
As per step 2 in the pubsub documentation: Attach your policy to your Amazon Cognito Identity.
If I use the AWS CLI to attach the IoT policy to the user and then I sign in with that user through the web application I am able to successfully subscribe and receive MQTT messages -- it works perectly!
Problem:
The application allows Cognito self-service user sign up (Self-registration) and expects to have many users.
I implemented a post authentication lambda trigger function in the Cognito user pool created by the Amplify service.
The lambda function runs the following sample from AWS documentation with two (2) additional console logs:
exports.handler = (event, context, callback) => {
// Send post authentication data to Cloudwatch logs
console.log ("Authentication successful");
console.log ("Trigger function =", event.triggerSource);
console.log ("User pool = ", event.userPoolId);
console.log ("App client ID = ", event.callerContext.clientId);
console.log ("User ID = ", event.userName);
*** console.log("Event = ", event);
console.log("Context = ", context);***
// Return to Amazon Cognito
callback(null, event);
};
I then authenticate with the user again through the application and go to CloudWatch logs for that Lambda function.
This is the information I get from logging Event and Context after post authentication trigger:
Event log:
{
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_*********',
userName: '4eea4a48-92b6-45da-b26e-*********',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: '*********'
},
triggerSource: 'PostAuthentication_Authentication',
request: {
userAttributes: {
sub: '4eea4a48-92b6-45da-b26e-*********',
'cognito:email_alias': '*********.com',
'cognito:user_status': 'CONFIRMED',
email_verified: 'true',
name: 'asdfasdf',
email: '*********.com'
},
newDeviceUsed: false
},
response: {}
}
Context log:
{
callbackWaitsForEmptyEventLoop: [Getter/Setter],
succeed: [Function (anonymous)],
fail: [Function (anonymous)],
done: [Function (anonymous)],
functionVersion: '$LATEST',
functionName: 'userAccess_iotCore_attachPolicyToCognitoIdentityID',
memoryLimitInMB: '128',
logGroupName: '/aws/lambda/userAccess_iotCore_attachPolicyToCognitoIdentityID',
logStreamName: '2023/01/13/[$LATEST]4eb4287aa4db4dd8a6b6efd810a7***',
clientContext: undefined,
identity: undefined,
invokedFunctionArn: 'arn:aws:lambda:us-east-1:*********:function:userAccess_iotCore_attachPolicyToCognitoIdentityID',
awsRequestId: 'bf6afd1c-117c-4a9e-9d3b-*********',
getRemainingTimeInMillis: [Function: getRemainingTimeInMillis]
}
The big issue here is that context.identity is undefined so I am not able to get that authenticated user's Amazon Cognito Identity Id to attach the required IoT policy for PubSub to work through the application.
Questions:
How can I get the Amazon Cognito Identity Id after post authentication trigger to then attach an IoT policy?
From the web application using the aws-amplify sdk I am able to get this Id after sign in. Is there any API I can use from the application to attach this policy?
Thanks.

Not getting correct permission as per defined in scope in oAuth2 access token when trying to sign in using google

I am trying to sign in with google using AWS Cognito federation inside the user pool. My main goal is to get an access token and refresh token to call Google APIs on my server. I added the required scope and got permission as well, but the access token I am getting is not containing that extra permission in my case that's google calendar, and when I am trying to access calendar API getting a 401 Unauthorized error even.
I used Amplify library on React side to request tokens.
Amplify config:
Amplify.configure({
Auth: {
// REQUIRED - Amazon Cognito Region
region: 'us-east-2',
// OPTIONAL - Amazon Cognito User Pool ID
userPoolId: 'us-east-2_xxxxxxx',
// OPTIONAL - Amazon Cognito Web Client ID (26-char alphanumeric string)
userPoolWebClientId: 'xxxxxxxxxxxxxxxxxx',
// OPTIONAL - Hosted UI configuration
oauth: {
domain: 'calendar-google.auth.us-east-2.amazoncognito.com',
scope: [
'phone',
'email',
'profile',
'openid',
'aws.cognito.signin.user.admin',
],
redirectSignIn: 'http://localhost:3000/',
redirectSignOut: 'http://localhost:3000/',
responseType: 'code',
},
},
});
Scope used in cognito config
profile email openid https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/calendar
enter image description here

AWS cognito social login throwing NotAuthorizedException:does not have identity providers configured React Native

I'm using user pool. I have completed signup with email now trying to implement social login.
I'm using Auth.federatedSignIn({ provider: 'Google' }) for google and
Auth.federatedSignIn({ provider: 'Facebook' }) for facebook.
Here is my config for OAuth
oauth: {
domain: '__domain__',
clientID: '__client id __',
scope: ['email', 'profile', 'openid'],
redirectSignIn: 'myapp://oauth/',
redirectSignOut: 'myapp://signout/',
responseType: 'code'
}
I have added google, Facebook id and secret in aws.
But in the hub listener, I'm getting the following error.
signIn_failure [NotAuthorizedException: Identity pool - * poolid * does not
have identity providers configured.]
However, the users who tried login using facebook and google is registered and is showing in the user list.
I'm pretty much stuck at this point, any help would be appreciated.
I found out the issue, we had Identity pool setup added in the config, so I had to add the social login id's in the Identity pool id config setup in the AWS section.

aws-sdk 403 Error for CORS preflight OPTIONS request to Quicksight API

I'm trying to register a temporary quicksight user and generate an embed url to put in my React App. However, when calling the register user api I get a 403 error for the CORS preflight OPTIONS request:
Access to XMLHttpRequest at 'https://quicksight.ap-southeast-2.amazonaws.com/accounts//namespaces/default/users' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
I've also tried using us-east-1 as my region, but that also fails.
Users sign into my webapp with Cognito credentials. The identity pool has an associated IAM role, and I've attached a policy to that role giving access to register a new quicksight user and get the embed url. My webapp currently uses the aws-sdk library to assume the role through sts, and then make the subsequent quicksight calls.
The React app is hosted on Amplify
quicksightRegisterUser(data) {
var params = {
AwsAccountId: 'QQQ',
Email: 'XXX',
IdentityType: 'IAM' ,
Namespace: 'default',
UserRole: "READER",
IamArn: 'arn:aws:iam::YYY:role/ZZZ',
SessionName: 'XXX',
UserName:'XXX'
};
var quicksight = new QuickSight();
quicksight.registerUser(params, function (err, data1) {
if (err) {
console.log("err register user");
console.log(err);
} // an error occurred
else {
console.log("Register User1");
console.log(data1)
}
})
}
As #sideshowbarker mentioned, you can't call the Quicksight API from your webapp.
The solution I found was to set-up a Lambda to generate the Embedding URL, given the user's Cognito Username and password.
Full details of the solution, and a step-by-step tutorial, can be found here:
https://github.com/aws-samples/amazon-quicksight-embedding-sample

Cognito Groups with IAM Permissions

What I want to implement:
I have a Cognito User-Pool and I have some Users and some Groups. I want that certain Users have access to API Gateway functions, some Users can access some functions and others have no access.
What I did:
I created three groups and assigned the Users to each of the groups. I gave each of the groups an IAM role and gave each roled spezific policies. The permission for the group for all users looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "execute-api:*",
"Resource": "*"
}
]
}
I created Lambda functions and API Gateway Resources through the Serverless framework. I set the authorizer to a Cognito User-Pool authorizer.
(I tried a couple different things like using federated identities but that didnt seem to work as well)
What is my result:
All Users have full access to the API Gateway. The given permissions do not seem to make any difference to the access of each user.
Help:
What did I do wrong?
How can I achieve my goal?
The roles attached to a user pool group only come into picture when you generate credentials for the user using Cognito Federated Identity. Adding groups to a user pool
IAM roles and their permissions are tied to the temporary AWS
credentials that Amazon Cognito identity pools provide for
authenticated users. Users in a group are automatically assigned the
IAM role for the group when AWS credentials are provided by Amazon
Cognito Federated Identities using the Choose role from token option.
So basically
create an identity pool attached to your user pool.
change authorization for API gateway to IAM
after login to user pool, user id_token to generate the federated identity
use this identity (secret key + access key + token) for authorization with API gateway.
Now your roles should be honored. But mind you - you will be required to generate AWS SigV4 credentials on your own as for some reason this is not provided out of the box. I ended up using aws-sign-web for use in browser.
PS: your role seems to give blanket access to API gateway. you will need to fix that as well. e.g. sample role I used to limit access to one API endpoint
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Resource": [
"arn:aws:execute-api:us-east-2:<aws account id>:<API id>/*/*/acc/*"
],
"Effect": "Allow"
}
]
}
Sample code to generate federated identity
function getAccessToken(idToken, idenPoolId, userPool) {
let region = idenPoolId.split(":")[0];
let provider = "cognito-idp." + region + ".amazonaws.com/" + userPool;
let login = {};
login[provider] = idToken;
// Add the User's Id Token to the Cognito credentials login map.
let credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: idenPoolId,
Logins: login
});
//call refresh method in order to authenticate user and get new temp credentials
credentials.get((error) => {
if (error) {
console.error(error);
//let response = {
// statusCode: 500,
// body: JSON.stringify(error)
//};
return null;
} else {
console.log('Successfully logged!');
console.log('AKI:'+ credentials.accessKeyId);
console.log('AKS:'+ credentials.secretAccessKey);
console.log('token:' + credentials.sessionToken);
let response = JSON.stringify({
'AKI': credentials.accessKeyId,
'AKS': credentials.secretAccessKey,
'token': credentials.sessionToken
});
return response;
}
});
}
I have a much better solution, and you don't need the IAM.
Simply save the pair of {username, serviceName} in a S3 or DB. So every time, you get the request for a service:
Check if the user is authorized (from Cognito).
Check if the user is authorized for the service (S3, MySQL, RDS, etc.).
Why I think it is better
Because adding/removing users from services, you don't need to login as an admin to IAM. And hopefully later on, you can create a dashboard for management.
Work Flow
UserA sends a request to your securityApi.
SecurityApi checks the token is authorized (user is valid or not).
If the UserA is valid, the securityApi, sends the username of the user (can get it from the payload of the token) and the service name to a DB, to see if the user has access to the user. For example for Mysql (use RDS for this):
SELECT username from ServiceX LIMIT 1 WHERE username = "xyz";
If the second or third steps passed the user is 1. valid user and 2. has the right to use the service. If the user is failed in step 2 or 3, the user is not authorized to use the service.