Sharing an ExpressJS / Connect / PassportJS Session with Golang – Part 1

TL;DR – I’ve confirmed the process to extract and verify the session ID and accompanying signature from the authentication cookies set by ExpressJS and Connect. For a “no-sh*t-sherlock” version of this article (bare bones research) check out my Oystr map here.

ConnectSid

 

I’ve begun the process of writing some of my microservices for my start-up, Oystr, in Golang and I have encountered a slight issue with authentication. My current authentication is all handled by PassportJS in a Node.JS and ExpressJS stack meaning I’m going to have to somehow share the the session information between the two different platforms. I’m a one man team at the moment so re-writing everything in Golang is out of the question and I’m just battling too much with the lack of type checking in JavaScript to be able to continue completely on Node.JS. The solution for me is to be able to access the cookie information saved by ExpressJS and then pull the user information from Redis into Golang.

The Connect.SID Cookie

So this is what I know from previous experience with setting up PassportJS – I know that it uses the information stored in the “connect.sid” cookie value to find the corresponding user IDs in the Redis session store I’m using to persist sessions. Verifying this was the easy bit and was just a matter of opening up Chrome’s developer tools (F12) and then looking at the cookies. Sure enough I found it as shown below.

connect.sid Cookie

Looking at the value, it was clear to see that it was URL encoded so once I decoded this I got something of the form “s:sessionid.signature”. At this point you could say “now that I have the session ID I can go look for that ID in the Redis session store… my work here is done”, smack your hands and walk away… BUT if you do that you’re opening yourself up to a massive security hole. Someone could easily just try brute forcing the session ID in the hope that they hit the session ID matching a logged in user. To really make this secure you need to be able to verify the signature is correct for the given session ID.

Verifying the Signature

So after a bit of research (go look at my research map in Oystr, here, if you want to see my sources for yourself) I figured out the process for creating the signature. I decided that initially I’d prove the process works with the sample I took from my browser using commands on the Linux command line as I hate writing code for a process that doesn’t actually work. Writing code for something that isn’t even correct is a million times more annoying than having to continuously check your typing in JavaScript (and if you read my last post https://mymemorysucks.wordpress.com/2016/05/19/why-javascript-is-giving-me-depression/ you’ll realise how big of annoyance that is to me).

The basic process to create the signature from the session ID is –

  1. Create a SHA256 HMAC signature based upon the secret you declare in your ExpressJS middle-ware setup code. The code itself should look something like app.use(session({secret: ‘my secret’})).
  2. Creating the signature will generate a long hexadecimal value like “6F0AD0BFEE7D4B478AFED096E03CD80A”. You need to convert this to base64 and that value should match the signature stored in the “connect.sid” cookie.

It’s only two steps so it’s pretty basic. After some searching around I figured out you could do the conversion from the Linux command line using the “openssl”, “xxd”, and “base64” commands.

  1. You use “openssl” to first create the signature for the session ID.
  2. You use “xxd” to convert the signature, which is actually just a “string” of numbers and letters, into the actual bytes represented by the hexadecimal characters.
  3. You use “base64” to convert the bytes from “xxd” into a base64 format.

You can do all of that pretty easily with the following commands –

  1. echo -n <session id> | openssl sha256 -hmac <my secret>

    This dumps out a string like “6F0AD0BFEE7D4B478AFED096E03CD80A”. This is the <signature> to be used in the next set of commands.

  2. echo -n <signature> | xxd -r -p | base64

After that second command, assuming you did all that correctly and used the correct values, you should have a base64 signature that matches exactly the signature part of your example connect.sid cookie.

What next?

So now that I can calculate the correct signature, I can make sure that the session ID I’m being supplied by the user hasn’t been tampered with and that they are unlikely to be attempting a brute force hack. In my part 2 post I’ll give details and code as to how I made use of all of this in developing a Golang package to share the sessions and user profiles between my two platforms.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s