The user uploads an image to his/her subfolder on S3. The only way this can be enforced with policy is by using identity id:
arn:aws:s3:::thebucket/${cognito-identity.amazonaws.com:sub}/avatar.jpg
A lambda that transforms that image, is triggered, and saves the transformations to a different S3.
But now, with the identity id on disposal, that lambda needs to update the user's db record with the references to the avatar transformations. This is where the issue is evident, I only have the identity id, and from it, I need to get to the cognito user's details so i can look for the user in my users table which has user:sub as identifier.
How do I correlate those two? Is there an api in cognito that would give me the sub
based on the identity id?
Is there maybe a more reasonable way?
I have not been able to find a way to do this. Also, you should only get a Cognito Identity Id passed to Lambda if you are using the Mobile SDK, which you can access using 'context.identity.cognitoIdentityId'. Although one user user at least seems to be defying the AWS documention set by getting it to work with Javascript.
It looks like you are using the sub in your s3 object key, so have you thought about taking it form there? You get loads of information passed about the s3 object in your event, including the key, which in your case includes your sub.
Your S3 event should look something like this
{
"Records":[
{
"eventVersion":"2.0",
"eventSource":"aws:s3",
"awsRegion":"us-east-1",
"eventTime":"1970-01-01T00:00:00.000Z",
"eventName":"ObjectCreated:Put",
"userIdentity":{
"principalId":"AIDAJDPLRKLG7UEXAMPLE"
},
"requestParameters":{
"sourceIPAddress":"127.0.0.1"
},
"responseElements":{
"x-amz-request-id":"C3D13FE58DE4C810",
"x-amz-id-2":"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"
},
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"testConfigRule",
"bucket":{
"name":"mybucket",
"ownerIdentity":{
"principalId":"A3NL1KOZZKExample"
},
"arn":"arn:aws:s3:::mybucket"
},
"object":{
"key":"HappyFace.jpg",
"size":1024,
"eTag":"d41d8cd98f00b204e9800998ecf8427e",
"versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko",
"sequencer":"0055AED6DCD90281E5"
}
}
}
]
}
You could parse the S3 object key, which should have your sub in it.
EDIT: After sharing some comments I think your situation is this:
- You have a user who has logged into using an external identity (e.g. google)
- This user also has a user pool identity
- The identities have not been linked using admin-link-provider-for-user
- You want to lookup the user pool identity from the external identity after some action
Im assuming the thing that links these accounts is an email address? One option is to link the accounts when they signup, using a cognito pre-signup trigger and the admin-link-provider-for-user function.
The other thing you could do is take the current (externally provided) identity email, then do ListUsers based on that email. You will get a list of UserType back, then choose the one where the provider is Cognito, which should give you the sub you want.
Is that the sort of thing your after?
EDIT: Another idea we discussed in the comments was calling your Lambda function directly from your application, rather than relying on the S3 event. The benefit of this approach is that you could include any information you like in the call, like the correct user sub.