Adventures in Two Factor Authentication

Off we go!

Another hack week was upon us, and I had a definite idea in mind. I wanted to add two factor authentication to our web application. Having enabled it on web sites I use regularly, I was curious to see how difficult it was to implement and learn about the best practices associated with it. A bare bones implementation turned out to be remarkably trivial.

Our application runs on PHP, and it took minimal Google-fu to determine the RobThree/TwoFactorAuth library was the best option to try first -- well maintained, great documentation. One quick

composer require RobThree/TwoFactorAuth

to pull the library in, and it was right into setting it up. First hurdle reached! Our authentication code needed some tender loving refactoring to be able to support having two factor authentication enabled for your login or not. Ah... the satisfaction of being able to clean code up including squashing a bug that has long irritated you...

Once the authentication code was cleaned up, actually adding two factor authentication was trivial. It took more time to refactor our existing code than it did to use the library to generate the shared secret, display the QR code for scanning, and verify the entered token against the shared secret.

Which thirds to invite to the party?

By default, the PHP library reaches out to an external Google service to generate the QR code. However, you can use a local library to generate it if security of sending the shared secret over the wire is a concern. Hrm... Should I be concerned about that? Should I use an external third party service for generating QR codes, or should I compose in another third party library into our application?

Did a bit of research and found no compelling argument either way. Thinking it through, let's say I use an external third party and send the shared secret to them. What is the attack surface? They could sniff and record the secret, but they get no other details. How would they tie it back and use it with an actual username? They would need access to our database or server to make that association. If they have that, the game is already up, and they likely don't care or need the secret anyway.

What other drawbacks might there be then? There are two that spring to mind. First is the need to make an HTTP request to the service to get the QR code back. You are now dependent on the service being up and the network being fast and stable between you and the service. Second is the (likely) closed nature of the service; you have no way of vetting the code to make sure there are no shenanigans behind the curtain.

Given all of that, I stuck with the default Google service. Google knows just a little bit about keeping a service up and running, and their QR code service has likely been battle tested as much if not more than any other third party library I could use locally. However, the RobThree documentation provides an easy example of using a local library should the need or desire to switch arise.

Drifting away...

It was demo day; time to practice before presenting my work to the rest of the team! I'll just plug in my username and password... Type in the token from my device, and... Wait... Why am I not logged in? What did I break with my last commit?! All my work is for naught! I'm a frauuuud!

OK... OK... calm down... There must be a logical explanation. What would make a token work yesterday but not today? This is a time based protocol... My phone is setup to automatically keep my time correct. Let's check the time on my server... AHA! My local vagrant instance is not running any time synchronization and has decided to drift away by about an hour. One quick NTP query to fix that, and... We're back in business! Whew... Crisis averted; demo proceeds without issue.

I've learned an important lesson about TOTP. Make sure your server is automatically keeping the time correct!

Dude... Where's my phone?

If you are like me, you have used two factor authentication on other sites and have come across "recovery codes". These are meant to be written down and stored offline; if you were to ever lose the device that generated the token for the site, you could enter one of these codes to complete authentication and establish the shared secret on a new device. While I had an idea in mind of how this could be implemented, I wanted to see if there were any established best practices people follow. How many codes should be generated? How should you generate each code? What is the best way to securely store them?

After some digging, I found... nothing. I've seen sites provide anywhere from five to ten codes with the codes varying in length. I have yet to implement this feature but am leaning to at least generating five codes. However I end up generating them, I will store them exactly like passwords -- as encrypted salted hashes.

I need more...

One other flow I have encountered with other two factor enabled sites is the need to input multiple tokens if the server seems to think your token is out of sync. Again, I could find no information on best practices. How many tries should you give the user before entering this flow? How many tokens should you ask for? Does this really add any security value? For now, I am unlikely to implement this flow. While some big names use it, I'm not seeing much benefit from this flow versus just allowing the user to keep entering a single token.

That's all folks!

The RobThree library made it easy to add two factor authentication to our application. Follow the examples in the documentation, and you'll be up and running in no time. However, there seem to be no best practices (none I could easily surface at least) around the items like recovery codes and "out of sync... give us more than one token to proceed". Did I miss anything? Have any best practices from your own implementations? Sound off in the comments and let me know.


Staatus: Exploring the Slack API

Back in April, Slack released a cool new feature that allows you to set a status message on your account. Some of the examples they provide are:

  • In a meeting
  • Commuting
  • Out sick
  • Vacationing
  • Working remotely

"This is awesome!," I thought. "Now I can do what did on AIM in 1997!"

Slack did sprinkle this status in various places in the UI, but it's still a pain to go searching for it, especially if you haven't chatted with a person in a while. Plus, there doesn't seem to be an easy way to see a compiled status for a group (e.g. @engineering-team).

Enter: Staatus

