• We are trusted partners of:
BlogDevelopment

TokenBundle

A while ago, we needed a solution to secure some URLs for single use. As this problem seemed to be quite common, we thought of making a reusable solution, which resulted in a separate Bundle that we used in several projects, and updated it to best fit other encountered situations.

We believe this could be useful to other projects, as well, so we’ve decided to make it open-source and share it with the community.

This article introduces you with this TokenBundle, and describes a few situations in which it can be used, along with examples.

When to use? / Purpose

The goal of TokenBundle is to provide a means to validate/restrict actions taken by users.

The validation is achieved by using a hash, which could, for example, be embedded in a URL, be it in an email or a link generated on-the-spot inside a page.

Basic usage includes securing an action by enforcing the link to work only once.

Other use cases include:

  1. It could be used for securing an account activation link for a given user, valid only for 1 day – by setting the expiry time.
  2. Another use case could be allowing a user to vote, the change this vote only 3 times – by setting a max uses value of 4.
  3. A slightly more advanced situation could be securing a forgot password link, enforcing the change to be made from a given IP, in a time frame of 1 hour since the email was sent – however, this scenario requires using the additional data and implementing some custom rules validation conditions.

Why to use? / Strong points

This bundle provides a clean way for generating Tokens, and then validating, respectively consuming them. It exposes a service, innobyte_token, which abstracts all the work needed for common situations.

The only dependencies are Doctrine and Dependency Injection, so no third party library is needed.

Unit testing offers the needed confidence in terms of reliability for future development, containing over 20 tests and 80 assertions, with 100% code coverage for Service and Entity.

Another benefit is that the code is well commented and documented, and detailed usage examples are provided inside the README.md file.

The Database table structure is optimized in both storage (by choosing the right field types) and search performance (by using indexes and properly ordering columns, which is particularly useful for tables containing many rows, as such).

The approach for failures is throwing exceptions when something unexpected occurs.

The Doctrine Entity Manager to use is configurable (exposed in semantic configuration).

How to use? / Examples

The Service API is fairly simple and intuitive, exposing the following methods:

  • generate – used to generate the Token – the needed information includes:
    • the scope of the Token (the purpose for which it is used, such as account confirmation, password reset etc.)
    • the owner type (typically the entity name that the Token is generated for: user, project etc.)
    • the owner ID (the identifier for the owner entity)
    • optionally, the Token can be used multiple times, by setting the max uses parameter
    • optionally, an expiration time can be specified
    • also optional, additional data can be set, in order to build more advanced validation rules
  • get – used to retrieve the Token by the mandatory info provided at generation time
  • isValid – will verify if the Token is available to use, meaning: being active, with the usage number lower than the maximum usage number and expiry time not passed
  • consume – will find the Token by the given criteria (the mandatory info), and then increase its number of uses

  • consumeToken – same as consume, except it operates on a given managed Token instead of fetching it by the mandatory info provided when the Token was generated
  • invalidate – will find the Token by the given criteria, and then deactivate it
  • invalidateToken – which operates on the managed Token directly, and deactivates it

Note: managed means fetched through Doctrine, either directly from DB (less common), either through get method exposed by the service.

Advanced usage allows setting additional data for the Token (stored as an array on the entity), which can be used to implement custom validation rules for the Token (like setting an IP for which the Token is valid, or any other conditions that would have to be met at validation time, such as referrer URI, minimum purchase amount etc., or setting validation scenarios etc.).

How to install? / Setup

The installation is simple and pretty standard:

  1. The package must be added into composer.json, under the require section
  2. The bundle must be added into $bundles array inside AppKernel.php
  3. As for any bundle that uses the Database connection, the bundle must be added into entity manager’s mapping, inside config.yml. Here, local is the name of the used entity manager.
  4. If the entity manager name is different than the default default, it must be specified inside parameters.yml. Here, local is the name of the used entity manager.
  5. The Database schema needs to be updated. Here, local is the name of the used entity manager.
    to see the resulting SQL
    to actually update it

This is all the setup needed for TokenBundle to work properly.

What do you think about TokenBundle? If you find other ways of using it, plese let us know. We’re curious!

Equally, if you have feature requests or bug reports, please let us know on GitHub: http://github.com/innobyte/token-bundle

Sorin Dumitrescu

Author Sorin Dumitrescu

Hello, I'm Sorin and I consider myself to be a passionate web developer. I advocate for writing high quality code and for adherence to best practices. I also welcome any kind of challenge. :)

More posts by Sorin Dumitrescu

Leave a Reply