Skip to main content
IAM Strategy Report CIAM Buyer's Guide Contact Us
Janrain respects your privacy and will treat the personal data you choose to share with us in accordance with our privacy statement.
 

We use cookies to give you the best online experience. By using our website you agree to our use of cookies in accordance with our privacy statement

OK

Mobile Menu

Using Python to Build a Social Network on Top of the Janrain Platform (Part 1)

By Luc Perkins | Posted on June 20, 2013

Blog Banner

If you head over to the Janrain developers portal , you’ll see lots and lots of documentation. The folks on our docs team— Ian Smith , Ed Allen , and Mark McCarron-Fraser —have done a phenomenal job of enabling devs of all kinds to implement Janrain, including social login and social sharing , social profile storage , single sign-on , and more.

What I’d like to add to our current documentation is a step-by-step walk-through of building an application from scratch that incorporates social login and other capabilities. To that end, I’m going to build a really simple social network called "Episteme" (after one of the ancient Greek words for knowledge ) that is geared toward sharing books and ideas and allows people to do the usual things that you’d expect from a social network, like upload a picture, add and remove friends, and so on.

The essential difference between Episteme and a lot of other social networks, though, is that there’s no username and password requirement. Instead, I’ll use Janrain Engage to build social login into my site–which I’ll do in this tutorial–and, later on, Janrain Capture to store social profile data gathered from other social media outlets.

In this tutorial, though, I’ll just be implementing social login. No social profile storage or social sharing or anything like that.

Software Stack

The web framework I’ll use for this app will be the Python Flask framework. I chose this framework for a variety of reasons: the documentation is excellent, I’m a big fan of Sinatra -inspired micro-frameworks, and Python is a very readable, intuitive language, which helps concepts travel quickly and easily to other runtimes.

Outside of Flask itself, I’ll use PostgreSQL as my user database. SQLite, MySQL, or something else would also work just fine, but Postgres is simply what I know best. If you’re familiar with other relational databases, everything on this front will be 100% familiar. We also use Postgres a ton here at Janrain, so I always know that there are people I can lean on if I need to.

Oh, and I’m not a big fan of writing my own HTML—for reasons involving both maintainability and my own laziness—so I’ll use the Jade templating language in later tutorials. Today, though, I’ll only be creating one very simple HTML page, so I’ll stick with just writing straight-up HTML.

The code for this tutorial is up on GitHub .

Setting Up Our HTTP Server

The beauty of microframeworks is that they enable you to set up a functioning—if sparse—HTTP server in just a few lines. First, let’s install Flask using pip:

 $ pip install flask

Now let’s set up a simple server in a server.py file that will serve up an index.html file when you try to access the / endpoint:

 from flask import Flask, render_template app = Flask(__name__) @app.route('/', methods=['GET']) def index(): <%%KEEPWHITESPACE%%> return render_template('index.html') app.run(debug=True, port=3000) 

At the top, I’ve loaded the Flask class, which enables me to build an object of type Flask that will act as a kind of container for our application logic. I’ll simply call that object app to avoid confusion. After that, I’ll begin adding routes. For this tutorial, we only need one route. The function that is tied to that route could be called anything, but I’ll simply call it index()to avoid confusion. If we go to the /route, Flask will simply render our index.html file. In this example, I’ve specified that this particular route will only be handling GET requests. This is the default in Flask, but it’s not a bad idea to make things like this explicit from the get-go.

At the bottom, you’ll see our app.run()function. I’ll give that function two kwargs ( key-word arguments ), specifying that debug mode is turned on (this will help us a ton with stack traces)and that the app will be running on port 3000. The default is port 5000, but I use 3000 a lot and if I use 5000 I’ll forget and wonder what’s going on. YMMV.

Getting Set Up In The Janrain Dashboard

Before we can set up our index.html landing page, we need to register our application in the Janrain dashboard. If you’ve ever built an application using Twilio, Google Maps, or another web service API, the process is deeply similar in some respects but with important differences that I’ll note later. Here’s how to do that:

First, go to RPXNow.com , sign in using one of the identity providers (hooray for dog-fooding!),and create a new application. Once you’ve done that, you’ll be returned to the main dashboard. On the lower right-hand side you’ll see your app ID, API key, and other information listed under "Application Info."

For this tutorial, I’ll only need to use the API key. Personally, whenever I’m using API keys, I like to store them as environment variables rather than embedding them directly in my application. So I’ll add my API key to my~/.bash_profile:

 $ echo "export JANRAIN_ENGAGE_API_KEY='123abc123abc123abc123abc'&#3 >> ~/4;.bash_profile source /.bash_profile 

Now, I’ll add that to our server.py file and import Python’s os library, which enables us to interact with system-level environment variables:

 import os janrain_engage_api_key =os.environ['JANRAIN_ENGAGE_API_KEY'] 

Our server will also need to know which URL it will need to interact with to make Janrain Engage work. All applications use the same base URL and then append other parameters onto that URL (more on that in a moment). I’ll set the root URL near the top of my server.py file:

 janrain_engage_root_url ='https://rpxnow.com/api/v2/auth_info'

Now, we need to choose an identity provider ( IDP) . We could choose any combination of IDPs, and Janrain offers over 30 of them. But for now, let’s keep it simple and set up authentication via Twitter alone.

Creating A Twitter Application

This part sounds like it will be tough and annoying because it will introduce a completely new interface into the equation, but don’t worry: it’s really not so bad, and we won’t be doing anything fancy in the Twitter console. We just need to create a new stub application, make some configuration changes, and we’re done.

