From 14863ba4c92cd9781a961be0486f0ea7dfe84144 Mon Sep 17 00:00:00 2001 From: Colin Ross Date: Tue, 29 Oct 2019 11:06:37 -0700 Subject: [PATCH] Documentation: Details/Notes regarding Rails API-only applications (#5152) * doc: Add some additional details concerning using devise in an API-only Rails application * Apply wording suggestions from code review Co-Authored-By: Marcos Ferreira * Apply suggestions from code review Co-Authored-By: Marcos Ferreira --- README.md | 19 ++++++++++++++++++- lib/generators/templates/README | 10 +++++++++- lib/generators/templates/devise.rb | 5 ++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ab4dffc7..575bd121 100644 --- a/README.md +++ b/README.md @@ -697,7 +697,22 @@ Devise supports ActiveRecord (default) and Mongoid. To select another ORM, simpl ### Rails API Mode -Rails 5+ has a built-in [API Mode](https://edgeguides.rubyonrails.org/api_app.html) which optimizes Rails for use as an API (only). One of the side effects is that it changes the order of the middleware stack, and this can cause problems for `Devise::Test::IntegrationHelpers`. This problem usually surfaces as an ```undefined method `[]=' for nil:NilClass``` error when using integration test helpers, such as `#sign_in`. The solution is simply to reorder the middlewares by adding the following to test.rb: +Rails 5+ has a built-in [API Mode](https://edgeguides.rubyonrails.org/api_app.html) which optimizes Rails for use as an API (only). Devise is _somewhat_ able to handle applications that are built in this mode without additional modifications in the sense that it should not raise exceptions and the like. But some issues may still arise during `development`/`testing`, as we still don't know the full extent of this compatibility. (For more information, see [issue #4947](https://github.com/plataformatec/devise/issues/4947/)) + +#### Supported Authentication Strategies +API-only applications don't support browser-based authentication via cookies, which is devise's default. Yet, devise can still provide authentication out of the box in those cases with the `http_authenticatable` strategy, which uses HTTP Basic Auth and authenticates the user on each request. (For more info, see this wiki article for [How To: Use HTTP Basic Authentication](https://github.com/plataformatec/devise/wiki/How-To:-Use-HTTP-Basic-Authentication)) + +The devise default for HTTP Auth is disabled, so it will need to be enabled in the devise initializer for the database strategy: + +```ruby +config.http_authenticatable = [:database] +``` + +This restriction does not limit you from implementing custom warden strategies, either in your application or via gem-based extensions for devise. +A common authentication strategy for APIs is token-based authentication. For more information on extending devise to support this type of authentication and others, see the wiki article for [Simple Token Authentication Examples and alternatives](https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example#alternatives) or this blog post on [Custom authentication methods with Devise](http://blog.plataformatec.com.br/2019/01/custom-authentication-methods-with-devise/). + +#### Testing +API Mode changes the order of the middleware stack, and this can cause problems for `Devise::Test::IntegrationHelpers`. This problem usually surfaces as an ```undefined method `[]=' for nil:NilClass``` error when using integration test helpers, such as `#sign_in`. The solution is simply to reorder the middlewares by adding the following to test.rb: ```ruby Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Cookies @@ -706,6 +721,8 @@ Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatc For a deeper understanding of this, review [this issue](https://github.com/plataformatec/devise/issues/4696). +Additionally be mindful that without views supported, some email-based flows from Confirmable, Recoverable and Lockable are not supported directly at this time. + ## Additional information ### Heroku diff --git a/lib/generators/templates/README b/lib/generators/templates/README index b7648280..c89920b0 100644 --- a/lib/generators/templates/README +++ b/lib/generators/templates/README @@ -1,6 +1,6 @@ =============================================================================== -Some setup you must do manually if you haven't yet: +Depending on your application's configuration some manual setup may be required: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment @@ -10,10 +10,14 @@ Some setup you must do manually if you haven't yet: In production, :host should be set to the actual host of your application. + * Required for all applications. * + 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" + + * Not required for API-only Applications * 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: @@ -21,8 +25,12 @@ Some setup you must do manually if you haven't yet:

<%= notice %>

<%= alert %>

+ * Not required for API-only Applications * + 4. You can copy Devise views (for customization) to your app by running: rails g devise:views + + * Not required * =============================================================================== diff --git a/lib/generators/templates/devise.rb b/lib/generators/templates/devise.rb index 5f37f696..0c971902 100644 --- a/lib/generators/templates/devise.rb +++ b/lib/generators/templates/devise.rb @@ -74,7 +74,10 @@ Devise.setup do |config| # Tell if authentication through HTTP Auth is enabled. False by default. # It can be set to an array that will enable http authentication only for the # given strategies, for example, `config.http_authenticatable = [:database]` will - # enable it only for database authentication. The supported strategies are: + # enable it only for database authentication. + # For API-only applications to support authentication "out-of-the-box", you will likely want to + # enable this with :database unless you are using a custom strategy. + # The supported strategies are: # :database = Support basic authentication with authentication key + password # config.http_authenticatable = false