summaryrefslogtreecommitdiff
path: root/share/www/script/test
diff options
context:
space:
mode:
authorDamien F. Katz <damien@apache.org>2009-08-04 19:50:46 +0000
committerDamien F. Katz <damien@apache.org>2009-08-04 19:50:46 +0000
commit8e2215ee6306b0f4c13553796d401e9f5f93bcb6 (patch)
tree948b9179887e73379bc445b9ad058de3a0bbe870 /share/www/script/test
parentfd72a9bc48ebab76976f538c28459a0e26aa1750 (diff)
Initial check-in of OAuth and cookie authentication.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@800938 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'share/www/script/test')
-rw-r--r--share/www/script/test/changes.js4
-rw-r--r--share/www/script/test/cookie_auth.js162
-rw-r--r--share/www/script/test/oauth.js166
-rw-r--r--share/www/script/test/security_validation.js12
-rw-r--r--share/www/script/test/show_documents.js2
5 files changed, 337 insertions, 9 deletions
diff --git a/share/www/script/test/changes.js b/share/www/script/test/changes.js
index 1800ca82..d8abcc71 100644
--- a/share/www/script/test/changes.js
+++ b/share/www/script/test/changes.js
@@ -195,8 +195,8 @@ couchTests.changes = function(debug) {
// test for userCtx
run_on_modified_server(
[{section: "httpd",
- key: "authentication_handler",
- value: "{couch_httpd, special_test_authentication_handler}"},
+ key: "authentication_handlers",
+ value: "{couch_httpd_auth, special_test_authentication_handler}"},
{section:"httpd",
key: "WWW-Authenticate",
value: "X-Couch-Test-Auth"}],
diff --git a/share/www/script/test/cookie_auth.js b/share/www/script/test/cookie_auth.js
new file mode 100644
index 00000000..63ab21b9
--- /dev/null
+++ b/share/www/script/test/cookie_auth.js
@@ -0,0 +1,162 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+couchTests.cookie_auth = function(debug) {
+ // This tests cookie-based authentication.
+
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ // Simple secret key generator
+ function generateSecret(length) {
+ var secret = '';
+ for (var i=0; i<length; i++) {
+ secret += String.fromCharCode(Math.floor(Math.random() * 256));
+ }
+ return secret;
+ }
+ // this function will be called on the modified server
+ var testFun = function () {
+ try {
+ // try using an invalid cookie
+ var usersDb = new CouchDB("test_suite_users");
+ usersDb.deleteDb();
+ usersDb.createDb();
+
+ var password = "3.141592653589";
+
+ // Create a user
+ T(usersDb.save({
+ _id: "a1",
+ salt: "123",
+ password_sha: "8da1CtkFvb58LWrnup5chgdZVUs=",
+ username: "Jason Davies",
+ author: "Jason Davies",
+ type: "user",
+ roles: ["_admin"]
+ }).ok);
+
+ var validationDoc = {
+ _id : "_design/validate",
+ validate_doc_update: "(" + (function (newDoc, oldDoc, userCtx) {
+ // docs should have an author field.
+ if (!newDoc._deleted && !newDoc.author) {
+ throw {forbidden:
+ "Documents must have an author field"};
+ }
+ if (oldDoc && oldDoc.author != userCtx.name) {
+ throw {unauthorized:
+ "You are not the author of this document. You jerk."+userCtx.name};
+ }
+ }).toString() + ")"
+ };
+
+ T(db.save(validationDoc).ok);
+
+
+
+ T(CouchDB.login('Jason Davies', password).ok);
+ // update the credentials document
+ var doc = usersDb.open("a1");
+ doc.foo=2;
+ T(usersDb.save(doc).ok);
+
+ // Save a document that's missing an author field.
+ try {
+ // db has a validation function
+ db.save({foo:1});
+ T(false && "Can't get here. Should have thrown an error 2");
+ } catch (e) {
+ T(e.error == "forbidden");
+ T(db.last_req.status == 403);
+ }
+
+ // TODO should login() throw an exception here?
+ T(!CouchDB.login('Jason Davies', "2.71828").ok);
+ T(!CouchDB.login('Robert Allen Zimmerman', 'd00d').ok);
+
+ // test redirect
+ xhr = CouchDB.request("POST", "/_session?next=/", {
+ headers: {"Content-Type": "application/x-www-form-urlencoded"},
+ body: "username=Jason%20Davies&password="+encodeURIComponent(password)
+ });
+ // should this be a redirect code instead of 200?
+ T(xhr.status == 200);
+
+ usersDb.deleteDb();
+ // test user creation
+ T(CouchDB.createUser("test", "testpassword", "test@somemail.com", ['read', 'write']).ok);
+
+ // make sure we create a unique user
+ T(!CouchDB.createUser("test", "testpassword2", "test2@somemail.com", ['read', 'write']).ok);
+
+ // test login
+ T(CouchDB.login("test", "testpassword").ok);
+ T(!CouchDB.login('test', "testpassword2").ok);
+
+ // test update user without changing password
+ T(CouchDB.updateUser("test", "test2@somemail.com").ok);
+ result = usersDb.view("_auth/users", {key: "test"});
+ T(result.rows[0].value['email'] == "test2@somemail.com");
+
+
+ // test changing password
+ result = usersDb.view("_auth/users", {key: "test"});
+ T(CouchDB.updateUser("test", "test2@somemail.com", [], "testpassword2", "testpassword").ok);
+ result1 = usersDb.view("_auth/users", {key: "test"});
+ T(result.rows[0].value['password_sha'] != result1.rows[0].value['password_sha']);
+
+
+ // test changing password with passing old password
+ T(!CouchDB.updateUser("test", "test2@somemail.com", [], "testpassword2").ok);
+
+ // test changing password whith bad old password
+ T(!CouchDB.updateUser("test", "test2@somemail.com", [], "testpassword2", "badpasswword").ok);
+
+ // Only admins can change roles
+ T(!CouchDB.updateUser("test", "test2@somemail.com", ['read', 'write']).ok);
+
+ T(CouchDB.logout().ok);
+
+ T(CouchDB.updateUser("test", "test2@somemail.com").ok);
+ result = usersDb.view("_auth/users", {key: "test"});
+ T(result.rows[0].value['email'] == "test2@somemail.com");
+
+ // test changing password, we don't need to set old password when we are admin
+ result = usersDb.view("_auth/users", {key: "test"});
+ T(CouchDB.updateUser("test", "test2@somemail.com", [], "testpassword3").ok);
+ result1 = usersDb.view("_auth/users", {key: "test"});
+ T(result.rows[0].value['password_sha'] != result1.rows[0].value['password_sha']);
+
+ // Only admins can change roles
+ T(CouchDB.updateUser("test", "test2@somemail.com", ['read']).ok);
+
+ } finally {
+ // Make sure we erase any auth cookies so we don't affect other tests
+ T(CouchDB.logout().ok);
+ }
+ };
+
+ run_on_modified_server(
+ [{section: "httpd",
+ key: "authentication_handlers",
+ value: "{couch_httpd_auth, cookie_authentication_handler}"},
+ {section: "couch_httpd_auth",
+ key: "secret", value: generateSecret(64)},
+ {section: "couch_httpd_auth",
+ key: "authentication_db", value: "test_suite_users"}],
+ testFun
+ );
+
+};
diff --git a/share/www/script/test/oauth.js b/share/www/script/test/oauth.js
new file mode 100644
index 00000000..fb4ab818
--- /dev/null
+++ b/share/www/script/test/oauth.js
@@ -0,0 +1,166 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+couchTests.oauth = function(debug) {
+ // This tests OAuth authentication.
+
+ var authorization_url = "/_oauth/authorize";
+
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var dbA = new CouchDB("test_suite_db_a");
+ var dbB = new CouchDB("test_suite_db_b");
+ dbA.deleteDb();
+ dbA.createDb();
+ dbB.deleteDb();
+ dbB.createDb();
+
+ // Simple secret key generator
+ function generateSecret(length) {
+ var secret = '';
+ for (var i=0; i<length; i++) {
+ secret += String.fromCharCode(Math.floor(Math.random() * 256));
+ }
+ return secret;
+ }
+
+ function oauthRequest(path, message, accessor, method) {
+ message.action = path;
+ message.method = method || 'GET';
+ OAuth.SignatureMethod.sign(message, accessor);
+ var parameters = message.parameters;
+ if (method == "POST" || method == "GET") {
+ if (method == "GET") {
+ return CouchDB.request("GET", OAuth.addToURL(path, parameters));
+ } else {
+ return CouchDB.request("POST", path, {
+ headers: {"Content-Type": "application/x-www-form-urlencoded"},
+ body: OAuth.formEncode(parameters)
+ });
+ }
+ } else {
+ return CouchDB.request("GET", path, {
+ headers: {Authorization: OAuth.getAuthorizationHeader('', parameters)}
+ });
+ }
+ }
+
+ var consumerSecret = generateSecret(64);
+ var tokenSecret = generateSecret(64);
+
+ var host = CouchDB.host;
+ var dbPair = {
+ source: {
+ url: "http://" + host + "/test_suite_db_a",
+ auth: {
+ oauth: {
+ consumer_key: "key",
+ consumer_secret: consumerSecret,
+ token_secret: tokenSecret,
+ token: "foo"
+ }
+ }
+ },
+ target: "http://" + host + "/test_suite_db_b"
+ };
+
+ // this function will be called on the modified server
+ var testFun = function () {
+ try {
+ var usersDb = new CouchDB("test_suite_users");
+ usersDb.deleteDb();
+ usersDb.createDb();
+
+ // Create a user
+ T(CouchDB.createUser("jason", "testpassword", "test@somemail.com", ['test'], true).ok);
+
+ var accessor = {
+ consumerSecret: consumerSecret,
+ tokenSecret: tokenSecret
+ };
+
+ var signatureMethods = ["PLAINTEXT", "HMAC-SHA1"];
+ var consumerKeys = {key: 200, nonexistent_key: 400};
+
+ for (var i=0; i<signatureMethods.length; i++) {
+ for (var consumerKey in consumerKeys) {
+ var expectedCode = consumerKeys[consumerKey];
+ var message = {
+ parameters: {
+ oauth_signature_method: signatureMethods[i],
+ oauth_consumer_key: consumerKey,
+ oauth_token: "foo",
+ oauth_token_secret: tokenSecret,
+ oauth_version: "1.0"
+ }
+ };
+
+ // Get request token via Authorization header
+ xhr = oauthRequest("http://" + host + "/_oauth/request_token", message, accessor);
+ T(xhr.status == expectedCode);
+
+ // GET request token via query parameters
+ xhr = oauthRequest("http://" + host + "/_oauth/request_token", message, accessor, "GET");
+ T(xhr.status == expectedCode);
+
+ responseMessage = OAuth.decodeForm(xhr.responseText);
+
+ // Obtaining User Authorization
+ //Only needed for 3-legged OAuth
+ //xhr = CouchDB.request("GET", authorization_url + '?oauth_token=' + responseMessage.oauth_token);
+ //T(xhr.status == expectedCode);
+
+ xhr = oauthRequest("http://" + host + "/_session", message, accessor);
+ T(xhr.status == expectedCode);
+ if (xhr.status == expectedCode == 200) {
+ data = JSON.parse(xhr.responseText);
+ T(data.name == "jason");
+ T(data.roles[0] == "test");
+ }
+
+ xhr = oauthRequest("http://" + host + "/_session?foo=bar", message, accessor);
+ T(xhr.status == expectedCode);
+
+ // Replication
+ var result = CouchDB.replicate(dbPair.source, dbPair.target);
+ T(result.ok);
+ }
+ }
+
+ } finally {
+ }
+ };
+
+ run_on_modified_server(
+ [{section: "httpd",
+ key: "WWW-Authenticate", value: 'Basic realm="administrator",OAuth'},
+ {section: "couch_httpd_auth",
+ key: "secret", value: generateSecret(64)},
+ {section: "couch_httpd_auth",
+ key: "authentication_db", value: "test_suite_users"},
+ {section: "oauth_consumer_secrets",
+ key: "key", value: consumerSecret},
+ {section: "oauth_token_users",
+ key: "foo", value: "jason"},
+ {section: "oauth_token_secrets",
+ key: "foo", value: tokenSecret},
+ {section: "couch_httpd_oauth",
+ key: "authorization_url", value: authorization_url},
+ {section: "httpd",
+ key: "authentication_handlers",
+ value: "{couch_httpd_oauth, oauth_authentication_handler}, {couch_httpd_auth, default_authentication_handler}"}],
+ testFun
+ );
+};
diff --git a/share/www/script/test/security_validation.js b/share/www/script/test/security_validation.js
index 10553e5e..52f895bd 100644
--- a/share/www/script/test/security_validation.js
+++ b/share/www/script/test/security_validation.js
@@ -39,14 +39,14 @@ couchTests.security_validation = function(debug) {
run_on_modified_server(
[{section: "httpd",
- key: "authentication_handler",
- value: "{couch_httpd, special_test_authentication_handler}"},
+ key: "authentication_handlers",
+ value: "{couch_httpd_auth, special_test_authentication_handler}"},
{section:"httpd",
key: "WWW-Authenticate",
value: "X-Couch-Test-Auth"}],
function () {
- // try saving document usin the wrong credentials
+ // try saving document using the wrong credentials
var wrongPasswordDb = new CouchDB("test_suite_db",
{"WWW-Authenticate": "X-Couch-Test-Auth Damien Katz:foo"}
);
@@ -59,8 +59,8 @@ couchTests.security_validation = function(debug) {
T(wrongPasswordDb.last_req.status == 401);
}
- // test force_login=true.
- var resp = wrongPasswordDb.request("GET", "/_whoami?force_login=true");
+ // test force basic login
+ var resp = wrongPasswordDb.request("GET", "/_session?basic=true");
var err = JSON.parse(resp.responseText);
T(err.error == "unauthorized");
T(resp.status == 401);
@@ -104,7 +104,7 @@ couchTests.security_validation = function(debug) {
T(userDb.save(designDoc).ok);
// test the _whoami endpoint
- var resp = userDb.request("GET", "/_whoami");
+ var resp = userDb.request("GET", "/_session");
var user = JSON.parse(resp.responseText)
T(user.name == "Damien Katz");
// test that the roles are listed properly
diff --git a/share/www/script/test/show_documents.js b/share/www/script/test/show_documents.js
index a1138596..c87cfb0b 100644
--- a/share/www/script/test/show_documents.js
+++ b/share/www/script/test/show_documents.js
@@ -335,7 +335,7 @@ couchTests.show_documents = function(debug) {
var doc2 = {_id:"foo", a:2};
db.save(doc1);
- //create the conflict with a all_or_nothing bulk docs request
+ // create the conflict with an all_or_nothing bulk docs request
var docs = [doc2];
db.bulkSave(docs, {all_or_nothing:true});