Symfony3: JWT Authentication w/ Login Attempt Limits

One of my current projects is using JWT Authentication for an API built on Symfony (shocker, I know). One of the things I wanted to build into this was a limiter on the number of “login” attempts for the API that would lock someone out for x minutes after n failed attempts; mirroring typical traditional form login behavior.

This was accomplished with the following components:

  • Separate non-entity-driven database table
  • Parameters for defining the number of minutes to lock and the number of attempts before triggering a a lock.
  • A simple handler to check our table and do some simple maintenance and querying.

Separate non-entity-driven database table

The database table to track login attempts needed to be separate from a Doctrine (the ORM in this case) entity because a failed attempt naturally did not map to a real User. Similarly, we didn’t want to track ip_addr of logged in users because we are not Vizio. So, that being said, we created a very simple database table to track login attempts by ip_addr:

Parameters

Again in this case, we wanted to parameterize the values we used to determine the number of attempts, and the number of minutes a user was locked out from attempting to login. With Symfony this is a simple addition to the parameters file.

It’s important to note that timezone is very important here for comparing dates (later), so make sure when you define this (or if you ever change it) that you clear out the login_attempts table as well.

LoginAttemptHandler

Most importantly, we had to build a simple handler to manage our queries and maintenance actions. Ultimately, this is where the magic happens but the most important part is still last where we handle the actual logic in our Authentication controller (see below). However, this handler does the heavy lifting, and does have some room for improvement, particularly with Unit Testing.

Define LoginAttemptHandler as a Service

Symfony needs to understand this handler is a service, so we can use it in our Controller (next).

Handle Login Attempts in our Authentication Controller

Now, every time there is a JWT Token request, we have a slight amount of extra overhead to verify login attempts in our Controller.

 

“Smart” Accessor in Doctrine Entity

Easily add some logic to filter out specific entities from an ArrayCollection in Symfony2. In this simple example, I wrote an app that had Node, and Comment entities separately, as well as an explicitly defined NodeComment entity. In my Node entity, I want to serialize all of the associated comments. But rather than call ->getNodeComments() and then filter in AngularJS (or Twig, or whatever else for that matter), I just want to know that my object node.comments are the actual comments I care about.

The Entity property

The Accessor

Now, my serialized object.comments are the actual comments, instead of the ManyToMany Entity.

Load all mapped Entity classes from Doctrine

Ever wanted to create a simple dropdown of all the Entity classes you have mapped in Doctrine? I have! For a recent project I needed to create a sample API form and load the entity type first, so I needed a way to properly load every Entity that’s mapped programmatically and not with an ugly manually created array:

For this, I also applied Doctrine’s Inflector so I could make the key value of my array the pluralized version of the entity name. This was useful for my purposes, but probably isn’t a standard use case. Most use cases I imagine would simply want the simple class name: