Cognito user group can not invoke API GW - amazon-web-services

I am new in AWS Cognito topic. I am using IaC - Pulumi Typescript for deployment to AWS.
the purpose is to create two users(user1 and user2) and and give access only one user to invoke API GW.
// Create a Cognito user pool
const userPool = new pulumiAws.cognito.UserPool('my-user-pool', {});
// Create a Cognito user pool client
const userPoolClient = new pulumiAws.cognito.UserPoolClient('user-pool-client', {
userPoolId: userPool.id,
explicitAuthFlows: ["USER_PASSWORD_AUTH"],
});
//Create the first user group
const group1 = new pulumiAws.cognito.UserGroup('group1',{
description: 'Group1',
userPoolId: userPool.id
})
//Create the second user group
const group2 = new pulumiAws.cognito.UserGroup('group2',{
description: 'Group2',
userPoolId: userPool.id,
})
//Create the first user
const user1 = new pulumiAws.cognito.User('user1',{
username: 'user1',
password: 'TestUser1!',
userPoolId: userPool.id,
})
//Create the second user
const user2 = new pulumiAws.cognito.User('user2',{
username: 'user2',
password: 'TestUser2!',
userPoolId: userPool.id
})
//Assign the user1 to the group
const user1GroupMembership = new pulumiAws.cognito.UserInGroup('user1-group-membership',{
groupName: group1.name,
userPoolId: userPool.id,
username: user1.username
})
//Assign the user2 to the group
const user2GroupMembership = new pulumiAws.cognito.UserInGroup('user2-group-membership',{
groupName: group2.name,
userPoolId: userPool.id,
username: user2.username
})
const authorizer = new pulumiAws.apigateway.Authorizer("my-authorizer", {
restApi: api.id,
type: "COGNITO_USER_POOLS",
identitySource: "method.request.header.Authorization",
providerArns: [userPool.arn],
});
const method = new pulumiAws.apigateway.Method('method', {
authorization: 'COGNITO_USER_POOLS',
authorizerId: authorizer.id,
httpMethod: 'GET',
resourceId: resource.id,
restApi: api.id,
authorizationScopes: [user1GroupMembership.groupName],
});
Now I expect that the token which I created by using user1 credentials can be able to invoke API GW , but I get Unauthorized error.
On the other hand , if I remove authorizationScopes: [user1GroupMembership.groupName], from apigateway.Method(the code piece is in the above) then I can invoke the API GW via of course both user1 and user2 users.
Could you please give an idea how can give access only group1 or user1 to invoke API GW? what is wrong I am doing there.
Best Regards

I think that either user 1 or user 2 will be able to contact the Gateway API. However, you can set up an authorization mechanism with the implementation of a lambda authorizer which will be in charge of authorizing only the requests of the users of the group 1

Related

AWS Cognito Pre authentication get user data

I can't extract the username/password pair from the request.
2022-11-30T03:11:13.958Z xxxxxxxxxxxxxxxxxxxxx INFO{
version: '1',
region: 'xxxxxxxxx',
userPoolId: 'xxxxxxxxxxxxx',
userName: 'test',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxx'
},
triggerSource: 'PreAuthentication_Authentication',
request: { userAttributes: {}, validationData: null, userNotFound: true },
response: {}
}
Node script:
export const handler = async(event, context, callback) => {
console.log(event);
console.log(event.request);
console.log(context);
console.log(context.body);
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
Add all rights to Identity and Access Management (IAM), but unfortunately I can't see the password either, it's possible that it can't be extracted.
You (the AWS account user / role) cannot see, view, or extract the Cognito users' passwords ever, this is the purpose of Cognito as a service.
If you really want to do this you could do the signup outside of Cognito with your own system, then set the password manually for the user in Cognito with adminSetPassword.

How to make user attributes from AWS userpool updateable?

I am trying to update attributes from users from a AWS Cognito userpool with AWS Amplify.
try {
const user = await Auth.currentAuthenticatedUser();
await Auth.updateUserAttributes(user, {
'nickname': 'newtestname'
});
} catch (error) {
console.log(error);
}
But I get the following error:
InvalidParameterException: user.nickname: Attribute cannot be updated.
I would expect it to be updateable because I made the attributes writable in the userpool-client section in my SAM template:
WriteAttributes:
- email
- nickname
UserPoolId: !Ref MyCognitoUserPool
This is also reflected correctly in the console:
I have no app client secret and all auth flows enabled. The security configuration is set to enabled.
Users can register, so I assume that the Amplify config in the client is alright.
What is wrong here?
I found the issue. On creation of the userpool I had to set the mutable flag within the schema definition, like so:
Schema:
- Name: email
Mutable: true
...
- Name: nickname
Mutable: true
...
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html

AWS credentials with Identity pool

How can I pass the Cognito user's idToken to Amplify.configure() , cause the users have to be authenticated, not as a guest user. So Instead of getting an unauthenticated identityId, How do I get an authenticated Id by setting in the aws amplify configure.
For sign-in and sign-up we are not using Amplify instead we are using Rest API
Currently I'm sending Object to configure as follows,
{
Auth: {
identityPoolId: const.identityPoolId,
IdentityId: 'us-east-1:xxxxxxxxxxxxxxxxxxxyyyyyyzzzzzz',
region: 'us-east-1'
},
Analytics: {
disabled: false,
autoSessionRecord: true,
AWSPinpoint: {
appId: PinpointId,
region: 'us-east-1',
bufferSize: 1000,
flushInterval: 5000,
flushSize: 100,
resendLimit: 3
}
}
}
};
Any help is highly appreciated. Thanks

