Getting user from SNS EndpointAdded Event - amazon-web-services

I'm trying to associate my user's Cognito identity with the SNS endpoints they create when registering for push notifications. I've created a Lambda functions connected to the SNS application's EndpointAdded topic. It is fired whenever an endpoint is created, but it does not include any information I can see that I can use to associate the endpoint to a user.
I see many examples where people are adding the user ID as custom user data, but this allows any user to sign up for any other user's notifications. Is there a more secure way to make this association?

If you front registering the endpoint with Lambda or APIGateway and you use SigV4 credentials vended by Cognito to make the call, the context passed in will contain the Cognito Identity Id extracted from the credentials that made the call. This will ensure that the identity id you associate with the endpoint hasn't been tampered with.

Related

AWS Cognito: How to remember device in CUSTOM_AUTH authentication workflow?

I have followed this AWS blog to implement the Custom Authentication Flow for my website with Email One-Time-Password as a second Factor:
https://aws.amazon.com/blogs/mobile/extending-amazon-cognito-with-email-otp-for-2fa-using-amazon-ses/
Basically it explains that on Cognito, how to use the CUSTOM_CHALLENGE and 3 lambda functions as triggers for Cognito to:
Define custom auth challenge
Create custom auth challenge code and send to user's email address through AWS SES;
Verify that the verification code the user submitted is correct;
The authenticationFlowType would be CUSTOM_AUTH in this case, which is different from USER_SRP_AUTH in the normal username/password only scenario.
Now, I want cognito to remember the device that the user is on.
In this doc:
How do I use remembered devices in my Amazon Cognito user pool?
It says:
Note: The remembered devices functionality works only with the
USER_SRP_AUTH authentication flow. Also, this functionality requires
multi-factor authentication (MFA) to be enabled for the user pool.
So how can I remember device when it comes to CUSTOM_AUTH authentication workflow?
If there is no easy way, then I need a way to send the device info or IP address to the Lambda function triggers that Cognito is hooked with when calling:
const user = await Auth.signIn(formData.username, formData.password);
to sign in.
How can I do that with AWS Amplify?

Use cognito login instead of certificates to authenticate and subscribe to aws IoT MQTT topics?

