Hark: Who goes there? (Call for developers)

LoginEngine is aging and was built on top of a quick-and-dirty
generator;
even James isn’t too happy with it anymore. acts_as_authenticated is
somewhat cleaner, but is a generator, and as with all generators,
there’s
no way to keep up with changes to the codebase. Neither is particularly
modular. And both of them provide some authorization as well as
authentication, and even a little user management, which further muddies
the waters.

So I’m proposing a new engine: Hark. It’s a pared-down, opinionated
engine
that answers only one question: “Who goes there?”

Hark has its roots in both LoginEngine and acts_as_authenticated. I’ve
borrowed liberally from each where their code was cleanest, and tried to
incorporate both sets of best practices.

The following features are not found in Hark, by design:

  • Authorization, such the login_required filter and its magic
    redirection.
    This is best performed by an authorization system such as
    such as Bill K.'s excellent authorization plugin1.

  • Support for extra fields. LoginEngine expected you to extend its User
    model to add your own fields. Hark prefers that you create your own
    User
    model, and declare that it belongs_to :hark_user. You can thus create
    any
    fields you want in your own model.

  • Support for delayed_delete. This is already handled by the excellent
    acts_as_paranoid plugin2.

  • Configuration options for validation. There are an infinite number of
    ways you might want to validate passwords, logins, etc.; Hark doesn’t
    try
    to anticipate them. There’s a great DSL for that already called
    “Rails”.
    Instead, just create your own copy of the hark_user.rb model, and use
    any
    validations you like. The user code is all kept in a library, not in
    hark_user.rb, so when you update to a newer version, you won’t lose your
    customizations.

The following features ARE present:

  • Passwords are hashed with a per-user salt value
  • “Remember me” cookies
  • E-mail verification upon registration (by release)

The following principles guide Hark’s development:

  • Extension over configuration. Rather than trying to build in
    configuration options for every possible use case, make hark easy to
    extend
    without losing the benefits of shared code. That means:

  • Be modular. All code, both controller and model, is in a properly
    abstracted, verb-based library that takes care of things like cookie
    creation, session management, attribute setting, etc. For instance, the
    controller code for login looks like:

    def login

    hs = Hark::Session.get(session, cookies)

    unless hs.login(params[:hark])
    flash.now[:warning] = ‘Login unsuccessful’
    return
    end
    end

And this controller code itself is just the default login screen, which
will most likely be overwritten by your own controller.

  • Play nice with others. Hark should be able to take advantage of
    plugins
    like acts_as_paranoid, secure-action-plugin, etc. instead of trying to
    roll
    its own.

  • Be paranoid. An awful lot of Rails code doesn’t check its state or
    inputs, because the end result is usually nothing worse than an
    “Application error”. In login code, we have to be a little more
    careful.
    To the extent that Rails allows, we should watch out for race
    conditions,
    session fixation attacks, etc.

  • Be behavior-driven. All code in Hark is developed using rspec. I’ve
    attached the current specdoc below.

  • Be correct. That seems self-evident, but again, because Rails is so
    easy
    to work with, there’s a lot of “programming by coincidence”. To the
    extent
    that Rails allows, we should take advantage of locking, transactions,
    and
    update granularity so that things like multiple simultaneous logins are
    not
    an issue on larger systems.

  • Be useful. I see too many posts saying that “AAA/LoginEngine/etc are
    great starting points, but I always end up having to rewrite them.”
    Yes, a
    lot of authentication is system-specific - is your back end LDAP, or a
    Rails table? - but the basic transaction sequences are usually the same.
    Hark should be able to cope with that, while still providing a framework
    for extension. You shouldn’t NEED to roll your own; there are too many
    common mistakes that we already know how to avoid.

  • Stay focused. Hark should not attempt authorization or user
    management.
    It’s purely about authentication and its dependencies, such as
    registration
    and verification.

So… that’s the goal. Right now, it’s in its infancy; I’ve just
completed
basic login and remember-me functionality, and I’m starting to work on
registration. The codebase is at http://svn.jay.fm/public/hark. It’s
not
even an engine at the moment, pending some resolution on the engines bug
with Dependencies in Edge Rails. I’d love to have someone to work with
on
this, especially someone with a systems background who can bring
additional
large-scale discipline to the project.

Interest? Questions?

Jay



specdoc:

The HarkController

  • should allow Vlad the valid user to log in
  • should have no current_user if Vlad provides the wrong password

