Reputation: 344
I recently started experimenting with AWS AppSync but I had some questions around AWS Cognito.
I would like for users to be able to authenticate with Facebook but I need their profile picture, name and email as data for my public user profiles in my app. So far, I noticed Cognito integrates with Facebook Auth but it does not allow access to the user information and this info does not get saved in a DynamoDB table.
My question is, how can I create a new User in DynamoDB when Cognito receives a new sign in, or return an existing user/id when the user already exists in the db.
Upvotes: 6
Views: 4976
Reputation: 1780
AWS AppSync allows you to access information in the GraphQL resolver which you can choose to store in a DynamoDB table. In your case for data coming from a Facebook profile you could pass this as arguments to a GraphQL mutation or in a header to AppSync which you can then access in the resolver via $ctx.request.headers.NAME
where NAME is your header name. Then you could simply choose which attributes you want to write to DynamoDB for that user as part of the mutation. More information is in the reference guide here: https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html
Since you also asked that you'd like to do a check first to see if the user is already in the DDB first you could just do an existence check first:
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"userId": $util.dynamodb.toDynamoDBJson($ctx.identity.username),
},
"attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
"condition": {
"expression": "attribute_not_exists(userId)"
},
}
This checks against the username from Cognito User Pools. If you were using the Cognito Federated Identities feature it would be ctx.identity.cognitoIdentityId
. If the record is already there the response that comes back will tell you which means the user is already present. You could also transform the returned message in the response mapping template by looking at $ctx.result
with a conditional statement and either building the JSON response by scratch or using one of the $util.error()
methods in the guide above.
Finally as you mentioned that you'll have public profile data, you might want to mark this on certain records for control. In AWS AppSync you can filter GraphQL responses on authorization metadata such as this. You would just have an attribute (aka column) on the DynamoDB record marked 'public' or 'private. Then your response template would look like so:
#if($context.result.public == 'yes')
$utils.toJson($context.result)
#else
$utils.unauthorized()
#end
You can see more examples of this here: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html#public-and-private-records
Upvotes: 1
Reputation: 5661
You could use custom attributes and federating user from Facebook in your user pool to achieve this. Here are the steps at high level to do this.
After this, on each new user log in in your app a new user is created in your user pool with all the attributes that were defined in attribute mapping and values which Cognito gets in the Facebook token. Your app will get these attribute values in the IDToken issued after authentication and you app can use these.
Additionally, if you want to store these attribute values outside of Cognito user pools profile, like your own DynamoDB table, you can configure a PreSignUp trigger in the pool which will be invoked on all new user creations. You can export the user attributes from this trigger to any database of your choice.
Hope this helps.
Upvotes: 3
Reputation: 1548
I was trying to achieve the same a few weeks ago.
After reading the docs for hours, I realised that Cognito may not help us in regards to the data that comes back from FB or how to save it.
I ended up doing the following:
(1) Using FB-SDK, pulled in the user data.
(2) Invoked a Lambda function that saved this data (like FB_id,etc) to DynamoDB.
(3) If user logged in again, their FB_id (or email) was used to check against DynamoDB entries to retrieve their data.
If Cognito is able to help us and I missed it somehow, I would love to know.
Happy Coding!
Upvotes: 4