Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic authentication generator #50446

Open
dhh opened this issue Dec 26, 2023 · 34 comments
Open

Add basic authentication generator #50446

dhh opened this issue Dec 26, 2023 · 34 comments
Labels
Milestone

Comments

@dhh
Copy link
Member

dhh commented Dec 26, 2023

Rails now include all the key building blocks needed to do basic authentication, but many new developers are still uncertain of how to put them together, so they end up leaning on all-in-one gems that hide the mechanics. While these gems are great, and many people enjoy using them, they should not be seen as a necessity. We can teach Rails developers how to use the basic blocks by adding a basic authentication generator that essentially works as a scaffold, but for authentication.

Note: This ticket serves as a placeholder for the intention to do this work. Not as an open invitation to feature requests. Before we engage in broad discussion of what should or shouldn't be in such a generator, the core team will propose a solution first, so there's something tangible to discuss.

cc @rafaelfranca

@dhh dhh added the railties label Dec 26, 2023
@dhh dhh added this to the 8.0.0 milestone Dec 26, 2023
@devcamke
Copy link

Great!

Have been waiting for this.

@claudiug
Copy link

@dhh are you thinking something similar to: https://github.com/lazaronixon/authentication-zero

@dhh
Copy link
Member Author

dhh commented Dec 26, 2023

@claudiug That's too much for what I have in mind, but the general direction of using generators instead of engines is correct.

@seanwmitchell
Copy link

Could a simple magic link approach be an elegant yet simple solution?

@dhh
Copy link
Member Author

dhh commented Dec 27, 2023

Going to tap the sign in the issue description about now diving into specific feature discussions before there's a PR proposal 😄

@dixpac
Copy link
Contributor

dixpac commented Dec 27, 2023

@dhh is this open for a PR, or we wait for the core team to build initial "version"?

@arianvp
Copy link

arianvp commented Dec 27, 2023

Should include Passkey support ideally. If rails just supports that out of the box that'd be huge

@revskill10
This comment was marked as a violation of GitHub Acceptable Use Policies
@crbelaus
Copy link

crbelaus commented Dec 27, 2023

The Elixir Phoenix team used the same generator approach with the mix phx.gen.auth command.

Even though it is a different language and framework I'm just mentioning it in case it can be interesting or useful to examine.

@rails rails temporarily blocked revskill10 Dec 27, 2023
@dhh
Copy link
Member Author

dhh commented Dec 27, 2023

"Device is the reason Rails sucks" adds nothing of value to the technical discussion, and it's a violation of our Code of Conduct. This has merited a 30-day suspension from engagement here. Let's get back to discussing technical progress.

@tobi
Copy link

tobi commented Dec 27, 2023

I think that's an excellent decision.

One of the reasons authentication has always been a DIY/Userspace feature has been that our Browsers didn't have a native solution ready. The common implementations of user/password have been an unmitigated disaster for security by shifting identity responsibilities to the uses. This has now changed with Passkeys being implemented well on all evergreen browsers and operating systems.

The passkey spec is not perfect but it's a very good set of tradeoffs with a workable API. I feel it makes sense to consider a strong push towards passkeys as a default convention.

@bparanj
Copy link
Contributor

bparanj commented Dec 27, 2023

I would rather go with passwordless or passkey based authentication approach. Any approach that does not require password would be ideal.

@tcannonfodder
Copy link
Contributor

Seconding the calls for a passkeys-first approach; for the reasons outlined here: heartcombo/devise#5527

@dhh
Copy link
Member Author

dhh commented Dec 28, 2023

We built a full passkey solution for ONCE #1 but the user ergonomics left a ton to be desired. So we pulled it out again. Long term, I can definitely see the appeal. But right now the way passkeys are synced or not on different platforms and browsers is hella confusing.

So I want to keep watching the puck, but for an application made with regular users today, it seems too soon to skate there.

But we should get all our infrastructure ready for when passkeys are not just viable but obvious everywhere. We will extract our work into a gem. Too much machinery to all just generate as part of a controller.

@Ukaypromise
Copy link

I strongly believe that this is an excellent decision.

@arianvp
Copy link

arianvp commented Dec 28, 2023

That makes sense. Happy that it's on the radar though.

@kobaltz
Copy link

kobaltz commented Dec 28, 2023

I've been working on https://github.com/kobaltz/action_auth for this very reason. Basically using only the Rails provided mechanisms, I wanted to have a simple authentication solution that could be yanked out in hopes that a Rails built-in solution would seamlessly (as much as possible) take over when or if that time ever came.

@AlexeyMatskevich
Copy link

I just use rodauth and rodauth-rails. Simply because its out-of-the-box feature set is incomparably larger than Devise and any other authentication framework I've seen.
Webauth? no problem, JWT ? Have you ever tried to embed jwt + refresh in devise? it's just available immediately here.
Both View and JSON api are available at once.

And the library author is pretty reliable, after all it's a rack, ruby and sequel orm maintainer.

And if something isn't there, it's either just integrate it yourself or there are plugins available:

  1. oauth
  2. omniauth
  3. pwned
  4. etc...

@dhh
Copy link
Member Author

dhh commented Dec 28, 2023

That is vastly out of scope for what this intends to be. Plenty of room for kitchen sink with gems to continue to serve that. In any case, as per the issue, let’s hold off on discussing features until there’s a proposal PR ready.

@laptopmutia
Copy link

