简体   繁体   中英

How to deploy multiple Rack/Sinatra apps with Passenger (on Apache) with HTTP Basic Authentication?

The issue here is with multiple instances of the same Sinatra (Rack) app deployed on Passenger+Apache on different sub URIs with HTTP basic auth to keep away unwanted access:

I have 4 instances of a Sinatra app deployed on my domain as:

  1. example.com/private/foo
  2. example.com/private/moo
  3. ...
  4. ...

Access to all of them is protected by HTTP basic authentication using the Rack::Auth::Basic middleware. config.ru for all of them look like:

# ...
users = {'user' => 'password'}
use Rack::Auth::Basic, 'realm' do |username, password|
    users.key?(username) && users[username] == password
end

run MyApp

The only thing the changes from one config.ru to another is the 'realm' parameter.

Now the issue is that once I have logged into one of the apps, say private/foo , Chrome doesn't prompt me for a username and password for other apps ( private/moo etc.). This is counterintuitive since all instances are uniquiely identified by their URLs. Using different credentials for each instance does work, but shouldn't Chrome request credentials at least once for each instance? One thing I noticed is that the first time I log into one of the instances, Chrome says 'The server at example.com:80 requires a username and password'. I would have expected 'The resource example.com/private/foo requires a username and password'. Isn't that how it is supposed to work?

I checked Rack::Auth::Basic source code and Wikipedia's article on HTTP Basic Auth and came up with nothing to help my case :(.

In basic authentication, the realm parameter isn't send back to the server. So the server can't really check if the client is sending authorization header for the same realm or not. It depends on the client. Rack's implementation of HTTP basic authentication is correct. So:

Now the issue is that once I have logged into one of the apps, say private/foo, Chrome doesn't prompt me for a username and password for other apps (private/moo etc.). This is counterintuitive since all instances are uniquiely identified by their URLs.

As Andrew pointed out and is clear from the RFC, URL doesn't play a role there. But if '/foo' is protected, '/foo/moo' is protected under the same realm.

Using different credentials for each instance does work, but shouldn't Chrome request credentials at least once for each instance?

Under the scenes what is happening (on inspecting with debugger tools) is that, after I have logged once into one of the apps, say private/foo, Chrome re-sends the same authorization header to other apps, say private/moo, without being challenged first.

The RFC says that the client may send the corresponding authorization header for a realm without being challenged by the server first.

Looks like Chrome is either treating all my apps to be under the same realm or re-sending the same authorization header across different realms. I don't think that is the expected behavior but I could be missing something. Firefox behaves same. Anyway, that wasn't the essence of the question.

The theme of the question was "How do I get Chrome to request me username and password at least once for each instance? Basic auth isn't working the way I expected it to; why?"

Use Digest authentication (RFC 2617 again). Rack implements the MD5 algorithm version under Rack::Auth::Digest::MD5 . Set different opaque for each instance and you are good to go:

# ...
realm  = "Description of the protected area."
opaque = "Secret key that uniquely identifies a realm."

users = {'user' => 'password'}
use Rack::Auth::Digest::MD5, realm, opaque do |username|
  users[username]
end

opaque is sent back by the client and can be verified on the server side that the authorization request is for the correct resource. Job of realm seems descriptory in nature -- which area or resource are you trying to protect? what id do I flash?

RFC: http://tools.ietf.org/html/rfc2617

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM