[HN Gopher] Rails authentication from scratch
___________________________________________________________________
Rails authentication from scratch
Author : clairity
Score : 43 points
Date : 2023-01-08 17:56 UTC (5 hours ago)
(HTM) web link (stevepolito.design)
(TXT) w3m dump (stevepolito.design)
| throway2342444 wrote:
| Rolling your own auth is a waste of time unless this is some
| learning exercise.
|
| Cognito + oauth2-proxy or the millions of alternatives are at
| your disposal.
|
| Although for past 15 years I've socially distanced myself from
| Rails, I'm pretty sure it had a decent auth library at the time,
| something called device.
| dorianmariefr wrote:
| Great to see a post from a colleague at thoughtbot
| clairity wrote:
| i've admittedly only skimmed the (long) article for now, but
| it's a great reference and really shows how much thought needs
| to go into user authentication flows. i've done this kind of
| custom implementation in the past and it was definitely a great
| learning experience, but i'm not sure i'd trust my code to
| withstand a serious attack.
|
| they basically recreated a simpler but not-as-flexible (yet?)
| devise. the flexibility/adaptability of devise seems to be
| where all the extra complexity comes from. i'm just waiting to
| see this released as a gem, and the cycle to start anew... =)
| benevol wrote:
| And for reference, the gold standard, Devise:
| https://github.com/heartcombo/devise
| jrvarela56 wrote:
| A great reminder that, if you choose to roll your own auth, you
| need to handle a lot of edge cases. Timing attacks are not
| obvious and easy to forget protecting against.
| clairity wrote:
| yah, i ran across this article[0] that had some response time
| comparisons with the new authenticate_by feature in the
| upcoming rails 7.1 that mitigates a specific timing attack,
| which is what got me interested in seeing what the rails auth
| landscape looked like now.
|
| [0]: https://blog.kiprosh.com/rails-7-1-adds-authenticated_by/
| benmmurphy wrote:
| why do people use cryptographically signed tokens for secret
| tokens (reset password / confirmation)? it should be safer to
| generate a random string and if the token needs to expire to
| store a timestamp in the database. revocation can then be
| performed on individual tokens. I can see why people might be
| more tempted to use these crypto-tokens for session storage to
| avoid the database but I think if this is a requirement then you
| should be using redis or some other fast key storage to hold the
| sessions.
|
| if you are worried about timing attacks then you can just have
| your routes in the form of `/user/<id>/reset_password/<token>`
| and pull the user out of the DB and then do the comparison using
| a timing safe function. alternatively, if that is not possible
| and you need to do a lookup by the token its possible to blind
| the value stored in the DB but i would avoid that because it
| introduces another cryptographic primitive unnecessarily. and
| having only index on user_id and not having to have indexes on
| all your tokens saves space as well!
| aobdev wrote:
| I think the most secure approach is to store a random id in the
| database and to also sign it any time it's exposed to the user
| (as a cookie or url sent via email). The first benefit is that
| you won't be exposed to DoS attacks whereby you're querying
| non-existent tokens from your database, and the second benefit
| is that illegitimate sessions can only be established by
| compromising both your database sessions table and your
| application's signing secrets.
| benmmurphy wrote:
| if you worried about a database compromise you can use the
| blinding trick. so you expose secret to the user and store
| HASH(secret).
| mrinterweb wrote:
| Authentication is rarely something I want to write myself. There
| are many security concerns that need to be considered, many that
| I forget about. Libraries like devise are well thought out, and
| have been security hardened. I'd much rather use an established
| authentication library or service than roll my own. At higher
| scales, I've written authentication middleware services when
| performance was critical and we had complex auth needs, but as a
| starting place for a new app, I would not roll my own.
| chucke wrote:
| Devise has not aged well. It's quite complex for the
| functionality it offers. Does not support json api mode. Only
| supports email/password. It's account creation flow is too
| simplistic for what most apps require OOTB.
| debarshri wrote:
| I think it really depends. Sometime you want to have control
| over the process, and if you have experience building
| authentication before i would recommend doing it yourself
| rather than working with an abstraction defined by a library. I
| have seen first hand with tools like fusion auth when you hit
| the situation which cannot be resolved while adding more
| complexity to your product, I would rather start building it
| into the product than increasing the product complexity and
| working with an abstraction you dont have control over. Again
| take advice with grain of salt.
| bvirb wrote:
| Imagine you want to stop someone from brute-force password
| attempts on your users. You could add some code to lock a
| user out after a specific number of attempts within a given
| time period for that username. But then say it's a real user
| and they forgot their password and they want to get back in
| without having to wait. You might then allow them to reset
| their password (which requires re-verifying access to their
| email addresses) and immediately reset the lock so they can
| get back in. But then since that functionality technically
| allows anyone to have your app send a password reset email to
| any of your users without authentication you might want to
| limit the rate at which those resets can be requested.
|
| None of that is particularly hard, but it's a lot to build,
| test, and maintain. Start throwing in more account features
| you might take for granted elsewhere (MFA, recovery codes,
| re-enter current password to change your password, allow a
| user to sign out of all their sessions, etc etc) and you
| could find yourself spending all your time building your user
| system instead of your application features.
|
| I would guess, for most applications, user systems are
| standard enough that rolling your own isn't going to be worth
| the possible additional customization.
| debarshri wrote:
| I dont think you need these features from day 1. My advice
| should be taken with grain of salt. If the effort of
| building these features is alot in your product, then yes
| you should buy into a library or a service or a product.
| But you also buy into the complexity these product bring
| that might not be relevant for the project you are
| building.
| chucke wrote:
| If you want to use an authentication solution which will not make
| you want to roll your own and highly configurable, use rodauth:
| http://rodauth.jeremyevans.net/
| jkmcf wrote:
| I looked at it awhile ago but it appears to require Roda. Which
| seems a bit heavy dependency on the surface.
| chucke wrote:
| Roda is as lightweight as it gets, when it comes to ruby web
| routers. If you're worried about heavy dependencies, you
| should probably look into rails first.
| jkmcf wrote:
| Yes, Rails is a heavy framework. But strapping another
| framework on top of rails just for authentication smells
| pretty bad.
|
| The reality may be different, but superficially it seems
| odd.
| chucke wrote:
| Roda is not a full blown framework. The footprint of
| rodauth overall is quite low, when compared. Couple that
| with the fact that you get 2 factors, sms, otp, webauthn,
| json mode, argon2, along with json mode + an array of
| security and usability features, from a single
| dependency.
| nnf wrote:
| The website shows code examples for use in non-Roda
| applications, and the readme states:
|
| > Rodauth is Ruby's most advanced authentication framework,
| designed to work in any rack application.
| bvirb wrote:
| Rodauth is really great. We had a partially hand-rolled
| solution and it was time to add MFA so decided to migrate
| rather than build more of our own authentication logic, it was
| definitely the right call.
___________________________________________________________________
(page generated 2023-01-08 23:01 UTC)