Happy Birthday Devise

Today we are celebrating Devise‘s birthday. But wait, if you have started watching Devise since the beginning you may be asking: has Devise already completed one year of life? Nope. Today we are completing exactly 4 months since Devise was released at Rails Summit Latin America 2009. And we are very proud and glad to say that we have just reached version 1.0! Yeah! Let’s celebrate and talk a bit about history.

The beginning

We decided to build Devise based on some requirements we had in a project last year. The majority of our projects usually require an admin interface to configure the application with some CRUD information. And in this specific project, we were needing two different roles in the same application, the admin itself with all its powers to manage the application, and the end users that should be signed in to do some stuff inside the application. Usually only one model would be required in this situation, with some “type” column or flag to determine if the user is an admin or not, right? Okay, but we didn’t like this approach that much. So we started looking at some of the possibilities:

  • Authlogic: a really great piece of code and functionality, but a bit messy by handling the session in a model. It also only handles the model part.
  • Clearance: full stack, Rails Engine, extra modules, everything we needed. However, packaged with a User model and without the ability to customize it.

Okay, we could pick one of these and with a bit of extra work we would achieve our requirements. But would we need to do it every time this situation happens? We said no. It’s not DRY enough. And we like DRY. So Devise was born.

The main objective of the first Devise version was to get up and running the entire sign in process, including password recovery and confirmation stuff. And everything should work with different roles, which mean you could easily plug and play an Admin, User, Account, or whichever role you needed, in your application, without much effort. And we had a deadline: Rails Summit. It took almost 1 month of work before Rails Summit. I still remember the days before the event, we putting a lot of effort to have Devise up and running, and the README being written during the event. So, we were ready there and presenting Devise to the world.

How it works

Devise was born with the intuit of handling different roles without effort, automatically, and it is achieved with Rails Engines. In addition, Devise is build in top of Warden, a great rack authentication framework. It allowed us to be flexible enough and add different strategies, hooks, and modules easily. In short, Devise:

  • Is Rack based;
  • Is a complete MVC solution based on Rails Engines;
  • Allows you to have multiple roles (or models/scopes) signed in at the same time;
  • Is based on a modularity concept: use just what you really need.

The road so far

Devise has started with the basic modules needed for that specific application:

  • Authenticatable: responsible for signing users in through a basic login form, handling password validation and authentication.
  • Confirmable: manages confirming users account.
  • Recoverable: handles password recovery.
  • Validatable: basic email and password validation.

Okay, everything we needed were there. Everything else was in a wish list, nicely called TODO. And we decided from the beginning to not add features to Devise until us or somebody else really needed them. But people asked, people needed new features. And they were always there to help, to fork and fix a bug, to comment. We started soon to add new features, the first was:

  • Rememberable: handles signing users in automatically from cookies.

After people were asking for easier ways to create their migrations, so we introduced a new module with Devise 0.2:

  • Migratable: hooks into ActiveRecord migrations to add helper methods for creating Devise colums. So you can do stuff like t.authenticatable, t.confirmable and so on.

To help people getting up and running faster, we created some generators. Now they are:

  • script/generate devise_install: create devise initializer file to enable some configs and copy default locale file.
  • script/generate devise MyModel: create a model with setup for Devise, routes and migration.
  • script/generate devise_views: copy all Devise views to your app/views folder, so you can change it as needed.

Devise 0.3 and 0.4 came soon after, with a lot of bug fixes in generators, I18n, initialization, some deprecations and a bunch of code refactored.

Contributions from community were coming more and more. The first big contribution came with the addition of encryptors. Nowadays Devise supports encrypting passwords with SHA1, SHA512, and BCrypt. It has also support for using the same encryptors as Authlogic, Clearance and Restful Authentication, to help you migrating from these solutions.

At this point we thought: okay, that should be enough. It wasn’t. People needed different ORMs, other than ActiveRecord. So we introduced support to MongoMapper and then we were reaching Devise 0.5.

We were receiving a lot of issues with functional tests, so we introduced some test helpers to help people with the sign in/out process in this kind of tests called Devise::TestHelper.

As applications grow, more roles may be needed. So we created the possibility to scope your views for each role/scope in your application. This way your user can have a different sign in view than the admin, for example. Reaching Devise 0.6, a lot of improvements on routes and DataMapper support were added.

We were full of nice ideas to add new features, and our TODO was bigger than we like. So we came up with:

  • Timeoutable: verify each request to timeout the user session after a certain period of inactivity, asking for credentials again.
  • Trackable: records how many times each user has signed in, last timestamps and ips.

Also the loading process and ORM support received a lot of work before launching Devise 0.7.

For Devise 0.8 we looked at tests for MongoMapper and the code got a great review. Also some work was done to get Devise up and running with latest version of Warden and its new features, such as serializers. We also extracted a new base module from Confirmable:

  • Activatable: allow setting up extra activation methods for your models.

We were receiving a lot of feedback from the community, and then we merged a cool new feature:

  • Lockable: lock accounts based on a number of invalid sign in attempts.

Following the same pattern from Rails in this commit we moved flash messages to :notice and :alert, and released Devise 0.9. Step by step the 1.0 version was coming.