Getting `Cannot read property 'byteLength' of undefined` when accessing AppSync with AWS_IAM authentication type

I setup my backend using AWS Amplify, everything works using API_KEY but now I'm trying to use AWS_IAM but it's throwing me the error
I don't want to use AWS Cognito User pools because it won't allow unauth users to access my API
Amplify.configure({
API: {
"aws_project_region": "ap-southeast-1",
"aws_appsync_graphqlEndpoint": "endpoint",
// "aws_appsync_authenticationType": "API_KEY",
"aws_appsync_authenticationType": "AWS_IAM",
},
Auth: {
identityPoolId: process.env.REACT_APP_identityPoolId,
region: process.env.REACT_APP_awsRegion,
userPoolId: process.env.REACT_APP_userPoolId,
userPoolWebClientId: process.env.REACT_APP_userPoolAppClientId,
},
Storage: {
bucket: process.env.REACT_APP_bucketName,
region: process.env.REACT_APP_awsRegion,
identityPoolId: process.env.REACT_APP_identityPoolId
}
});

How to call AWS API Gateway Endpoint with Cognito Id (+configuration)?

I want to call an AWS API Gateway Endpoint that is protected with AWS_IAM using the generated JavaScript API SDK.
I have a Cognito UserPool and a Cognito Identity Pool. Both properly synced via ClientId.
I use this code to Sign in and get the Cognito Identity
AWS.config.region = 'us-east-1'; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:XXXXXXXXXXXXXXXXXXXXXXXX' // your identity pool id here
});
AWSCognito.config.region = 'us-east-1';
AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:XXXXXXXXXXXXXXXXXXXXXXXX' // your identity pool id here
});
var poolData = {
UserPoolId: 'us-east-1_XXXXXXXX',
ClientId: 'XXXXXXXXXXXXXXXXXXXXXXXX'
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var authenticationData = {
Username: 'user',
Password: '12345678',
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var userData = {
Username: 'user',
Pool: userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:XXXXXXXXXXXXXXXXXXXX',
IdentityId: AWS.config.credentials.identityId,
Logins: {
'cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXX': result.idToken.jwtToken
}
});
AWS.config.credentials.get(function (err) {
// now I'm using authenticated credentials
if(err)
{
console.log('error in autheticatig AWS'+err);
}
else
{
console.log(AWS.config.credentials.identityId);
}
});
},
onFailure: function (err) {
alert(err);
}
});
All this succeeds and I have an authorized Cognito Identity now.
Now I try to call the API Gateway Endpoint to execute the Lambda Function it points to.
var apigClient = apigClientFactory.newClient({
accessKey: AWS.config.credentials.accessKeyId, //'ACCESS_KEY',
secretKey: AWS.config.credentials.secretAccessKey, //'SECRET_KEY',
sessionToken: AWS.config.credentials.sessionToken, // 'SESSION_TOKEN', //OPTIONAL: If you are using temporary credentials you must include the session token
region: 'us-east-1' // OPTIONAL: The region where the API is deployed, by default this parameter is set to us-east-1
});
var params = {
// This is where any modeled request parameters should be added.
// The key is the parameter name, as it is defined in the API in API Gateway.
};
var body = {
// This is where you define the body of the request,
query: '{person {firstName lastName}}'
};
var additionalParams = {
// If there are any unmodeled query parameters or headers that must be
// sent with the request, add them here.
headers: {},
queryParams: {}
};
apigClient.graphqlPost(params, body, additionalParams)
.then(function (result) {
// Add success callback code here.
console.log(result);
}).catch(function (result) {
// Add error callback code here.
console.log(result);
});
But unfortunately this fails. The OPTIONS request succeeds with 200 but the POST then fails with 403.
I am pretty sure that there is no CORS problem here.
I am pretty sure the problem has to do with IAM Roles and AWS Resource Configurations.
My question is basically, can you please provide me with all the necessary AWS Resource Configurations and IAM Roles that are necessary for this to work please?
Resources I have are
API Gateway - with deployed API Endpoints
Lambda Function - called by the Endpoint
Cognito User Pool - with App synced to the Identity Pool
Cognito Identity Pool - with Authorized and Unauthorized Role mapped to it.
IAM Roles - for the Lambda Function and the Authorized and Unauthorized Role of the Cognito Identity Pool.
But I don't know how these Resources need to be configured properly to get this to work.
Thank you
What access permissions does the role of the Cognito Identity have? Make sure it has access to perform execute-api:Invoke on your API.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": [
"arn:aws:execute-api:us-east-1:<account>:<rest-api>/*/POST/graphql"
]
}
]
}
You can get the exact resource ARN from the method settings page in the web console.
Even after following everything I was getting the same error. And the reason was I missed the "sessionToken" while initialising the apigClient.
var apigClient = apigClientFactory.newClient({
accessKey: AWS.config.credentials.accessKeyId, //'ACCESS_KEY',
secretKey: AWS.config.credentials.secretAccessKey, //'SECRET_KEY',
sessionToken: AWS.config.credentials.sessionToken, // 'SESSION_TOKEN', //OPTIONAL: If you are using temporary credentials you must include the session token
region: 'us-east-1' // OPTIONAL: The region where the API is deployed, by default this parameter is set to us-east-1 });
//OPTIONAL: If you are using temporary credentials you must include the session token -- is not really optional