unauthenticated issues on Cognito - amazon-web-services

Goal:
Basically, I want to retrieve the user attributes/identity ID using the users' STS credentials (access, secret, session keys). I'm writing a java servlet (server side), and my client is passing the STS credentials over HTTP.
Problem:
I am getting unauthenticated issues on the servlet. Below is my Java Code.
BasicSessionCredentials bsccreds = new BasicSessionCredentials(access, secret, session);
AmazonCognitoSyncClient cogni = new AmazonCognitoSyncClient(bsccreds);
AmazonCognitoIdentity identityClient = new AmazonCognitoIdentityClient(bsccreds);
GetIdRequest idRequest = new GetIdRequest();
idRequest.setRequestCredentials(bsccreds);
idRequest.setAccountId("51xxxxxxxx");
idRequest.setIdentityPoolId("us-east-1:xxxxxx-xxxx-xxxx-xxxxxxxxx");
GetIdResult idResp = identityClient.getId(idRequest); // this line is giving unauthenticated issues even though i pass the STS credentials.
String uuid = idResp.getIdentityId();
ListRecordsRequest lrr = new ListRecordsRequest();
lrr.setIdentityPoolId("us-east-1:xxxxxx-xxxx-xxxx-xxxxxxxxx");
ListRecordsResult lrr_res = cogni.listRecords(lrr);

that is inside a lambda method? does the IAM user has permissions to use cognito?

Related

Authenticating with AWS .NET SDK for Amazon Chime

I'm trying to create meeting using Chime SDK and I'm passing accessKey and accessKeyId to authenticate. However, the request fails with error, 'Invalid session token'. When I pass session token generated using AWS CLI it works fine. I want to generate the session token programmatically from within .net. How to achieve this.
AWSCredentials credentials = new Chime.Credentials(awsAccessKeyId, awsSecretAccessKey, token);
RegionEndpoint region = RegionEndpoint.USEast1;
client = new AmazonChimeClient(credentials, RegionEndpoint.USEast1);
CreateMeetingRequest request = new CreateMeetingRequest();
request.MeetingHostId = meetingHostId;
request.ExternalMeetingId = externalMeetingId;
return await client.CreateMeetingAsync(request);
You are not setting the ClientRequestToken
CreateMeetingRequest request = new CreateMeetingRequest();
request.MeetingHostId = meetingHostId;
request.ExternalMeetingId = externalMeetingId;
//needs request.ClientRequestToken = ????
Tim

Getting cognito user pool username from cognito identity pool identityId

I am using AWS Congito User Pools for account management with a Cognito Identity Pool that has this User Pool as the Identity Provider. I'm using this to control access to an API through API Gateway that sends requests to Lambda. My Lambda is implemented with Java 8 using Micronaut. All of this is working fine.
In the Lambda, I'm getting the name from the Principal in the HttpRequest:
protected String resolveUser( HttpRequest request ){
String ret = null;
Optional<Principal> principal = request.getUserPrincipal();
if( principal.isPresent() ){
ret = principal.get().getName();
}
if( ret == null || ret.length() == 0 ){
ret = "unknown";
}
return ret;
}
What is coming back in the string name of the Cognito identityId. Something like this:
us-east-1:xxxxe650-53f4-4cba-b553-5dff42bexxxx
I would like to either log the actual user login or at least have some way to convert the identityId to the login when needed.
The LookupDeveloperIdentity API call appears to be the right way to go about this, but I'm unable to get it to work.
Attempting to do this with Java and the AWS Java SDK 2:
protected String loadUsername( String user ){
String ret = "unknown:"+user;
CognitoIdentityClient cognito = CognitoIdentityClient.create();
LookupDeveloperIdentityRequest request = LookupDeveloperIdentityRequest.builder()
.identityPoolId( identityPoolId )
.identityId( user )
.build();
LookupDeveloperIdentityResponse response = cognito.lookupDeveloperIdentity( request );
List<String> identifiers = response.developerUserIdentifierList();
if( identifiers != null && identifiers.size() > 0 ){
ret = identifiers.get( 0 );
}
return ret;
}
throws an exception
software.amazon.awssdk.services.cognitoidentity.model.NotAuthorizedException: You do not have access to this identity (Service: CognitoIdentity, Status Code: 400, Request ID: 64e36646-612b-4985-91d1-82aca770XXXX)
Attempting to do this via the CLI produces a similar result:
aws cognito-identity lookup-developer-identity --identity-id us-east-1:xxxxe650-53f4-4cba-b553-5dff42bexxxx --identity-pool-id us-east-1:xxxx0aa1-89f9-4418-be04-7e83c838xxxx --max-results=10
An error occurred (NotAuthorizedException) when calling the LookupDeveloperIdentity operation: You do not have access to this identity
I have made sure the IAM policy in place should be able to handle this, and when I try it with a role that does not have this policy, I get a different error
{
"Effect": "Allow",
"Action": [
"cognito-identity:LookupDeveloperIdentity"
],
"Resource": [
"arn:aws:cognito-identity:us-east-1:##########:identitypool/us-east-1:xxxx0aa1-89f9-4418-be04-7e83c838xxxx"
]
}
So the questions boil down to:
Is this the best way to get the user pool username from the identity pool id?
If it is - what am I doing incorrectly?
If it is not - what is a better way of doing this?
Alternative Approach
In order to retrieve the user’s User Pool user id you can retrieve in your lambda:
authProvider = event.requestContext.identity.cognitoAuthenticationProvider;
This will return a string which will include the user's User Pool user ID and it will look something like:
cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxxx,cognito-idp.us-east-1.amazonaws.com/us-east-1_aaaaaaaaa:CognitoSignIn:qqqqqqqq-1111-2222-3333-rrrrrrrrrrrr
Where us-east-1_aaaaaaaaa is the User Pool id and qqqqqqqq-1111-2222-3333-rrrrrrrrrrrr is the User Pool User Id. You can then split the string and extract the user ID.
Note that these info will be different depending on the authentication provider you are using.
Then if you need the username instead of user ID you can extract it directly from user Pool by getting the appropriate details for that specific user ID.
Reference
https://serverless-stack.com/chapters/mapping-cognito-identity-id-and-user-pool-id.html

