Hiro Shaw
Hiro Shaw

Reputation: 395

Rails basic authentication with cutomized JSON failure message

I have got a Rails 5.2 app in API mode. If a request is supplied with correct Basic Authentication credentials, expected JSON data { status: true, data: 'test_user_data' } will be rendered.

users_controller.rb

class Api::UsersController < ApplicationController
  before_action :basic_authenticate

  def get_user_info
    render json: { status: true, data: 'test_user_data' }
  end

  private

  def basic_authenticate
    authenticate_or_request_with_http_basic do |username, password|
      username == 'test_name' && password == 'test_password'
    end
  end
end

application_controller.rb

class ApplicationController < ActionController::API
    include ActionController::HttpAuthentication::Basic::ControllerMethods
end

However, if Basic Authentication fails, only a plain text HTTP Basic: Access denied. is rendered.

What I would like to do is to render error messages in JSON in case of authentication failure, something like { status: false, message: 'basic authentication failed'}.

What is the proper way to fix it?

Upvotes: 0

Views: 664

Answers (2)

spickermann
spickermann

Reputation: 106882

authenticate_or_request_with_http_basic takes an optional message parameter (which is, unfortunately, the second in the parameter list, therefore the "Application" for the first parameter).

In Rails 5 just change your code to:

def basic_authenticate
  message = { status: false, message: 'basic authentication failed' }.to_json

  authenticate_or_request_with_http_basic("Application", message) do |username, password|
    username == 'test_name' && password == 'test_password'
  end
end

The implementation has changed in Rails 6 and therefore in Rails 6 the most basic implementation would look like this:

def basic_authenticate
  message = { status: false, message: 'basic authentication failed' }.to_json

  authenticate_or_request_with_http_basic(nil, message) do |username, password|
    username == 'test_name' && password == 'test_password'
  end
end

Upvotes: 2

Velusamy Venkatraman
Velusamy Venkatraman

Reputation: 736

Use rescue from in your application_controller.rb like below

rescue_from User::NotAuthorized, with: :deny_access # self defined exception

def deny_access
  render json: { status: false, message: 'basic authentication failed'}
end

Upvotes: 0

Related Questions