Hacker News new | ask | show | jobs
by drspacemonkey 2475 days ago
>I don't like Devise either

I've got my complaints about Devise, but I'll take those pains any day of the week over the alternative nightmare of "built in-house" authentication.

At this point, if somebody doesn't want to use Devise in a project I'm working on, they better have a _really_ good explanation. To me, it's like suggesting setting the building on fire.

2 comments

I've found the "out of the box one stop auth" packages rarely deliver the experience that product managers / UX people have planned for. You're usually stuck with whatever workflow the library decides for things like forgot password, password expiration policies, 2fa, login methods, etc.

There are very legitimate reasons why your SaaS app might want a nuanced workflow for these things.

> I've found the "out of the box one stop auth" packages rarely deliver the experience that product managers / UX people have planned for. You're usually stuck with whatever workflow the library decides for things like forgot password, password expiration policies, 2fa, login methods, etc.

It's pretty effortless to override and/or completely rewrite the views/flow with something like Devise.

Overriding is simple when it's changing a view. I've found the exact opposite to be true if it's anything regarding the actual workflow. If you're trying to change the workflow, you're probably already in an edge case and you're usually dealing with documentation that isn't terribly comprehensive or updated and rarely relates to the change you are trying to make. You're usually stuck reading the library internals carefully and scouring Stack Overflow for other people who have attempted to make the same change (often only to find unanswered question).

Every time I've ended up in this scenario I've wished that I had just built from scratch in the first place.

What sort of workflow are you trying to achieve? Devise is effectively `User.create(email: params[:user][:email], password: params[:user][:password])`
Here's a good example of something I worked on recently that I highly doubt is simple to implement with an out of the box solution. I could be wrong - I have no idea if Devise can do it or how hard it would be (it wasn't considered because the auth handling was already implemented):

You have a multi-tenant SaaS application that needs to support the following:

* Accounts may have different password, lockout, and expiration policies.

* There's a generic "login" button on the marketing site that 50%+ of our users use. This generic login page must implement all account specific constraints (probably via a 2-step login form)

* Some customers have SSO. For some customers, using SSO is optional. For others, it is required.

* Owners of accounts have a limited impersonation feature that allows them to see only certain parts of information in eyes of one of their account members

* Accounts may have different password, lockout, and expiration policies.

I've had to do that with Devise. It was easy enough to fork the `devise-security` plugin and modify the configuration settings to handle lambdas. The lambdas were then set to pull the config values from the user's account configuration.

* There's a generic "login" button on the marketing site that 50%+ of our users use. This generic login page must implement all account specific constraints (probably via a 2-step login form)

That's super easy.

* Some customers have SSO. For some customers, using SSO is optional. For others, it is required.

I'm in the process of adding exactly this to my project's Devise configuration right now. It's a little tricky, but only because our previous attempt at SSO was very strangely done (and I now understand why so many users complained about not being able to log in).

* Owners of accounts have a limited impersonation feature that allows them to see only certain parts of information in eyes of one of their account members

User permissions are outside the scope of Devise, since it just handles authentication. But the Pretender plugin makes user impersonation dead simple.

>I've found the "out of the box one stop auth" packages rarely deliver the experience that product managers / UX people have planned for.

I’d love to see more pushback from devs on this. So many products nowadays provide an “experience” for auth which makes things unnecessarily difficult. Not showing login and password fields on a single page, ambiguous 3rd party auth rules, weird account linking logic, etc.

Custom built auth isn't as scary as you make it to be. I have done it myself and would do it in the future. You just have to be cognizant of what you're doing (i.e. simply copying Hartl's or Railscasts' tutorial won't suffice; see session fixation attacks).

If I were to bring in 3rd party gem for auth, I'd have gone with Sorcery rather than Devise.

> Custom built auth isn't as scary as you make it to be

> You just have to be cognizant of what you're doing

These two ideas are incompatible with each other.

I would have phrased it differently, but I see the parent's point.

You don't roll your own security. You just don't do it. There are far too many variables that you can screw up, and anything you come up with isn't realistically going to go through nearly as much battle-testing as a ready-made solution (either upfront or on an ongoing basis).

> Custom built auth isn't as scary as you make it to be

Custom-built auth should be scary. Anyone who's worked on the security story for a popular framework will tell you that.

If you're not scared by it I'd have to assume you're either not seeing large swathes of the problem space or you're a genius.

But everyone rolls their own security. Security isn't a feature of the application, it's a characteristic of every piece of code, workflow, and practice your dev team implements. I know this sounds like a platitude, but if you treat security like something that you should only let the experts handle, you may end up not paying attention to the security properties that end up in your control.

Don't write your own crypto. That's great advice. The idea that everyone's auth needs are so standard they fit for every app just hasn't been realistic in my experience.

I should have phrased it differently.

Yes, you don't roll your own security. You use powerful primitives provided by Ruby and Rails, such as bcrypt, has_secure_password/has_secure_token, encrypted sessions, secure httponly cookies with prefixes + samesite attrbiute all served over TLS 1.2+, with HSTS and CSP

I'd argue that Auth itself isn't hard per se, but it involves hard things that you shouldn't roll your own, notably cryptography and session handling.

But those are things that people normally delegate to either libraries (crypto) or the framework itself (session handling).

Of course, there's lots of places one can screw up, such as sending non-expirable password reset tokens, revealing private information and membership status via F2A/reset tokens. But those are the kinds of screw-ups that can happen in other parts of the website too.

That said, Devise is one of the few things that I don't completely dislike about Rails.