Trigger basic HTTP auth from within middleware

核能气质少年 提交于 2019-12-23 03:50:18

问题


I have created a custom middleware for rails which will intercept all requests and make sure it's coming from an authorized IP, otherwise it should prompt for a basic http auth user/name password.

This is currently what it looks like:

require 'net/http'

class AuthorizeEnvironment
  def initialize(app)
    @app = app
  end

  def call(env)
    if AppConstants.approved_doximity_ips.include?(env["REMOTE_ADDR"])
      @app.call(env)
    elsif authorized?(env)
      @app.call(env)
    else
      [403, {"Content-Type" => "text/html"}, ["Not Authorized on this environment."]]
    end
  end

  def authorized?(env)
    @auth ||= Rack::Auth::Basic::Request.new(env)
    @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == ['username', 'password']
  end
end

The issue with this code is that I can't seem to find a way to trigger the http auth window on the browser. I reviewed this and didn't see any obvious indication of how this is done.

Could you please point me in the right direction?


回答1:


I haven't tested your code, but it looks like your replying with a 403 which means "forbidden". I.e., the currently logged in user does not have permissions to access this resource.

From the RFC (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)

The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.

Instead, you need to use a 401, and only reply with a 403 ONLY if the currently logged in user cannot access the resource.




回答2:


I'm using Rack::Auth::Basic directly and saves myself the validation part:

class BasicAuth
  def initialize(app)
    @app = app
  end

  def call(env)
    if env["PATH_INFO"] == '/supersecret' # Any condition here
      auth = Rack::Auth::Basic.new(@app) do |u, p|
        u == username && p == password
      end
      auth.call env
    else
      @app.call env
    end
  end

  def username
    ENV["username"]
  end

  def password
    ENV["password"]
  end
end

```




回答3:


You need to provide a WWW-Authenticate header. See.

I assume, in your else, you would do:

[401, {'WWW-Authenticate' => 'Basic realm="Application"', "Content-Type" => "text/html"}, ["Not Authorized on this environment."]]


来源:https://stackoverflow.com/questions/16577139/trigger-basic-http-auth-from-within-middleware

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!