What is new

Devise 1.0 introduces a lot of cool features. The community seems to be really appreciating Devise, and we’ve received another great contribution:

  • Token Authenticatable: validates authenticity of a user while signing in using an authentication token (also known as “single access token”).

In addition, we created the two most requested features for Devise:

  • Registerable: handles sign up users through a registration process, and also editing/updating user info and deleting user account.
  • HTTP Authenticatable: http basic authentication.

We also added the possibility to use Migratable while editing a table using change_table, among other fixes.

What comes next

We are preparing a new release of Devise fully compatible with Rails 3. It means Devise has now closed its development for new features in Rails 2.x. We are still going to maintain a 1.0 branch in github for bug fixes to keep everything up and running.

In the end

We would like to say thank you to everyone who has helped us achieve 1.0 version and who is using Devise, testing, creating issues, and giving all this feedback.

Also, for those who were at Rails Summit last year, we proposed something: get the biggest number of watchers on github as fast as possible! When we presented Devise, there were 7 watchers, and if I am right we were 4 of them. At the time of this writing we have 762 watchers. Yeah! I think I can take the risk and say we accomplished it. Thanks!

Let’s celebrate Devise 1.0, and look forward to see Devise and Rails 3. Enjoy!

Happy birthday Devise!

36 responses to “Happy Birthday Devise”

  1. Trevor Turk says:

    Great work, everyone. Devise is totally awesome. Thank you!

  2. Trevor Turk says:

    Great work, everyone. Devise is totally awesome. Thank you!

  3. Very nice! Devise was the first open source project I contributed. It’s a great feeling to see it growing up. Thanks do everyone.

  4. Very nice! Devise was the first open source project I contributed. It’s a great feeling to see it growing up. Thanks do everyone.

  5. Rizwan Reza says:

    Devise is the best authentication solution for Rails so far, very nice work. Thanks!

  6. Rizwan Reza says:

    Devise is the best authentication solution for Rails so far, very nice work. Thanks!

  7. Dave Porter says:

    Hi there, Well done on your progress with Devise…

    Although following Rails for a while I rank myself as a Rails newbie!, I don’t use it everyday and have struggled with most of the other authorization systems.

    But with yours I just started a new project with your demo and can see immediately how easy it is to give me everything I need to get started.
    All the Best…
    ps Also checking out your other projects – looks interesting…

  8. Dave Porter says:

    Hi there, Well done on your progress with Devise…

    Although following Rails for a while I rank myself as a Rails newbie!, I don’t use it everyday and have struggled with most of the other authorization systems.

    But with yours I just started a new project with your demo and can see immediately how easy it is to give me everything I need to get started.
    All the Best…
    ps Also checking out your other projects – looks interesting…

  9. iain says:

    Great work, I love how easy it is to customize it, with methods that beg to be overridden. Never have I seen an authentication solution in which you can add single sign on, ldap and gmail authentication all in under one day’s work, and still keep the source clean.

    Keep up the good work! Hope Rails 3 support comes quickly!

  10. iain says:

    Great work, I love how easy it is to customize it, with methods that beg to be overridden. Never have I seen an authentication solution in which you can add single sign on, ldap and gmail authentication all in under one day’s work, and still keep the source clean.

    Keep up the good work! Hope Rails 3 support comes quickly!

  11. NonRailsUse says:

    How is this factored for non-Rails Ruby use?
    Possible?

    All best, MarkT

  12. NonRailsUse says:

    How is this factored for non-Rails Ruby use?
    Possible?

    All best, MarkT

  13. José Valim says:

    Mark, Devise is a Rails Engine and unfortunately you cannot use it outside Rails.

  14. José Valim says:

    Mark, Devise is a Rails Engine and unfortunately you cannot use it outside Rails.

  15. Anrake says:

    Awesome plugin. I haven’t implemented it on my site yet, but just playing around this weekend testing this against other systems has me impressed enough to leave this comment. I’ll be using Devise going forward with my project. So easy to implement and works perfectly. A little more documentation would be nice, but it hardly needs any. Devise_example helped a lot. I also love all the user stats that are tracked. Looking forward to your continued efforts !

  16. Anrake says:

    Awesome plugin. I haven’t implemented it on my site yet, but just playing around this weekend testing this against other systems has me impressed enough to leave this comment. I’ll be using Devise going forward with my project. So easy to implement and works perfectly. A little more documentation would be nice, but it hardly needs any. Devise_example helped a lot. I also love all the user stats that are tracked. Looking forward to your continued efforts !

  17. Mihael Konjević says:

    I really like devise, but it broke my login after upgrading to 1.0. I know this is not the place for bug reports, but I have to do some investigation before filing proper bug report 🙂

  18. Mihael Konjević says:

    I really like devise, but it broke my login after upgrading to 1.0. I know this is not the place for bug reports, but I have to do some investigation before filing proper bug report 🙂

  19. Jazz says:

    Any idea on how long Rails3 development might take?

    Would be more than happy to be a beta tester 🙂

    Since this is the Authentication framework i WANT to use 🙂

  20. Jazz says:

    Any idea on how long Rails3 development might take?

    Would be more than happy to be a beta tester 🙂

    Since this is the Authentication framework i WANT to use 🙂

  21. @Jazz we’re working on this and willing to get it working asap. We will let everyone know and test it before we launch a Rails3 version ok. Stay tunned in github, there are already some other people with forks doing some work on it. Thanks.

  22. @Jazz we’re working on this and willing to get it working asap. We will let everyone know and test it before we launch a Rails3 version ok. Stay tunned in github, there are already some other people with forks doing some work on it. Thanks.

  23. @Mihael after doing some investigation to be sure it’s be a Devise bug, please use the github issues, we appreciate. Thanks =).

  24. @Mihael after doing some investigation to be sure it’s be a Devise bug, please use the github issues, we appreciate. Thanks =).

  25. @Marcelo we really appreciate your effort on helping Devise getting to 1.0, thank you. Keep up the good work.

  26. @Marcelo we really appreciate your effort on helping Devise getting to 1.0, thank you. Keep up the good work.

  27. Millisami says:

    Anybody have any tips on how to migrate from restful_authentication to devise?

  28. Millisami says:

    Anybody have any tips on how to migrate from restful_authentication to devise?

  29. José Valim says:

    @Millisami, I can only tell you that you need to change your column names and that Devise has a restful_authentication compatible encryptor (so you can reuse the password in your database). We never migrate, so we cannot add you any further. Maybe you should try the mailing list?

    http://groups.google.com/group/plataformatec-devise

    Regards!

  30. José Valim says:

    @Millisami, I can only tell you that you need to change your column names and that Devise has a restful_authentication compatible encryptor (so you can reuse the password in your database). We never migrate, so we cannot add you any further. Maybe you should try the mailing list?

    http://groups.google.com/group/plataformatec-devise

    Regards!

  31. Off Topic says:

    Hi there!

    Isn’t the any https://lighthouseapp.com/ account for devise ?

    I think I found a bug, using devise 1.1pre on 3.0.0.beta.

    When I try to cancel an account (using a :delete method on /users), and if the user had logged in using “remember me”, rails generate a “TypeError (can’t modify frozen hash)”

    Trace following:

    activerecord-3.0.0.beta/lib/active_record/attribute_methods/write.rb:26:in `[]=’
    activerecord-3.0.0.beta/lib/active_record/attribute_methods/write.rb:26:in `write_attribute’
    activerecord-3.0.0.beta/lib/active_record/attribute_methods/dirty.rb:57:in `write_attribute’
    activerecord-3.0.0.beta/lib/active_record/attribute_methods/write.rb:13:in `remember_token=’
    .gem/ruby/1.8/gems/devise-1.1.pre/lib/devise/models/rememberable.rb:51:in `forget_me!’
    .gem/ruby/1.8/gems/devise-1.1.pre/lib/devise/hooks/rememberable.rb:27

    I have also a “WARNING: Can’t mass-assign these protected attributes: remember_me” on POST “/users/sign_in” having “remember_me”=>”0” in parms.

  32. Off Topic says:

    Hi there!

    Isn’t the any https://lighthouseapp.com/ account for devise ?

    I think I found a bug, using devise 1.1pre on 3.0.0.beta.

    When I try to cancel an account (using a :delete method on /users), and if the user had logged in using “remember me”, rails generate a “TypeError (can’t modify frozen hash)”

    Trace following:

    activerecord-3.0.0.beta/lib/active_record/attribute_methods/write.rb:26:in `[]=’
    activerecord-3.0.0.beta/lib/active_record/attribute_methods/write.rb:26:in `write_attribute’
    activerecord-3.0.0.beta/lib/active_record/attribute_methods/dirty.rb:57:in `write_attribute’
    activerecord-3.0.0.beta/lib/active_record/attribute_methods/write.rb:13:in `remember_token=’
    .gem/ruby/1.8/gems/devise-1.1.pre/lib/devise/models/rememberable.rb:51:in `forget_me!’
    .gem/ruby/1.8/gems/devise-1.1.pre/lib/devise/hooks/rememberable.rb:27

    I have also a “WARNING: Can’t mass-assign these protected attributes: remember_me” on POST “/users/sign_in” having “remember_me”=>”0” in parms.

  33. José Valim says:

    Off Topic, please use the issues tracker on Github for bug reports.

  34. José Valim says:

    Off Topic, please use the issues tracker on Github for bug reports.

  35. Daniel Kehoe says:

    Happy Birthday, Devise!

    I’ve put together an example app that shows how to use Devise with
    subdomains:

    http://github.com/fortuity/subdomain-authentication

    It’s written for Rails 2.3 and uses Matthew Hollingworth’s subdomain_routes gem. It demonstrates the flexibility and ease-of-use of Devise.

  36. Daniel Kehoe says:

    Happy Birthday, Devise!

    I’ve put together an example app that shows how to use Devise with
    subdomains:

    http://github.com/fortuity/subdomain-authentication

    It’s written for Rails 2.3 and uses Matthew Hollingworth’s subdomain_routes gem. It demonstrates the flexibility and ease-of-use of Devise.