Replicator fails to authenticate to open db after cookie timeout #1607
Comments
Made a script to replicate the issue: #!/bin/bash
S=localhost:15984
SA=adm:pass@${S}
JSON="Content-Type: application/json"
curl -s -XDELETE $SA/db > /dev/null
curl -s -XDELETE $SA/srcdb > /dev/null
curl -s -XDELETE $SA/_replicator > /dev/null
curl -s -XPUT $SA/db > /dev/null
curl -s -XPUT $SA/srcdb > /dev/null
echo "Setting [couch_httpd_auth] timeout = 5"
curl -s -XPUT adm:pass@localhost:15986/_config/couch_httpd_auth/timeout -d '"5"' > /dev/null
curl -s -XPUT adm:pass@localhost:25986/_config/couch_httpd_auth/timeout -d '"5"' > /dev/null
curl -s -XPUT adm:pass@localhost:35986/_config/couch_httpd_auth/timeout -d '"5"' > /dev/null
echo "Adding VDU to target"
cat <<EOF > /tmp/vdu.json
{
"_id": "_design/vdu",
"validate_doc_update":"function(newDoc, oldDoc, userCtx) { log(userCtx); if (newDoc.name != userCtx.name) { throw({'forbidden': 'VDU failed'}); } }"
}
EOF
curl -s -XPUT $SA/db/_design/vdu -H "$JSON" -T /tmp/vdu.json > /dev/null
echo "Replicating from srcdb to db"
curl -s XDELETE $SA/_replicate -H "$JSON" -d '{"source":"http://adm:pass@localhost:15984/srcdb", "target":"http://adm:pass@localhost:15984/db", "worker_proceses":1, "continuous":true}' > /dev/null
curl -s XPOST $SA/_replicate -H "$JSON" -d '{"source":"http://adm:pass@localhost:15984/srcdb", "target":"http://adm:pass@localhost:15984/db", "worker_proceses":1, "continuous":true}' > /dev/null
sleep 3
DOCID=0
echo "With frequent enough updates, session is getting refreshed"
while [ $DOCID -lt 2 ]; do
let DOCID++
echo ""
echo "DocID: $DOCID"
curl -s -XPUT $SA/srcdb/$DOCID -H "$JSON" -d '{"name":"adm"}' > /dev/null
echo "Doc added to source, sleeping 2 seconds"
sleep 2
echo "Getting doc from target:"
curl $SA/db/$DOCID
done
echo "With long sleeps, sesssion will timeout and not get refreshed"
sleep 10
while [ $DOCID -lt 10 ]; do
let DOCID++
echo ""
echo "DocID: $DOCID"
curl -s -XPUT $SA/srcdb/$DOCID -H "$JSON" -d '{"name":"adm"}' > /dev/null
echo "Doc added to source, sleeping 7 seconds"
sleep 7
echo "Getting doc from target:"
curl $SA/db/$DOCID
done
It can be run against a default dev cluster:
|
An interesting observation is that a 403 HTTP response, which a However replicator, in the normal case would write documents using a It is possible to trick the replicator to use single requests if attachments are used. Indeed, I had waited till the after the session expired and added a document with an attachment to the source:
The script was running in the part with long sleep but as soon as the attachment was added, the session was refreshed and the a few writes succeeded:
|
Force couch_replicator_auth_session plugin to refresh the session periodically. Normally it is not needed as the session would be refreshed when requests start failing with a 401 (authentication) or 403 (authorization) errors. In some cases when anonymous writes are allowed to the database and a VDU function is used to forbid writes based on the authenticated in username, requests with an expired session cookie will not fail with a 401 and the session will not be refreshed. When set, the value should be less than the minimum session timeout for any of the replication endpoints. For example, for CouchDB, the session timeout is 600 by default so the value would be set to something like 550. Issue apache#1607
Implemented a fix: #1619 |
Force couch_replicator_auth_session plugin to refresh the session periodically. Normally it is not needed as the session would be refreshed when requests start failing with a 401 (authentication) or 403 (authorization) errors. In some cases when anonymous writes are allowed to the database and a VDU function is used to forbid writes based on the authenticated in username, requests with an expired session cookie will not fail with a 401 and the session will not be refreshed. 550 is used as default as it is less than the default 600 used for CouchDB's session refresh timeout. Issue apache#1607
Force couch_replicator_auth_session plugin to refresh the session periodically. Normally it is not needed as the session would be refreshed when requests start failing with a 401 (authentication) or 403 (authorization) errors. In some cases when anonymous writes are allowed to the database and a VDU function is used to forbid writes based on the authenticated in username, requests with an expired session cookie will not fail with a 401 and the session will not be refreshed. 550 is used as default as it is less than the default 600 used for CouchDB's session refresh timeout. Issue apache#1607
Force couch_replicator_auth_session plugin to refresh the session periodically. Normally it is not needed as the session would be refreshed when requests start failing with a 401 (authentication) or 403 (authorization) errors. In some cases when anonymous writes are allowed to the database and a VDU function is used to forbid writes based on the authenticated in username, requests with an expired session cookie will not fail with a 401 and the session will not be refreshed. To fix the issue using these two approaches: 1. Use cookie's max-age expiry time to schedule a refresh. To ensure that time is provided in the cookie, switch the the option to enable it by default. This handles the issue for endpoints which are updated with this commit. 2. For endpoints which do not put a max-age time in the cookie, use a value that's less than CouchDB's default auth timeout. If users changed their auth timeout value, and use VDUs in the pattern described above, and don't update their endpoints to version which sends max-age by default, they could adjust `[replicator] session_refresh_interval_sec` to their auth timeout minus some small delay. Of course refresh based on auth/authz failures should still works as before. Fixes apache#1607
Force couch_replicator_auth_session plugin to refresh the session periodically. Normally it is not needed as the session would be refreshed when requests start failing with a 401 (authentication) or 403 (authorization) errors. In some cases when anonymous writes are allowed to the database and a VDU function is used to forbid writes based on the authenticated in username, requests with an expired session cookie will not fail with a 401 and the session will not be refreshed. To fix the issue using these two approaches: 1. Use cookie's max-age expiry time to schedule a refresh. To ensure that time is provided in the cookie, switch the the option to enable it by default. This handles the issue for endpoints which are updated with this commit. 2. For endpoints which do not put a max-age time in the cookie, use a value that's less than CouchDB's default auth timeout. If users changed their auth timeout value, and use VDUs in the pattern described above, and don't update their endpoints to version which sends max-age by default, they could adjust `[replicator] session_refresh_interval_sec` to their auth timeout minus some small delay. Of course refresh based on auth/authz failures should still works as before. Fixes apache#1607
Force couch_replicator_auth_session plugin to refresh the session periodically. Normally it is not needed as the session would be refreshed when requests start failing with a 401 (authentication) or 403 (authorization) errors. In some cases when anonymous writes are allowed to the database and a VDU function is used to forbid writes based on the authenticated in username, requests with an expired session cookie will not fail with a 401 and the session will not be refreshed. To fix the issue using these two approaches: 1. Use cookie's max-age expiry time to schedule a refresh. To ensure that time is provided in the cookie, switch the the option to enable it by default. This handles the issue for endpoints which are updated with this commit. 2. For endpoints which do not put a max-age time in the cookie, use a value that's less than CouchDB's default auth timeout. If users changed their auth timeout value, and use VDUs in the pattern described above, and don't update their endpoints to version which sends max-age by default, they could adjust `[replicator] session_refresh_interval_sec` to their auth timeout minus some small delay. Of course refresh based on auth/authz failures should still works as before. Fixes apache#1607
Force couch_replicator_auth_session plugin to refresh the session periodically. Normally it is not needed as the session would be refreshed when requests start failing with a 401 (authentication) or 403 (authorization) errors. In some cases when anonymous writes are allowed to the database and a VDU function is used to forbid writes based on the authenticated in username, requests with an expired session cookie will not fail with a 401 and the session will not be refreshed. To fix the issue using these two approaches: 1. Use cookie's max-age expiry time to schedule a refresh. To ensure that time is provided in the cookie, switch the the option to enable it by default. This handles the issue for endpoints which are updated with this commit. 2. For endpoints which do not put a max-age time in the cookie, use a value that's less than CouchDB's default auth timeout. If users changed their auth timeout value, and use VDUs in the pattern described above, and don't update their endpoints to version which sends max-age by default, they could adjust `[replicator] session_refresh_interval_sec` to their auth timeout minus some small delay. Of course refresh based on auth/authz failures should still works as before. Fixes apache#1607
Force couch_replicator_auth_session plugin to refresh the session periodically. Normally it is not needed as the session would be refreshed when requests start failing with a 401 (authentication) or 403 (authorization) errors. In some cases when anonymous writes are allowed to the database and a VDU function is used to forbid writes based on the authenticated in username, requests with an expired session cookie will not fail with a 401 and the session will not be refreshed. To fix the issue using these two approaches: 1. Use cookie's max-age expiry time to schedule a refresh. To ensure that time is provided in the cookie, switch the the option to enable it by default. This handles the issue for endpoints which are updated with this commit. 2. For endpoints which do not put a max-age time in the cookie, use a value that's less than CouchDB's default auth timeout. If users changed their auth timeout value, and use VDUs in the pattern described above, and don't update their endpoints to version which sends max-age by default, they could adjust `[replicator] session_refresh_interval_sec` to their auth timeout minus some small delay. Of course refresh based on auth/authz failures should still works as before. Fixes #1607
Thank you! |
Expected Behavior
A replicator document with valid credentials for a target database should continue to present valid credentials when replicating. Even when a target database allows anonymous writes, there may be validate_doc_update scripts that make decisions based on the user performing the replication.
Current Behavior
If the target database does not require authentication, the replicator may function with the user context of the administrator creating the replication document until the authentication cookie expires. At this point, the target database will ignore the expired cookie and accept documents but any validate_doc_update scripts that make decisions based on user context will instead receive an 'undefined' user context.
Possible Solution
Steps to Reproduce (for bugs)
Context
Our Nunaliit tool makes a lot of decisions in the VDU about which documents can be updated based on roles and fields in documents. The configuration of Nunaliit permits decisions about whether or not to accept anonymous writes or to require valid users. In addition, valid users may be required to agree to terms (attribute on user doc because terms may be versioned, etc.) of use or take other steps before being granted write or edit permissions.
We have designed Nunaliit to work with couchdb without assuming that we are the only code touching it. Making configuration changes at a database level or customizing plugin settings is something we'd like to avoid. Ideally the cookie auth would have the same behaviour as the basic auth.
Your Environment
The text was updated successfully, but these errors were encountered: