janko / rodauth-rails

Rails integration for Rodauth authentication framework
https://github.com/jeremyevans/rodauth
MIT License
584 stars 40 forks source link

JWT usage unclear #21

Closed technodrome closed 3 years ago

technodrome commented 3 years ago

Hello Janko,

I have trouble getting JWT to work. I have what I'd call mixed mode app where I'm using normal Rails app (not --api) with Vue frontend. Vue will communicate with a dedicated Rails API to get data.

Error

When testing user signup, I hit the following error:

Started POST "/create-account" for 172.23.0.1 at 2020-12-29 19:35:16 +0000
   (0.8ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC

NameError (uninitialized constant RodauthApp::RodauthController
Did you mean?  RodauthMailer):

app/lib/rodauth_app.rb:27:in `block (2 levels) in <class:RodauthApp>'
app/lib/rodauth_app.rb:162:in `block in <class:RodauthApp>'

Request

triggered by my request (deleted cookie session from the request)

curl --request POST \
  --url http://localhost:3000/create-account \
  --header 'Content-Type: application/json' \
  --data '{
    "login": "test@test.com",
    "password": "testtest"
}'

Rodauth-Rails config

class RodauthApp < Rodauth::Rails::App
  configure json: :only do
    enable(
      :create_account,
      :verify_account,
      :verify_account_grace_period,
      :login,
      :logout,
      :reset_password,
      :change_password,
      :change_password_notify,
      :change_login,
      :verify_login_change,
      :close_account,
      :jwt
    )

    rails_controller { RodauthController }

    account_status_column :status
    account_unverified_status_value 'unverified'
    account_open_status_value 'verified'
    account_closed_status_value 'closed'

    verify_account_set_password? false

    jwt_secret "123456-example"

    require_login_confirmation? false
    require_password_confirmation? false

    after_create_account do
      Profile.create!(account_id: account[:id])
    end

    after_close_account do
      Profile.find_by!(account_id: account[:id]).destroy
    end

    logout_redirect '/'

    verify_account_redirect { login_redirect }
    reset_password_redirect { login_path }
  end

  route do |r|
    r.rodauth
  end
end

Remarks

I have three remarks I feel were very nice to add to this project:

janko commented 3 years ago

You're might be missing a RodauthController, you can just create an empty one. It's normally created by the install generator on latest rodauth-rails version, but you might have erased it in the process.

do not depend on Rails API mode in your generators. Make it explicit, so user can actually choose what to generate, like with rails generate rodauth:install:api

Agreed, I was planning to add an --api option to rodauth:install for toggling this, which would default to true when Rails app is in API-only mode.

I had to generate a dummy rodauth-rails project, diff my real project and dummy project just to be able to see what your generator actually added to the code. Not cool.

I don't think it's difficult to set up API-only mode manually, so I think it's still cool, just it would be even better to have settings for mixed mode 😉

how to send mails when user registers/other actions with JWT only mode. Currently mails are available only in non-JWT mode of rodauth-rails without any info how to do that with JWT. It is not clear how to do that, as (according to the Rodauth author) you have to enable render plugin. Not sure how to do that with your DSL

In which was exactly does it not work for you? rodauth-rails always loads the render plugin, even if you've set json: :only, precisely to allow rendering emails in JSON-only mode. I tried setting JSON-only mode on the official demo app, and email sending works for me.

technodrome commented 3 years ago

You're might be missing a RodauthController, you can just create an empty one. It's normally created by the install generator on latest rodauth-rails version, but you might have erased it in the process.

This is weird. Controller is there, git confirms this. Had to kill the docker app and restart it a couple of times. Maybe FS inconsistency. Now it works properly.

Agreed, I was planning to add an --api option to rodauth:install for toggling this, which would default to true when Rails app is in API-only mode.

Cool. This will be very helpful.

I don't think it's difficult to set up API-only mode manually, so I think it's still cool, just it would be even better to have settings for mixed mode

It's unneccessarily complicated, that's all.

In which was exactly does it not work for you? rodauth-rails always loads the render plugin, even if you've set json: :only, precisely to allow rendering emails in JSON-only mode. I tried setting JSON-only mode on the official demo app, and email sending works for me.

Didn't know this. Maybe it would be useful to add this to the documentation, e.g. what plugins are autoloaded and maybe how to load manually some others/custom ones.

Two questions:,

Thank you for your fast replies :)

janko commented 3 years ago

is there a way to control which mails get sent in JWT-only mode? In normal mode one specifies which mail gets sent when in the app/lib/rodauth_app.rb. Are similar config options available for JWT?

Emails are configured exactly the same with JWT as it is when using HTML.

how would one go about adding new custom fileds in JWT-only mode, e.g. custom fields you're passing from a signup Vue component?

This should also be the same as described in this guide. Any request JSON payload should be automatically available via param and param_or_nil methods; if Vue sends e.g. name along with login & password, it should be available under param("name") in a before_create_account hook.

Didn't know this. Maybe it would be useful to add this to the documentation, e.g. what plugins are autoloaded and maybe how to load manually some others/custom ones.

Good idea, I will provide additional explanation.