I built Staatus on a PHP framework called Silex. It's a microframework based on Symfony that provides the guts for building simple single-file apps. Here's an example:

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/hello/{name}', function($name) use($app) {
    return 'Hello '.$app->escape($name);
});

$app->run();

Staatus allows you to see a compiled status of an individual, a particular team, or everyone in a channel. The code is over on our Github.

I have to hand it to the devs at Slack. The API was super-easy to work with. I made use of these REST commands:

With that, I was able to display both status emojis/messages, but also a blue diamond if the person is online:

The Code

Coding this up was very straightforward. I'd say the only quirk I ran into is that the calls take too long, and Slack does not like that. If your plugin doesn't return within a few seconds, you get an error message. My plugin is hosted on Heroku, so between the lag of Heroku waking up instances and the time it takes to run all the API calls (which can amount to many, especially when Staatus is run against a team name), I needed to figure out a way to return a delayed response. Normally, in a single-threaded language like PHP, that's not easy. Most frameworks follow a very "serial" manner of generating a response:

  1. A request comes in (possibly with parameters).
  2. A response is generated.
  3. The response is returned and the request dies.

So if step 2 was taking too long, how was I going to work around Slack's request time limits? The answer comes in Silex's $app->finish() method. It is documented as:

A finish application middleware allows you to execute tasks after the Response has been sent to the client (like sending emails or logging)

Here's how I used it:

$process = function(Request $request) use($app) {

// first, validate token
 $token = $request->get('token');
 if (empty($token) || $token !== VERIFY_TOKEN) {
 $app->abort(403, "Invalid token.");
 }

$response = [
 'response_type' => 'ephemeral',
 'text' => 'Gathering staatus...'];

// just return; the rest of the processing will happen in finish()

return $app->json($response);
};

$app->get('/', $process); // for testing
$app->post('/', $process);

$app->finish(function (Request $request, Response $response) use($app) {
...
}

As you can see, my $process method returns immediately and I do the rest of the processing in a finish() method. This allows me to take as long as I'd like (give or take) to return a response back to Slack using a one-time response URL they provide. (Technically, you can't take as long as you'd like to respond. Slack has a hard limit of "up to 5 times within 30 minutes"):

$response = [
 'response_type' => 'ephemeral',
 'text' => $text];

$client2 = new Client(['base_uri' => $responseUrl]);
 $response2 = $client2->post('', [
 'json' => $response,
 'verify' => false
 ]);

And that's all, folks. So, go ahead and download Staatus, deploy it on Heroku, and you'll be partying like it's 1997 all over again. BOOYAH!


Traackr :hearts: Instagram

As we continue to support the influencer marketing programs of our clients, we have found it imperative to consume and dig as much as we can out of influencer content created on Instagram. Adding to the consumption of post captions and metrics for engagement reports, Traackr also gives users the ability to harvest the photo tags on influencer posts and make them searchable !!! :)  

Ready? Check it out.
Let’s look at the Traackr profile of the most decorated olympian in history:

Michael Phelps' Traackr influencer profile.

Now, let’s find a post that has photo tags on it.   Oh look...here’s a good one (they seem to be having a lot of fun eh?):

Michael Phelps' instagram post viewed from his Traackr influencer profile.

Now let’s search for one of those tags. I like @casamigos too… read my mind :wink:wink:  Voilà!

Searching photo tags through Traackr.

But … I thought keyword queries only matched the actual content of the post. All I see is ‘Boys will be boys!!! #meldman’. How did you do it?”  

Well… here’s an oversimplified explanation of how it works.

Making photo tags searchable at Traackr.

So, at step (1) we get the post from Instagram’s public API. At step (2), we store it in our search engine and at step (3) we query for “@casamigos”.  And yea...you guessed it! The real magic happens at step (2).

When we’re indexing content, we append the photo tags to a secret field that keyword queries are executed against. But what we surface in the UI is a field that contains the original post “Boys will be boys!!! #meldman”.

Since you’re such a curious cat, here’s an excerpt of what the record looks like in our search engine:

{
  "_type": "post",
  "_source": {
    "postUrl": "http:\/\/instagram.com\/p\/BTIKhMygox-",
    "rootDomain": "instagram",
    "author": "m_phelps00",  
    "postContent": "Boys will be boys!!! #meldman @randegerber @makenagbc @jjd7007 @stuttsydlc @casamigos @romanstutts",
    "postDisplay": "Boys will be boys!!! #meldman"
  }
}

Hint: See the difference between postContent and postDisplay?

So why do we do this?

We want to do more than just track Instagram content to compute the metrics that allow us to analyze an influencer’s reach and resonance. We believe that with Instagram’s ever growing outreach and business impact, the more value we derive from its content, the more meaningful will be the insights we provide to organizations that invest in the practice of influencer marketing.

As it pertains to this particular feature, our customers are able to get more insights on brand mentions by using our platform to match mentions on photo tags and get further analytics and reports on them :)


