HTTP Basic authentication
You can use HTTP basic authentication to restrict access to different controllers/actions.
The easiest way is to use a http_basic_authenticate_with
callback in a controller:
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
+ http_basic_authenticate_with name: 'superails', password: '123456', except: :index
A better approach where you have more control is to use authenticate_or_request_with_http_basic(realm = "Application", message = nil, &login_procedure)
, because it allows you to pass multple options and a block.
realm
- “scope”. You can have different http authentication for different parts of your app. Defaults to"Application"
.message
- failure message. Default:*"HTTP Digest: Access denied."
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :http_authenticate, only: %i[show]
def index
@posts = Post.all
end
def show
end
private
def http_authenticate
# conditionally enable the feature only in production:
# return true if %w(test staging).include? Rails.env
# return true unless Rails.env == 'production'
authenticate_or_request_with_http_basic do |username, password|
username == 'superails' && password == '123456'
# better to hide password in credentials:
username == Rails.application.credentials.dig(:http_auth, :username) &&
password == Rails.application.credentials.dig(:http_auth, :password)
end
end
end
# credentials.yml
http_auth:
username: superails
password: 123456
- Check (in a view) if current page required authorization to open:
request.headers[:HTTP_AUTHORIZATION].present?
request.authorization.present?
Sustainable ways to include http auth im multiple controllers:
- Controller inheritance:
You can create a controller that will require authentication, and than inherit further controllers from it:
# app/controllers/secured_controller.rb
class SecuredController < ApplicationController
before_action :http_authenticate
private
def http_authenticate
authenticate_or_request_with_http_basic do |username, password|
username == 'superails' && password == '123456'
end
end
end
# app/controllers/posts_controller.rb
-class PostsController < ApplicationController
+class PostsController < SecuredController
# app/controllers/posts_controller.rb
-class TasksController < ApplicationController
+class TasksController < SecuredController
- Concern inclusion:
# app/controllers/concerns/http_auth_concern.rb
module HttpAuthConcern
extend ActiveSupport::Concern
included do
before_action :http_authenticate
end
def http_authenticate
authenticate_or_request_with_http_basic do |username, password|
username == 'superails' && password == '123456'
end
end
end
# app/controllers/application_controller.rb
class PostsController < ApplicationController
+ include HttpAuthConcern
# app/controllers/posts_controller.rb
class TasksController < ApplicationController
+ include HttpAuthConcern