The HarkController, given Louie the logged-in user

  • should set current_user to be Louie
  • should redirect Louie to the index page by default
  • should redirect Louie back to his previous page if he has one
  • should set Louie’s token if he asks to be remembered
  • should prevent Louie from logging in twice

The HarkController, given Remmie the remembered user

  • should log Remmie in automatically

A HarkSession, when Louie logs in

  • should update Louie’s current last_login_at
  • should have Louie as current_user
  • should not have set any of Louie’s cookies
  • should not have remembered Louie
  • should prevent Louie from logging in again

A HarkSession, asked to remember Louie at login

  • should set Louie’s hark_token cookie
  • should remember Louie

A HarkUser in general

  • should not be able to be created via ‘new’

Reggie the registering user

  • should have an account created
  • should have his e-mail marked as unverified

Reggie, when attempting to register

  • should not be able to register without a password (FAILED - 1)

Vlad the valid user

  • should be able to authenticate with his password
  • should not be able to authenticate with the wrong password
  • should be able to login with his password
  • should not be able to login with the wrong password
  • should be able to login with spaces around his username
  • should be able to login with spaces around his password

Louie the logged-in user

  • should get a remember_me token back when he asks
  • should be able to log in with his token
  • should not be able to log in with an expired token

Hi Jay,

I think this sounds like a great project, and you seem to have made the
right choices, at least for my liking. What could be extra cool, was to
have
an ambition about being completely CRUD using Simply RESTful, most of
all
because I’d like to learn from that accomplishment - and it would 100%
compatible with all the nice API stuff etc. coming out of that.

I also think your spec is really nice - it seems map perfectly to a set
of
integration tests. Is this some kind standard; rspec?

I can probably find some time to give a hand with development, but I
can’t
offer any particular expertise. Anyway, uou can always count me in for
some
testing and feedback when you are ready for that :slight_smile:

Cheers,
Casper F.

On Wed, 20 Sep 2006 16:57:37 +0200, Casper F. wrote:

I think this sounds like a great project, and you seem to have made the
right choices, at least for my liking. What could be extra cool, was to have
an ambition about being completely CRUD using Simply RESTful, most of all
because I’d like to learn from that accomplishment - and it would 100%
compatible with all the nice API stuff etc. coming out of that.

I’ve thought about that, but I’m not convinced yet that CRUD maps nicely
to
the idea of logging in. In fact, most of the time, I suspect, you’ll
never
even explicitly call the login action; you’ll be going to a page on the
site, and it’ll have a before_filter to an authorization function that
will
redirect you to the login page.

Of course, since the controller itself is so lightweight, there’s
nothing
preventing you from defining your own CRUD actions, whether you are
mapping
CRUD to the account or to a login session. I expect that the built-in
controller will serve as a scaffold more than anything. But, to me,
verb-based actions are a better choice for Hark, at least till I see an
argument otherwise!

I also think your spec is really nice - it seems map perfectly to a set of
integration tests. Is this some kind standard; rspec?

Good eye - they are, in fact, the output of running a set of tests using
rspec (http://rspec.rubyforge.org). rspec doesn’t yet do integration
tests
in the Rails sense (multiple controllers/simultaneous sessions), so I’ll
probably end up writing those under Test::Unit, but someday I hope this
project can be completely spec-driven.

Jay

Hello all,

We have a bizarre problem I haven’t been able to figure out. We have a
site with the UserEngine (and LoginEngine) stuff installed. As I
understand it, I should be able to create a UserController class in
app/controllers/ and have it automatically overload the UserController
in the engines. However, something’s been happening recently to this –
our site acts like the methods in
vendor/plugins/userengine/app/controllers/user_controller.rb don’t
exist.

Models and other aspects of the UserEngine work fine.

Any thoughts or ideas would be much appreciated . . .


						Shane Iseminger
						Principal
						Ethos Media Creative Group
						www.ethosmedia.com
						719.589.2800

How’s the development of Hark coming along? Any progress?

  • James

On Sun, 7 Jan 2007 13:56:50 +0000, James A. wrote:

How’s the development of Hark coming along? Any progress?

Sadly, I’m no longer working on the project that I was using it for, so
it
sits unused and incomplete (and not Engine-ified) at
http://svn.jay.fm/public/hark. Presumably I’ll need a login module for
some project someday soon and finish it up…

Jay