laptopmutia commented Dec 29, 2023

this is cool finally some masterchef would do the omakase for auth in rails

no more worry about "did I do it correctly?"

@sergiotapia
Copy link

This is a great idea! In Phoenix land, there's the phx.gen.auth generators that use basic building blocks to build a secure solution out of the box.

Once generated you can tweak the code to your specific needs if necessary. Maybe something like this would be terrific for Rails.

@AndreyAzimov
Copy link

AndreyAzimov commented Dec 31, 2023

great to here it. I switched from devise to authentication-zero, because it's generating all the code, so I can see it all and understand what is going on + modify it as much as I want.

https://github.com/lazaronixon/authentication-zero

@laptopmutia
Copy link

great to here it. I switched from devise to authentication-zero, because it's generate all the code and I can see it all, so I can modify it as much as I want.

https://github.com/lazaronixon/authentication-zero

that is cool, I wonder where u all keep discovering these shiny gems

@ababich
Copy link

ababich commented Jan 2, 2024

even basic requirements are missing here :)

what is auth here? auth for humans? auth for APIs? and this is only beginning of long question/decision tree about how auth may work

I believe auth is so extremely broad question with so many opinions that to put into rails “distribution “ would be too questionable and opinionated ;)

@mtimofiiv
Copy link

mtimofiiv commented Jan 5, 2024

If the goal is to give people a quick, easy to roll out alternative to the step of installing one of several rich featured gems out there - I would imagine then the focus should be on authenticating humans, and giving the developer the most dead-simple functionality that covers the most common use-case:

  • Sign up
  • Log in
  • Log out
  • A couple helpers to the tune of current_user

A user model, with some basic infrastructure (like views) to handle this would go (in my opinion) as far as this would need to go.

For anything else there are gems. Maybe I'm over-simplifying here.

The new system would obviously need to be extendable. But maybe this could even be the realm of additional, optional, possibly 3rd party gems.

For example, if you need to have single sign on via providers like Github, Meta, etc - this will require things like callback routes, managing the tokens issued on the return trip, auth provider API keys, etc.

@n-studio
Copy link

n-studio commented Jan 5, 2024

  • Sign up

  • Log in

  • Log out

  • A couple helpers to the tune of current_user

I think there are other features that are not avoidable such as "reset password", "confirm email", "safe email update".

I'd also advocate to have other security related features all websites should have, such as the ability to discard all existing sessions after a hack recovery.

@mtimofiiv
Copy link

@n-studio yep, agreed, things like you mentioned would also be important.

@bparanj
Copy link
Contributor

bparanj commented Jan 6, 2024

Here is my wishlist:

  • Auto register
  • Login with magic link
  • No signup
  • No password storing
  • No password reset
  • No confirm email

If craigslist using Perl can have magiclink login, then in 2024 Rails should be able to accomplish this feature. Here is the requirements documented and functioning FastAPI project

@1klap
Copy link

1klap commented Jan 9, 2024

I think a default auth generator can do as little as a sessions_controller, a registrations_controller, an authorizable concern and some before hooks in the right places.
I (for myself) extracted the minimal required code into this gem, this is enough to get started and easy to move on if it needs to be extended. (Release post)
The generator could just do something similar in the project and i think it is simple enough for devs to look at the code and understand what it is doing (and tweak if needed)

@bparanj
Copy link
Contributor

bparanj commented Jan 11, 2024

The reason I want to replicate FastAPI way of doing this is due to security issues. They have already adopted best security practices for this feature. It is very well thought out with the end to end flow: You see it in their authentication guide. Without the password related stuff in this doc and retain only magiclink and maybe TOTP as another layer of defense.

I glanced over the Ruby related repos. They don't have much in terms of security. I was thinking something very lightweight:

has_magiclink

declaration in the model. Bake in the best security practices in this method.

@brunoprietog
Copy link
Contributor

It has already been said that a proposal will be submitted. I don't think it's worth discussing things ahead of time.

@cvalencia1991
Copy link

hello @dhh one way could be implement is using device i think could be use full also give a feature to implement OAuth

@philipithomas
Copy link

A small thing to consider based on my recent auth work:

Magic links don't work with PWAs on iOS. If you click the login link, it always opens in Safari and always log into Safari. The cookies in Safari are separate from the cookies in the PWA. So, it's impossible to get the magic link to open in the PWA.

I preferred pin-based login over links for this reason.

@sandergroen
Copy link

sandergroen commented Feb 23, 2024

Perhaps it is an idea to add something similar like has_secure_password that can store multiple credentials for a user. This way you can have a password and a passkey (or whatever other credential) at the same time.

I once was investigating a simple setup in Rails to do something like this but i could not find a way to use has_secure_password to make something like this to work. I know it is not intended for any use other than passwords but it would be nice to have the functionality to encrypt credentials extracted out of has_secure_password.

A data model could be something like this:

class User < ApplicationRecord
  has_many :credentials, dependent: :destroy
end

class Credential < ApplicationRecord
  has_credential
  belongs_to :user
end
class CreateCredentials < ActiveRecord::Migration
  def change
    t.references :user, null: false, foreign_key: true
    t.(string or integer) :type, null: false
    t.string :credential_digest, null: false
    
    t.timestamps
  end
end

The authentication will become more complex but you will have more authentication options this way. For the generator perhaps this could be an option:

rails g authentication --credentials

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests