Serverless Backends With AWS Cloud: Twitter Sessions

Rob Sherling - Apr 24 '17 - - Dev Community

This is a part in a series on AWS serverless architecture. The original blog post series can be found both here and on my blog J-bytes.

How to make a session in DynamoDB

In this section, we're just going to save some browsing information in a session (held in DynamoDB) and redirect the user to Twitter. Once we have a callback in place, we'll use that session data to have our user follow us. We can also use that data to message that user later (we actually have the user DM themselves, explained in the next section) with some promotional news.

More specifically, we're going to save their request token in a table in DynamoDB along with some other stuff, then when they confirm our app, use their oAuth token to go get the data attached to the request token and complete the chain.

This is fairly straightforward so let's just jump right into it.

Step 0: Make a Twitter App

Setup your Twitter app here. It's fast, free, and easy. You will need this to do anything cool like message users and create friendships (on Twitter, this technology is not guaranteed to create friendships in any other way), so making it now makes sense. When you set this app up, it is super hyper critical imperative that you go to the permissions tab and select read, write, and access direct messages. You do this because we need to have them DM themselves later on.

Step 1: DynamoDB Tables

You should know the drill from the last time we touched tables, so let's just rig up the rest of our tables right now. We're going to need an additional 4 tables total. We'll need staging and production tables for the session we'll create to hold our user's data while they log in to their Twitter accounts to (hopefully) authorize us, and we'll need staging and production tables to hold their data once they come back from that authorization and hit our callback.

Open the DynamoDB table and make the following tables:

name: staging_session -> primary key: request_token (string)
name: production_session -> primary key: request_token (string)

name: staging_twitter -> primary key: uid(Number)
name: production_twitter -> primary key: uid(Number)
Enter fullscreen mode Exit fullscreen mode

Quick note on the uid in the Twitter tables: The uid actually will be treated as a string in our lambdas and automatically converted on storage. This is because Javascript sometimes has a problem with numbers and uids(source), but DynamoDB does not care at all.

Step 2: env-config.json

Open up - or download from your S3 - your env-config.json file (you should have two, one for each environment we are creating). We'll be filling in the rest of the values, leaving only the twitter_api_callback blank for now (we'll do that in the next section). You can get your consumer_key and consumer_secret values from your Twitter app that you set up in step zero. You can find it in Keys and Access Tokens tab on your app settings.

The twitter_table_name should be <stage>_twitter, and the twitter_session_table_name is <stage>_session.

For the follow uid, you can get it from the same Keys and Access Tokens tab labelled as Owner Id. If it is not your own account use this link and put in the account that you want to follow.

Save your JSON, and re-upload to the appropriate S3 buckets.

Step 3: Constructing the Twitter Lambda

Make a session_lambda folder on your local disk, and cd into it.

We're going to download libraries like we did before. This time, we'll need the node-twitter-api library. Observe the spacing on this command, it's a little tricky (careful when you copy):

npm install –prefix=./ node-twitter-api

Add the loader.js that we made before using either a hard system link or copying it into the folder, depending on your expertise. If you're copying the loader.js from the github repo for the project, remember to change the S3 bucket on line 61 to our actual bucket.

Add the index.js file.
Change the line on line 6 to your appropriate db region.

Read the index file for the notes, but it should be fairly straightforward. We're just going to take a POST request that will tell us if the user chose to follow us or not, hit the Twitter API to get some request tokens, save that data all together, and then redirect to the Twitter site so they can complete the authorization. If you don't need users to follow an account or track any other data in the session, feel free to make it a get request later on.

Zip the folder like we did when we made the email lambda (zip the contents of the folder, not the folder itself) and head on over to the lambda console.

Create a lambda function. Select Blank Function for the blueprint.
Click Next on the Configure Triggers section that pops up to move to the next screen.
For the name of the function, use generate_twitter_session.
Change the Code entry type drop-down box to "upload a zip file."
Upload the zip we just made.
Under Lambda function handler and role, use master_lambda in the Existing role dropdown box.
Set the Timeout to 15s
Click Next, then Create Function.
From the Actions drop-down, configure the test event.

{
 "body-json": "follow=true"
}
Enter fullscreen mode Exit fullscreen mode

Click Save.
Click Actions and create two aliases. One 'staging', the other 'production'. Both should point to Version: $LATEST (you can make a version 1 if you'd like).
Click the button to the left of test (could start with either Alias or say Qualifiers) and click staging under the aliases drop-down tabs. Then click test.
If you get an error message in your logs on a line with JSON.parse that says SyntaxError: Unexpected token u or something similar, check your test event again.

You should get an error message that says:

  "errorMessage": "Twitter.MovedPermanently : Redirecting.",
  "errorType": "https://twitter.com/oauth/authenticate?oauth_token=<SOME TOKEN STUFF HERE>"
If you do, you are in good shape and ready to move on to hooking up our API endpoint.
Enter fullscreen mode Exit fullscreen mode

Step 4: Making our Gateway

We're just going to hook up an API endpoint to our Twitter. This is basically a carbon-copy of the email API we made, so if you need a refresher please go read that again now.

Open the API Gateway console and click on our services-api that we made. Click on /api, and then click the Actions drop-down and select Create Resource. Name that resource twitter-session, and click Create Resource.

This resource is going to mimic our email resource nearly identically. Remember to have your AWS CLI ready to approve our stage variable controlled lambdas.

Click on the twitter-session resource, and click create method. Change that method to post, and click the check mark.

Change the lambda region to your region, then type generate_twitter_session:${stageVariables.alias}. Save, and when you see that giant wall of text, put it into the AWS CLI and replace ${stageVariables.alias}with staging. Enter, then replace it again with production. Enter again. Confirm non-error text.

Back in your lambda console, click okay. Then click on Method Response. Delete the 200, add a 301, and then edit it to include the 'location' header.

Go to the integration response. Delete the default response with a status of 200. Click add integration response, change the status to 301, and make the error regex, ^Twitter.MovedPermanently.*

Edit our newly created integration response and set the value of the location header mapping to integration.response.body.errorType. Click the checkmark.

Lastly, go back to our Integration Request from the twitter-session post option, and add a body mapping template. The type is application/x-www-form-urlencoded. Set the general template to Method Request passthrough, and the Request body passthrough to When there are no templates defined. Save it all.

Deploy to staging and production. Export. Save.

Step 5: Postman

Click on staging under stages, then click on /api/twitter-session. Copy the invoke URL and paste it into Postman. Set the header to Content-Type: application/x-www-form-urlencoded. Set the body to x-www-form-urlencoded, and the data key-value to follow : true. Ensure that the method type is POST, and hit send. Postman should say loading for a short bit (if, for example, you are doing this from near Tokyo when your server is in California, it may be a long bit), and then come at you with something like this (you will have to click "pretty" to make it pretty):

Postman Screenshot

It works!

There is no need to go any farther than this for now. If you check your staging_session database table, you should have some data in it. That marks the completion of this section.

In the next section, we'll send confirmation tweets, actually follow an account, etc.

. . . . . . . . . . . . . . . . . . .