I'm new to learning AWS and I'm trying to figure out if my use-case is possible. I want to create a mobile app where the user can login (email/facebook/google etc.) and then subscribe to a few MQTT topics on aws IoT to receive realtime sensor data for a gardening system. There are many tutorials on AWS that show you how to do this
(prime example: https://github.com/awslabs/aws-sdk-android-samples/blob/master/AndroidPubSub/README.md)
but all of them require you to download certificates, insert app IDs, secret keys etc. in the code/keystore itself. I'd really like to avoid all of this and just use the login as all the authorization you would need to subscribe to these topics.
is this possible? or do I need to build some custom system?
Short answer, Yes, it is possible. To do that you should do the following:
Create Cognito user pool. User Pool ID and App client id will be used in the next step. You can find more information here.
Create Cognito Identity pool. Under Authentication Providers you should give User Pool ID and App client id, more information here. When you create this, it will create two Roles for Authenticated and Unauthenticated users in IAM. You should add IoT access permissions (Connect, Publish, Subscribe and Receive) to those roles.
On client side (your App), after choosing your preferred AWS SDK (Android, iOS, React, JS, etc.) and configuring User pool ID, Identity pool and App client ID you should first authenticate the user by sending the user information (usually Email/Username and Password) to the Cognito user pool. In return, you will get some tokens.
Among those IdToken (JWT) will be sent to the Identity pool and in return you will get User Identity ID along with credentials (accessKeyId, secretAccessKey, sessionToken) needed to access AWS other services like IoT.
Last step would be using aws-iot-sdk for your App along with those credentials to publish and subscribe to your IoT topics. You can find more information about aws-iot-sdk here.

Testing Cognito user pool auth with API gateway

I would like my client application to insert records in my dynamoDb instance using API gateway secured with Cognito user pools.
I have created my user pool and added it as an authorizer to my API gateway method call. Using AWS Cli I ran the following command which gave me my access token:
aws cognito-idp initiate-auth ...
My infrastructure seems to be working, now which direction do I need to go to pragmatically achieve signing-in as my user in the user pool, grabbing the token and calling my API method?
Well it's not difficult. You need to follow certain steps.
Create an user in Cognito user pool. Confirm it, by the means of activation message you have chosen. It can be sms or email as per the user pool settings.
After you confirm the user, you need to call the login API from Cognito SDK. Since I am comfortable in NodeJS, let me grab the method name - https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html. Set AuthFLow to ADMIN_NO_SRP_AUTH .The response from this APi will have one idToken, one accessToken and one refreshToken. Since you need these credentials at your client, write an API in your preferred language, expose it your client and return the tokens.
Use the idToken to make API calls to your API Gateway Authorizer. This is how you pass the token using Postman -
You can replicate the same using any client. If you face any error, It'd be better if you show me your APIG authorizer configuration.

AWS SNS Publish to specific User via Cognito Identity ID

What I'm trying to do here is sending a notification via SNS and APNS when a specific user is part of a newly added DynamoDB Item. I want to send it to the users Cognito Identity ID, not to device token.
So Lambda should be triggered when the item is added and then go through a list of Cognito Identity IDs, which is also part of the item.
Then Lambda is supposed to publish the push notifications to each Cognito Identity ID.
All the devices are registered as endpoints within sns. I also keep the Cognito Identity ID in the "user data" row for the endpoint.
But i didn't find a way to send notifications directly to a Cognito Identity ID. Do i have to add a topic for each user and send the notification to that topic? Or do i have to store another DynamoDB table to map Cognito Identity IDs to device tokens? It would be great if someone knew an easier and not too expensive way!
Thank you!
If you are sending Push Notifications via SNS to APNS or GCM then you first need to create an SNS Platform Endpoint for each device token registered for Push Notifications. Once you have an SNS Endpoint, you'll need to map that endpoint with the Cognito Identity ID in the user table or another mapping table.
When a new item is added to DynamoDB, the event handler (Lambda) will need to map the incoming Cognito Identity ID to the SNS Platform Endpoint in the user table and then it can direct publish to that one endpoint.
You do not need to create an SNS Topic for sending Push to individual endpoints.

Register Endpoint (Device) on Amazon SNS using API

Need to register an endpoint with Amazon SNS when a user agrees to accept Push Notificaitons. Have the registration id I need to send to SNS. When I enter it manually I can send push notifications to my device.
Just need to register the endpoint with SNS using the Amazon API using a Post or Get request automatically when the user agrees to accept push notifications. Right now I'm getting SignatureDoesNotMatch trying to call CreatePlatformEndpoint.
http://docs.aws.amazon.com/sns/latest/api/API_CreatePlatformEndpoint.html
I have my
Application ARN
Access Key Id
Secret Access Key
But I'm not sure what values need to be passed in. Nothing seems to work and I haven't found good examples of what values the API is looking for when I call CreatePlatformEndpoint
It also appears I may need to call this before but this has even more values I'm not sure of.
http://docs.aws.amazon.com/sns/latest/api/API_CreatePlatformApplication.html
Seems like it should be fairly simple to make a request to add an Endpoint to my app. If anyone could help define what data goes where in this request that would be great.
Thanks
Permissions for the JavaScript SDK are tricky as it's obviously client side which makes your application potentially very susceptible. There's a good overview of JS credential management here. Hardcoding is not advised and if used should only be of a user with read-only credentials. Obviously for this application you need SNS modification permissions for I'd say go down the federation route.
The access key ID can be thought of like a username, and the secret access key is like the password. You need both for an authenticated handler to an AWS resource. The ARN is the thing you want access to and in this case I'm guessing this is the PlatformApplication?
It sounds like your error is because your request isn't being authenticated with the appropriate credentials. Are you also aware if those credentials provide access to the SNS service to make changes?
CreatePlatformApplication will return an ARN to use when creating the Endpoint. The endpoint parameters appear to be looking for that, the token to identify the app on the device, your user data and any other attributes you want to set.