Great Scott! HackWeek 5/1 Recap

Prologue

It’s 6am on a Thursday morning, and I’m realizing the feature I had built last night to demonstrate Vue.js’s double-binding capabilities has regressed due to some code-reorganization I decided to do last-minute.  I thought I had done a good thing, but I ignored my sensibilities to quit while I was ahead and just do that “one last thing”.

So I put on a pot of coffee, and I spent the next few hours not only fixing what I had broken, (in order to make sure my demo doesn’t fall flat on its face in front of my esteemed colleagues), but I also tried to strategize the best way to communicate the week-long and tearful journey towards carving out a path to refactoring an important yet 3-year old feature on our app, in a way that employs the best that VueJS has to offer without throwing the jQuery baby out with the bathwater, all in 360 seconds. Why? because it’s our Hack Week Demo Day!

Hack Weeks @ Traackr

Once a quarter, we take a collective pause from roadmap-focused development, and carve out an entire week for the engineering team to work on projects of their own. What started out as a monthly hack day, we quickly realized that a single day was not enough for any of us to really flesh out let alone implement our ideas. Experimentation needs time and iteration if it would materialize into something solid; we needed more than a day to experiment, fail, retry, and repeat!  So, we decided to have our hacks less frequently but for a much longer period of time, and thus Quarterly Hackathon was born.

The 5/1 Hackweek Recap

This particular Hack Week arrived shortly after we completed a project that the entire Engineering team had been working on for the good part of 6 months. The project was a set of tremendous improvements and new functionality added to the Analytics Suite of the Traackr App, altogether has been named Integrated Influencer Intelligence (or I3).

The temptation after such a sizable release, is to use this unstructured time to make all those small improvements to what we just released vs. spending the time looking at new problems with fresh eyes. This time around, most of the team spent time on fairy new ideas, with some folks improving on existing ones.  By the time the week ended we a whole collection of demos and proof of concepts ranging from: Devops dashboards, to Slack integrations, to enhancements to security, just to name a few.  But like most Hack Weeks at Traackr, it was a great time to shift gears, recharge, and inspire new ideas not just for our team, but for the company as a whole.

So, without further ado, let’s dig into some of the Traackr team’s Hack Week projects, in the gallery below:

Our 5/1 Hackweek Projects Gallery

The gallery below only describes high level info on the projects.  More in-depth articles about our Hack Week is still to come!


Introducing: Enragement

Traackr is the leader in the Influencer Management space. Our platform is an enterprise system of record to manage, expand, validate, and scale an influencer marketing program. Though there are others that try to copy us, we feel we do it best. That's why we are excited to announce an upcoming feature: Engagement. Our customers will now be able to accurately measure engagement with influencers.

But we didn't want to stop there. Let's face it, once we release this feature, there will be others not far behind with similar functionality. So we are already busy working on the NEXT NEXT big thing in influencer management.

Introducing the NEXT NEXT big thing that NO ONE else is offering: Enragement. What is enragement? It is the perfect feature in these highly polarized times. Our “secret sauce” is an algorithm that measures not only how ENGAGED an audience is with a tweet, but how ENRAGED the author is.

Interestingly, they are two sides of the same coin – symbiotic concepts that feed off of one another. The more ENRAGED an author is, the more ENGAGED their audience becomes.

Take this series of tweets, for example. On the heels of a difficult meeting with Angela Merkel and a congressional hearing about investigations into Russian election-tampering, the POTUS sent out these tweets:

Our enragement algorithm kicked in and gave these tweets an enragement index of “TTF” (“Through the Roof”). Within hours, the tweets had thousands of replies, retweets, and favorites. Imagine if these tweets were about your product. That's money in the bank. YUGE!

How do we do it? Well, there's only so much we can divulge about our secret sauce. This diagram provides an overview of the non-confidential aspects of the algorithm:

Running any text through our algorithm will measure its rage score through a proprietary combination of:

  • bad grammar (a sign of anger)
  • overuse of CAPS
  • repeated characters (especially exclamation points)
  • cursing
  • a selection of low-brow emojis (e.g. “poo”)

That's all we can share for now. If you'd like to see a demo of how your influencer marketing programs can utilize our special algorithm to craft the perfect tweets for maximum enragement, please call our sales team today.

HAPPY APRIL FOOLS' DAY!


Setting up your Mac

Setting up your Mac

Setting a performance budget - TimKadlec.com

Setting a performance budget - TimKadlec.com

How to Avoid One of the Costliest Mistakes in Software Engineering

How to Avoid One of the Costliest Mistakes in Software Engineering

Stop Feature Creep with an 'Anti-Roadmap'

Stop Feature Creep with an 'Anti-Roadmap'

Crittercism: Scaling To Billions Of Requests Per Day On MongoDB

Crittercism: Scaling To Billions Of Requests Per Day On MongoDB