I won’t go through this process in this tutorial, as I would strongly recommend reading Twitter’s docs instead. I will say, however, that you’ll need to make sure that the following configurations are in place in your Twitter application:

  • Make sure and switch "Sign in with Twitter" to Yes
  • Change the "Callback URL"to the URL that you’ll use for the application in your localenvironment. For me, that will be http://127.0.0.1:3000.

Once you’ve done that, make sure and store your Twitter consumer key and consumer secret somewhere where it’s easily accessible later. Like I said, I tend to store API keys as environment variables, but you’re free to do it however you like.

Creating An Application-Specific JavaScript Widget

One of the nice things about developing on top of JUMP is that a lot of the more troublesome work–such as client-side JavaScript–is generated automatically.

For this part, I’m going to go back into the Janrain dashboard, click on Sign-In for Websites , select Twitter as my identity provider, and then input my Twitter consumer key and consumer secret. Once I’ve done that, Janrain has all the information that it needs from Twitter to put the social login special sauce to work. When I navigate to Get the Code , I see some generated JavaScript that I can copy and paste into the

of my index.html page.

Now comes the crucial part. In the JavaScript widget that the Janrain dashboard has dynamically generated, you’ll see the following line:

 janrain.settings.tokenUrl ='__REPLACE_WITH_YOUR_TOKEN_URL__';

We need to specify this token URL for our application. This part is deceptively simple. What we need to do is tell JUMP where to send a user’s information when he or she logs in through Twitter. We can make this URLwhatever we’d like. I’m going to change that to the following URL:http://localhost:3000/engage_callback_url.

This is the URL to which the JUMP servers will send the logged in user’s token. We’ll set up a URL to handle that request below.

Setting Up A Route to Handle Incoming User Data

Our Janrain Engage server pumps out lots and lots of information in the form of POST requests to servers all over the world. Now, it’s time for our application to bask in some of that plenitude. I’m going to have JUMP send users’ Twitter information to the /engage_callback_url endpoint. The piece of information that we need to extract is the token from the form data:

 @app.route('/engage_callback_url', methods=['POST']) def engage_callback(): <%%KEEPWHITESPACE%%>token =request.form['token'] 

In order to deal with form data, we need to import the request submodule from Flask. So now our import of Flask will look like this:

from flask import Flask, render_ template, request

So now, if the / engage_ callback_ url receives a POST request, it will trigger the engage_ callback( ) function, which will extract the user’s token from the data POSTed by JUMP.

Now, let’s make sure that everything is working the way it should. First, let’s start up our server:

 $ python server.py

We’re also going to need a basic landing page, complete with copy and pasted JavaScript widget:

  <%%KEEPWHITESPACE%%>; <%%KEEPWHITESPACE%%>RPXNow test app <%%KEEPWHITESPACE%%> <%%KEEPWHITESPACE%%> <%%KEEPWHITESPACE%%>
<%%KEEPWHITESPACE%%>

Notice that I’ve also added an empty HTML div called janrainEngageEmbed. This is essentially the empty DOM container inside of which our JavaScript widget is going to build our social login bar.

With our server up and running and our index.html file ready, let’s navigate to http:/ /localhost:3000 in our browser. That’s when a magical thing happens:our JavaScript widget has generated all the HTML and CSS necessary to render a social login widget. Hooray!

Fetching Our User Token

When we set up our /engage_callback_url endpoint above, we were enabling our application to fetch the user tokens sent to our application by the JUMP infrastructure. This token will enable us to interact with the Engage servers and fetch the user’s Twitter data in the future.

As it stands, our server is indeed fetching the user’s token–in the token =request.form[ 'token'] expression above–but it’s not doing anything with it. In this tutorial, we’re not going to do anything terribly complicated with it. We’re simply going to pass it into an HTML file to verify that the token is indeed being sent. So we’re going to add one line to our / engage_callback_url handler:

 @app.route('/engage_callback_url', methods=['POST']) def engage_callback(): <%%KEEPWHITESPACE%%>token =request.form['token'] <%%KEEPWHITESPACE%%>return render_template('logged_in.html', token=token) 

The new line simply does one thing:it will render a logged_in.html file and pass the user’s token into the view. Let’s set up a super-basic HTML file to show the token:

  <%%KEEPWHITESPACE%%> <%%KEEPWHITESPACE%%>User logged in page <%%KEEPWHITESPACE%%> <%%KEEPWHITESPACE%%> <%%KEEPWHITESPACE%%>

The user’s token is::{{token }}

<%%KEEPWHITESPACE%%>

As we can see, Flask uses a templating engine called Jinja , which is deeply reminiscent of MustacheJS . For now, we’re just going to set up this HTML file to dynamically render the user token.

Navigate to the main index.html page, click to sign in using Twitter, verify your email address and password for your Twitter account (if you aren’t logged into Twitter already), and if everything has been properly implemented you’ll be taken to the logged_in.html page and see you’re freshly generated user token.

Much More To Come Later

That’s it for now, Dear Reader. We’ve actually accomplished a surprising amount here. We have one .js file, a server.py file consisting of just a few lines of code, and two hyper-basic HTML files, but that basic setup is doing a lot of heavy lifting. This will in many ways form the nucleus of Episteme. In the next tutorial, I’ll set up my server to fetch user data from Twitter, store that data in Postgres, and more, so stay tuned for part 2!

Popular Posts

About the author