I'm having trouble implementing GetCallerIdentity with AWS within my application. When I try to generate temporary credentials, the server console returns the error InvalidClientTokenId: The security token included in the request is invalid.
I've been looking at the AWS documentation and I'm wondering if I've set up my IAM user incorrectly. The documentation says;
The temporary security credentials created by GetSessionToken can be used to make API calls to any AWS service with the following exceptions:
You cannot call any IAM APIs unless MFA authentication information is
included in the request.
You cannot call any STS API except AssumeRole or GetCallerIdentity.
Does this mean I can't use IAM accounts with the below example? I'm building in meteor js and I'm trying to implement a package called SlingShot. The documentation doesn't mention errors like this.
var sts = new AWS.STS();
sts.getSessionToken({
DurationSeconds: duration
}, function (error, result) {
console.log('error', error);
callback(error, result && result.Credentials);
});
Related
I'm trying to execute API calls from ReactNative AWS Amplify to API Gateway endpoint using AWS_IAM authorization.
I do it by calling (all Amplify initialization params are set):
import { API, Auth } from "aws-amplify";
...
API.get("MyApiName", "/resource")
.then(resp => { ... })
.catch(e => console.log(JSON.stringify(e));
I have console printout like:
{
"message":"Request failed with status code 403",
"name":"Error",
"stack": "...",
"headers":{
"Accept":"application/json, text/plain, */*",
"User-Agent":"aws-amplify/3.8.23 react-native",
"x-amz-date":"20210908T172556Z",
"X-Amz-Security-Token":"IQoJb3...",
"Authorization":"AWS4-HMAC-SHA256 Credential=ASIA23GCUWEDETN632PS/20210908/us-east-1/execute-api/aws4_request, SignedHeaders=host;user-agent;x-amz-date;x-amz-security-token, Signature=2a06fb4d8eb672164bfd736790fb1658edef1240d12a38afb599a9e33020c3cd"
...
}
So, it looks like the request is Signed!
I use Cognito User Pool and appropriate Identity Pool. They both are set properly, becuase these settings work with successfull authorization access to S3 storage using AWS Amplify S3.
Authenticated role for Cognito Identity Pool has permission to for ExecuteApi to invoke the API resource method. Also, it has permission to invoce the Lambda that is linked to the API's resource method.
All looks fine, but I am still getting the 403 Forbidden error.
What's missing here?
When calling Auth.currentUserCredentials() after Auth.signIn() I get valid valid credentials, but for an unauthenticated user, why?
Code:
async signIn({ dispatch, state }, { email, password }) {
try {
const user = await Auth.signIn(email, password);
console.log("User state after login")
const userCredentialsAfterLogin = await Auth.currentUserCredentials();
console.log(userCredentialsAfterLogin)
} catch (error) {
console.log("error")
console.log(error)
return
}
await dispatch('fetchUser')
},
Expected behaviour:
After signing in with a valid user, Auth.currentUserCredentials() should return an authenticated set of Credentials.
Actual behaviour:
Auth.currentUserCredentials() returns an unauthenticated user with the authenticated property set to false and a 400 error, "ResourceNotFoundException: IdentityPool 'eu-west-1:62dab5ed-5a84-4064-a7a2-87d1d0df511b'
System:
authenticationFlowType: "USER_SRP_AUTH"
Versions: "aws-amplify": "^3.3.14", "aws-amplify-vue": "^2.1.4", amplify version 4.42.0
config
{
"authSelections": "userPoolOnly",
"resourceName": "testapp89e81d50",
"serviceType": "imported",
"region": "eu-west-1"
}
I understand where you're coming from, and honestly I can't really show you clear documentation that exactly states why this won't work. AWS documentation on Cognito and Amplify is difficult to piece together, both because the Amplify framework still uses an old library under the hood ('amazon-cognito-identity-js') and Cognito is the name for both a connect-login-with-IAM and signup/signin-as-a-service offering. Cognito is super powerful and rock solid in terms of security if done right, but the setup is a bit of a pain.
There's a bit of documentation, e.g. the API docs of Amplify Auth here. You can see there that currentCredentials / currentUserCredentials gives you some object which contains among other things an 'identitiId'. Credentials, in the Amplify Auth framework, refer to AWS IAM credentials that refer to an Cognito Identity.
You seem to be using Amplify to login to a Cognito User Pool, using email/password. A Cognito User Pool can be connected to a Cognito Identify pool, to 'exchange' a Cognito JWT token for some credentials that can be used to use AWS resources (IAM credentials). This is not needed to have a normal sign in / sign up flow working though.
So, the question is: what do you want?
Do you want to know about the currently logged in Cognito User Pool user, e.g. his email, JWT token and other fields that are stored in the JWT token? Use 'currentUserInfo' or 'currentUserSession'
Do you actually want to have some IAM credentials to invoke AWS resources? Make sure to create and connect your Cognito User Pool with a Cognito Identity Pool and configure your Identity Pool id in your frontend settings. If you've done that, you should be able to use 'currentCredentials'.
I am trying to get a session token for the given IAM in postman but not able to receive a token.
If I use boto3.client('sts'), I am able to get the token.
Use Case: I am trying to Invoke VPC Rest Endpoint from EC2 instance where ServiceNow mid-server instance is running. Since we have ServiceNow mid-server agent running on EC2 instance, I want to use IAM Role attached to EC2 to authenticate other VPC endpoints that are deployed in the same AWS account.
I have permission policy attached to IAM Role to allow Assume Role policy. If there any other approach, please suggest.
here HTML HTML response in postman. Postman redirecting to IAM Docs
client = boto3.client('sts')
response = client.assume_role(
RoleArn='arn:aws:iam::**************:role/ServiceNow-midserver-Role',
RoleSessionName='Session1',
DurationSeconds=3600
)
print(response)
anything wrong with postman request body or endpoint.
Authentication on postman is none.
To call AssumeRole from Postman (or curl etc.) as opposed to using a supported AWS SDK, you should follow the AssumeRole API documentation. You will also need to authenticate using AWS credentials.
Specifically, the request is an HTTP GET and parameters are passed as query strings, for example:
GET https://sts.amazonaws.com/
?Version=2011-06-15
&Action=AssumeRole
&RoleSessionName=stackoverflow-64706420
&RoleArn=arn:aws:iam::123456781234:role/myrole
&DurationSeconds=3600
Here's what this looks like in Postman:
And you will need to add AWS credentials so that your API request is signed correctly, for example:
Click 'Send' and the response will look something like this:
<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleResult>
<AssumedRoleUser>
<Arn>arn:aws:sts::123456781234:assumed-role/123456781234/stackoverflow-64706420</Arn>
<AssumedRoleId>ARO123EXAMPLE123:stackoverflow-64706420</AssumedRoleId>
</AssumedRoleUser>
<Credentials>
<AccessKeyId>ASIAIOSFODNN7EXAMPLE</AccessKeyId>
<SecretAccessKey>wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY</SecretAccessKey>
<SessionToken>
AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQW
LWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGd
QrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU
9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz
+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA==
</SessionToken>
<Expiration>2020-12-09T13:34:41Z</Expiration>
</Credentials>
<PackedPolicySize>6</PackedPolicySize>
</AssumeRoleResult>
<ResponseMetadata>
<RequestId>c6104cbe-af31-11e0-8154-cbc7ccf896c7</RequestId>
</ResponseMetadata>
</AssumeRoleResponse>
You need to use credentials for an IAM user or an IAM role to call AssumeRole. boto3 must be getting credentials from the standard locations it look for (like ~/.aws/config) [ref:https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html]. May be you could try providing the AWS creds in Authorization tab in Postman selecting type as AWS Signature and then call assumeRole.
In my React Native App I am using API Keys with AWS AppSync and I want to move to using Cognito or IAM but with no user sign in.
My React Native app that just uses AWS Appsync to read to and write from DyanmoDB.
I initially set up the app to use API keys as it was easier to understand and I'm now attempting to transition to using AWS Cognito or IAM.
To do this in my AWS Console I changed the "Appsync->MyAppAPI->Settings->Default authorisation mode"/"API-level" from "API key" to "AWS Identity and Access Management (IAM)".
I then created an Identity Pool and allowed "Enable access to unauthenticated identities".
My aws-exports file is
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.
const awsmobile = {
"aws_appsync_graphqlEndpoint": "https://xxxxx.appsync-api.eu-west-x.amazonaws.com/graphql",
"aws_appsync_region": "eu-west-X",
"aws_appsync_authenticationType": "AWS_IAM",
"aws_appsync_apiKey": "xxx-xxxxxxxxxxxxxxxxxxxxxxxxxx",
};
export default awsmobile;
In my App.js file I have attempted to get the identityPoolId to be used and I have created this:
Amplify.configure({
url: config.aws_appsync_graphqlEndpoint,
region: config.aws_appsync_region,
auth: {
type: config.aws_appsync_authenticationType,
apiKey: config.aws_appsync_apiKey,
region: 'eu-west-x',
identityPoolId: 'eu-west-x:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
}
})
When I use the app to read from DynamoDB I get this error
[WARN] 04:51.835 API - ensure credentials error, No Cognito Federated Identity pool provided
I then went back to the Cognito Manage Identity Pool page and changed my identity pool to use Cognito as an authentication source and provided a User Pool ID and an App client id. But I still get the same error.
I am fundamentally missunderstanding something, could you offer any insight?
Scenario:
I create an app on Amazon, and use Login with Amazon, which returns an "access_token". Then I run:
AWS.config.credentials = new AWS.WebIdentityCredentials({
RoleArn: 'arn:aws:iam::416942672???:role/???_amazon_role',
ProviderId: 'www.amazon.com',
WebIdentityToken:"?????????"
});
AWS.config.region = 'us-west-2';
dynamodb = new AWS.DynamoDB() dynamodb.listTables({}, function a(error,data){
alert( "error: " + JSON.stringify(error) );
alert( JSON.stringify(data) );
});
When I later run the ListTable function it will return:
error: {"message":"Missing credentials in config","code":"SigningError","name":"SigningError","statusCode":403,"retryable":false}
I found it seems that I have to call AssumeRoleWithWebIdentity. But how can I call it in AWS SDK for JavaScript? Or is there any other process I missed?
The process of Getting Temporary Credentials indeed requires a call to AssumeRoleWithWebIdentity - this low level API call is implied in the higher level AWS SDK for JavaScript credentials provider call new AWS.WebIdentityCredentials() though, see e.g. Class: AWS.WebIdentityCredentials:
Represents credentials retrieved from STS Web Identity Federation
support.
By default this provider gets credentials using the
AWS.STS.assumeRoleWithWebIdentity() service operation. This operation
requires a RoleArn containing the ARN of the IAM trust policy for the
application for which credentials will be given. In addition, the
WebIdentityToken must be set to the token provided by the identity
provider. See constructor() for an example on creating a credentials
object with proper RoleArn and WebIdentityToken values.
Given the error message "Missing credentials in config", you are obviously passing an incorrect WebIdentityToken, which isn't a surprise given you just specified some ????????? placeholders ;) - since you already use Login with Amazon, which returns an access_token, you'll just need to pass the content of that ACCESS_TOKEN instead of those ????????? placeholders as value for WebIdentityToken and should be all set.
For other readers: Section 6. Putting it all together of Configuring Web Identity Federation in the Browser provides an example for retrieving the access token via Facebook Login. As noted there, Other identity providers will have a similar setup step that involves loading the respective SDK, logging in, and receiving an access token - in particular, how to handle Login with Amazon is documented in detail within Getting Started for Web.
Use AWS instance in this way:
var aws = AWS ;
var region = aws.config.region = 'us-east-1';
var cred = new aws.Credentials(<YOUR_ACCESS_KEY_ID>,
<YOUR_SECRET_ACCESS_KEY>, sessionToken = null);
To get ACCESS KEY ID and SECRET ACCESS_KEY go to:
AWS IAM>Users>Security Credentials>Access Keys
Now use aws instance for further operations.