For a JavaScript web app (AngularJS based) I am using PouchDB replicating a CouchDB database on my server. Authentication in PouchDB works nicely with pouchdb-authentication. I want to manage this through a html/js login screen.
However, if the user enters wrong credentials, I receive a 401 Unauthorized
from the CouchDB server that causes a browser popup asking for credentials.
How can I prevent this ugly Authentication popup and just handle everything from my javascript?!
I finally found the solution:
Edit the CouchDB config local.ini
and change the HTTP Header sent in response:
WWW-Authenticate = Other realm="app"
Originally this is
WWW-Authenticate = Basic realm="administrator"
or if it is commented, that's what is sent out anyway. The WWW-Authenticate = Basic
apparently causes the browser to handle (failed) authentication by showing its modal. Changing Basic
to anything else makes the browser ignore it and you can deal with the login yourself.
Update 2015.12.18
After a lot of testing I arrived at the second solution outlined. All you need to do is install nginx with the headers-more-module. Add the following to your nginx-config:
location / {
# forward all request headers to backend
proxy_pass_request_headers on;
# these settings come from the CouchDB wiki
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# your CouchDB backend
proxy_pass http://127.0.0.1:5984;
# replace WWW-Authenticate header in response if authorization failed
more_set_headers -s 401 'WWW-Authenticate: Other realm="App"';
}
# location to handle access to Futon
location /_utils/ {
# forward all request headers to backend
proxy_pass_request_headers on;
# these settings come from the CouchDB wiki
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# your CouchDB backend
proxy_pass http://127.0.0.1:5984;
# DO NOT replace WWW-Authenticate header in response if authorization failed
# more_set_headers -s 401 'WWW-Authenticate: Other realm="App"';
# Handle redirects
proxy_redirect default;
}
And your are set. You can continue using pouchdb-authentication or write your own login handler.
Original Post
Sorry to answer, but I cannot comment (yet).
I suffer from the same problem, even worse that on OS X the WWW-Authenticate parameter is lower-cased on every restart of CouchDB and therefore not recognized any more. Therefore it has to be set after EACH restart using Futon/Fauxton or the API.
You could try and play with the next parameter (see http://docs.couchdb.org/en/1.6.1/api/server/authn.html). In principle you send your auth-request to (example in angular2):
// assuming you bootstrapped HTTP_PROVIDERS and injected Http
// configure headers
let headers: Headers = new Headers()
headers.append('Content-Type', 'application/json')
headers.append('Accept', 'application/json')
headers.append('Authorization', 'Basic ' + window.btoa(username + ':' + password))
// using the injected Http instance
this.http
// post to _session specifying next and the redirect
.post(
'http://localhost:5984/_session?next=/successfullyLoggedInPage'
, JSON.stringify({'name': username, 'password': password})
, {headers: headers}
)
.map((res: Response) => res.json())
.subscribe(
(res) => {
// successful auth
},
(err) => {
if (err.status === 401) // failed auth
}
)
In my setup the web-app and CouchDB are served from two different origins. I can only get this working if I disable web-security in Chrome due to cross-origin restrictions. I believe a reverse proxy could rewrite the redirect response, e. g. using nginx's proxy_redirect (http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect).
I believe the best solution is to modify the response headers by a reverse proxy. For nginx there is a module called ngx_headers_more (see https://github.com/openresty/headers-more-nginx-module#readme) which should be able to do this. One could check for 401 responses and then modify the header from Authentication: Basic to Authentication: Other, therefore disabling the modal. In principle Futon/Fauxton should still work then, no? I haven't tried this approach yet but in the location block of nginx you need to specify
more_set_headers -s 401 'WWW-Authenticate: Other realm="App"'
I hope someone more qualified can add his/her two cents.
I was having more or less the same problem. Though I am using a reverse proxy with the 'proxy' authentication handler of CouchDB. When the user tries to do something that he is not allowed to (creating a DB while he is not an admin), a 401 response was returned by CouchDB, triggering HTTP basic auth. Not so nice, as the reverse proxy handles authentication based on X509 client certificates. I actually think that CouchDB should return a 403 response, but that's a different discussion.
To fix it, I used your answers, but I am not so eager to use an external Nginx module (ngx_headers_more) and actually am not so fond of changing the header to a 'nonsense' value. Instead, with the existing proxy module in Nginx, you can just remove the WWW-Authenticate all together:
proxy_pass http://${COUCHDB_HOSTNAME}:${COUCHDB_PORT};
proxy_hide_header WWW-Authenticate;
Seems to be working fine. See https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header for its documentation.
来源:https://stackoverflow.com/questions/32670580/prevent-authentication-popup-401-with-couchdb-pouchdb