How to exchange Google auth details for AWS Cognito user pool keys

After authenticating with Google, following the guide here, I end up with this set:
email // 'eddyverbruggen#gmail.com'
userId // user id
displayName // 'Eddy Verbruggen'
familyName // 'Verbruggen'
givenName // 'Eddy'
imageUrl // 'http://link-to-my-profilepic.google.com'
idToken // idToken that can be exchanged to verify user identity.
serverAuthCode // Auth code that can be exchanged for an access token and refresh token for offline access
accessToken // OAuth2 access token
How do I use these to get back a Cognito user pool session consisting of:
"access_token":"eyJz9sdfsdfsdfsd"
"refresh_token":"dn43ud8uj32nk2je"
"id_token":"dmcxd329ujdmkemkd349r"
Turns out, this is not supported yet. Here's a feature request.
It's my understanding that you need to enable a Federated Identity in AWS Cognito Console. That document provides this snippet, which shows that you need to use the idToken in the response from Google:
function signinCallback(authResult) {
if (authResult['status']['signed_in']) {
// Add the Google access token to the Cognito credentials login map.
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'IDENTITY_POOL_ID',
Logins: {
'accounts.google.com': authResult['id_token']
}
});
// Obtain AWS credentials
AWS.config.credentials.get(function(){
// Access AWS resources here.
});
}
}

Signing with temporary credentials for API gateway request problems

I'm trying to invoke my API Gateway with authenticated users with the REST API. For this I'm using: Cognito UserPool + Cognito Identity Pool + API Gateway + AWS_IAM Authorization + Cognito Credentials. From what I've gathered I need to sign my request with (temporary credentials). Based on this thread I want to sign my request with the following keys:
{
SecretKey: '',
AccesKeyId: '',
SessionKey: ''
}
If I use an associated user from my IAM console and use the corresponding SecretKey + AccesKeyID everything works fine. However, I want to use the Unauthenticated and Authenticated roles from my Identity Pools to apply IAM policies based on authenticated or unauthenticated users.
FYI: I can call the authenticated functions from this part of the documentation.
I'm building a React-Native app, and because of that I want to keep the native SDK to a minimum and I'm only using AWSCognitoIdentityProvider part. For the user handling.
I trying to receive the correct keys using this Objective-C code:
[[self.credentialsProvider credentials] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(#"Error: %#", task.error);
}
else {
AWSCredentials *response = task.result;
NSString *accessKey = response.accessKey;
NSString *secretKey = response.secretKey;
NSString *sessionKey = response.sessionKey;
NSDictionary *responseData = #{
#"AccessKey" : accessKey,
#"SecretKey" : secretKey,
#"SessionKey": sessionKey
};
}
return nil;
}];
The rest I've setup using the relevant docs.
I (wrongly?) tried to sign my requests with the
AccessKey, SecretKey, SessionKey retrieved from the CredentialsProvider above.
{
SecretKey: credentials.SecretKey,
AccesKeyId: credentials.AccessKey,
SessionKey: credentials.SessionKey
}
The signing fails with the following error:
{ message: 'The security token included in the request is invalid.' }
So the question I have is: which keys should I use to sign my requests for authenticated users so that I can apply the attached IAM policies from my Cognito Setup?
Thanks for any help :)
Like Michael - sqlbot, point out, it should be SessionToken instead of SessionKey. I found a better instruction on how to get credentials from Cognito.

How to use OAuth2.0 access token to retrieve gmail contact list

I use the following code to obtain access token for my application in Python.
CLIENT_SECRETS = 'client_secrets.json'
MISSING_CLIENT_SECRETS_MESSAGE = "Missing Client Secrets"
FLOW = flow_from_clientsecrets(os.path.join(os.path.dirname(__file__), CLIENT_SECRETS),
scope=['https://www.googleapis.com/auth/drive','https://www.google.com/m8/feeds'],
message=MISSING_CLIENT_SECRETS_MESSAGE)
storage = Storage('drive.dat')
credentials = storage.get()
credentials = run(FLOW, storage)
http = httplib2.Http()
http = credentials.authorize(http)
service = build("drive", "v2", http=http)
But after obtaining the access token, how am I supposed to retrieve gmail contact list using gdata client library of Python? The sample in client library does not use OAuth authentication but another approach.