Skip to content
Janko Marohnić edited this page Dec 3, 2024 · 15 revisions

JSON (cookie-based)

To make Rodauth endpoints accessible via JSON API, enable the json feature:

# app/misc/rodauth_main.rb
class RodauthMain < Rodauth::Rails::Auth
  configure do
    # ...
    enable :json
    only_json? true # accept only JSON requests (optional)
    # ...
  end
end

This will store account session data into the Rails session. If you're using Rails in API-only mode, make sure to enable session store in Rails configuration:

# config/application.rb
module YourApp
  class Application < Rails::Application
    config.session_store :cookie_store, key: '_your_app_api_session'
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use config.session_store, config.session_options
  end
end

CSRF protection

Rodauth disables CSRF protection for JSON requests, because they require Content-Type: application/json request header, so CSRF attacks should be impossible, as long as you allow cross-site credentials only from origins you own (see CORS section below).

You can do the same for your other JSON routes:

class ApplicationController < ActionController::Base
  skip_before_action :verify_authenticity_token, if: -> { request.format.json? }
end

CORS

If the frontend lives on a different origin from the JSON API it consumes, you will need to configure CORS to allow cross-site cookies.

One way to do is using the rack-cors gem. First, add the gem to your project:

$ bundle add rack-cors

Then configure it to allow requests from your frontend to include cookies:

# config/application.rb
module YourApp
  class Application < Rails::Application
    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins 'frontend.example.com'
        resource '*', headers: :any, methods: :any, credentials: true
      end
    end
  end
end

JavaScript

The Fetch API will only include cookies on same-origin requests by default. If your frontend lives on a different (sub)domain, you need to set credentials: "include":

fetch("https://api.example.com/submit-data", {
  method: "POST",
  credentials: "include", // include cookies on cross-origin requests
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ /* ... */ })
})

JWT (token-based)

If you would prefer token-based authentication via the Authorization header, enable the jwt feature (which builds on top of the json feature) and add the JWT gem to the Gemfile:

$ bundle add jwt
# app/misc/rodauth_main.rb
class RodauthMain < Rodauth::Rails::Auth
  configure do
    # ...
    enable :jwt
    jwt_secret "<YOUR_SECRET_KEY>" # store the JWT secret in a safe place
    only_json? true # accept only JSON requests (optional)
    # ...
  end
end

The JWT token will be returned after each request to Rodauth routes. To also return the JWT token on requests to your app's routes, you can add the following code to your base controller:

class ApplicationController < ActionController::Base
  # ...
  after_action :set_jwt_token

  private

  def set_jwt_token
    if rodauth.use_jwt? && rodauth.valid_jwt?
      response.headers["Authorization"] = rodauth.session_jwt
    end
  end
  # ...
end

Email links

When using JSON API mode with only_json? set to true, only POST endpoints are available (GET endpoints are disabled). This means that following email links (account verification, password reset, login change etc.) will not automatically work if the URL points to the backend API.

The emails links need to point to a frontend app, which should then make a POST request to the backend using the token from the URL, hitting the Rodauth endpoint. URL options for background emails can be modified through config.action_mailer.default_url_options, and those should point to the frontend app.

config.action_mailer.default_url_options = { scheme: "https", host: "frontend.example.com" }

If you don't want the frontend routes to use the same URL path as the backend Rodauth endpoints, you can override the *_email_link methods with the frontend URL, passing it the token:

class RodauthMain < Rodauth::Rails::Auth
  configure do
    verify_account_email_link do
      "https://frontend.example.com/account/verify?token=#{token_param_value(verify_account_key_value)}"
    end
  end
end

API documentation

If you'd like to get an overview of the routes available to you and the parameters they accept, you can use the rodauth-openapi gem to generate OpenAPI documentation from your Rodauth configuration.

$ bundle add rodauth-openapi --group development
$ rails g rodauth:openapi --save api-docs.yml

You can then upload the result into an OpenAPI renderer such as Swagger Editor or Redocly, and see the available routes.