Thanks! It works, with a little modification (path, not remaining_path).
A working example is copied below. But, to get it to work, I had to use the json_parser plugin. I don't ordinarily use that roda plugin because one of my routes wants to parse the json request body without symbolizing keys, while the rest of the routes in my application want the json body parsed *with* symbolizing keys.
require 'roda'
require 'rodauth'
require 'sequel'
DB = Sequel.postgres('test') unless defined?(DB)
class App < Roda
# The json plugin must be included to avoid:
#
# NoMethodError: undefined method `convert_to_json' for #<App::RodaRequest POST /login>
#
# Is this a bug?
plugin :json
# The json_parser plugin must be included to avoid failure to login:
#
# {"field-error":["login","no matching login"],"error":"There was an error logging in"}
plugin :json_parser
plugin :rodauth do
# The :login and :json features must be enabled to get
# application/json back after requesting "/login".
enable(:login, :json)
# csrf checking must be disabled on '/login' for json-based
# requests to avoid
#
# Roda::RodaPlugins::RouteCsrf::InvalidToken: encoded token is not a string
check_csrf? { '/login' == request.path ? false : super() }
end
plugin(:sessions, secret: (0..64).to_a.join(''))
route do |r|
r.rodauth
end
end