From 6483b29da107752e59e307935527deb32aa2c33a Mon Sep 17 00:00:00 2001 From: Rich Ellis Date: Tue, 3 Dec 2019 15:13:38 +0000 Subject: [PATCH 1/2] Used application/json for session POST Modified CookieTokenManager to use JSON. Decoded credentials from URL before passing to CookieTokenManager. Improved documentation of characters that must be encoded. --- CHANGES.md | 4 ++++ README.md | 7 +++++++ lib/tokens/CookieTokenManager.js | 3 ++- plugins/cookieauth.js | 5 +++-- test/plugins/cookieauth.js | 4 ++-- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 6262e56e..4e0f2b90 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,9 @@ # UNRELEASED - [FIXED] Expose BasePlugin. +- [FIXED] Prevent double encoding of credentials passed in URL user information + when using the `cookieauth` plugin. +- [IMPROVED] Documented the characters that are required to be encoded in URL + user information. - [IMPROVED] Documented the legacy compatibility behaviour that always adds the `cookieauth` plugin when using the initialization callback functionality. diff --git a/README.md b/README.md index eeaa718f..f11720d2 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,13 @@ var Cloudant = require('@cloudant/cloudant'); var cloudant = Cloudant("http://MYUSERNAME:MYPASSWORD@localhost:5984"); ~~~ +**Note**: If you pass credentials in the user information subcomponent of the URL +then they must be [percent encoded](https://tools.ietf.org/html/rfc3986#section-3.2.1). +Specifically the characters `: / ? # [ ] @ %` _MUST_ be precent-encoded, other +characters _MAY_ be percent encoded. +Credentials must not be percent encoded when passing them via other configuration +options besides `url`. + **Note**: If you pass in a `username`, `password`, and `url` that contains credentials, the `username` and `password` will supercede the credentials within the `url`. For example, `myusername` and `mypassword` will be used in the code diff --git a/lib/tokens/CookieTokenManager.js b/lib/tokens/CookieTokenManager.js index 310f929b..3e7e84e4 100644 --- a/lib/tokens/CookieTokenManager.js +++ b/lib/tokens/CookieTokenManager.js @@ -29,7 +29,8 @@ class CookieTokenManager extends TokenManager { this._client({ url: this._sessionUrl, method: 'POST', - form: { + json: true, + body: { name: this._username, password: this._password }, diff --git a/plugins/cookieauth.js b/plugins/cookieauth.js index f86aa2b9..6a1f989c 100644 --- a/plugins/cookieauth.js +++ b/plugins/cookieauth.js @@ -49,8 +49,9 @@ class CookiePlugin extends BasePlugin { client, this._jar, u.format(sessionUrl, {auth: false}), - sessionUrl.username, - sessionUrl.password + // Extract creds from URL and decode + decodeURIComponent(sessionUrl.username), + decodeURIComponent(sessionUrl.password) ); if (cfg.autoRenew) { diff --git a/test/plugins/cookieauth.js b/test/plugins/cookieauth.js index 105c8c2d..d73510e5 100644 --- a/test/plugins/cookieauth.js +++ b/test/plugins/cookieauth.js @@ -21,10 +21,10 @@ const nock = require('../nock.js'); const uuidv4 = require('uuid/v4'); // random const ME = process.env.cloudant_username || 'nodejs'; -const PASSWORD = process.env.cloudant_password || 'sjedon'; +const PASSWORD = process.env.cloudant_password || 'sjedon!@#"£$%^&*()'; const SERVER = process.env.SERVER_URL || `https://${ME}.cloudant.com`; const SERVER_NO_PROTOCOL = SERVER.replace(/^https?:\/\//, ''); -const SERVER_WITH_CREDS = `https://${ME}:${PASSWORD}@${SERVER_NO_PROTOCOL}`; +const SERVER_WITH_CREDS = `https://${ME}:${encodeURIComponent(PASSWORD)}@${SERVER_NO_PROTOCOL}`; const DBNAME = `/nodejs-cloudant-${uuidv4()}`; const COOKIEAUTH_PLUGIN = [ { cookieauth: { autoRenew: false } } ]; From 245cbb05958157168b2c4c78b7ed5075627eec56 Mon Sep 17 00:00:00 2001 From: Rich Ellis Date: Wed, 4 Dec 2019 09:59:53 +0000 Subject: [PATCH 2/2] Added example to percent encoding documentation --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f11720d2..64abe19e 100644 --- a/README.md +++ b/README.md @@ -156,14 +156,20 @@ var Cloudant = require('@cloudant/cloudant'); var cloudant = Cloudant("http://MYUSERNAME:MYPASSWORD@localhost:5984"); ~~~ -**Note**: If you pass credentials in the user information subcomponent of the URL -then they must be [percent encoded](https://tools.ietf.org/html/rfc3986#section-3.2.1). -Specifically the characters `: / ? # [ ] @ %` _MUST_ be precent-encoded, other -characters _MAY_ be percent encoded. +**Note**: It is preferred to pass credentials using the `account`/`username` and +`password` configuration options rather than as part of the URL. However, if you +choose to pass credentials in the user information subcomponent of the URL then +they must be [percent encoded](https://tools.ietf.org/html/rfc3986#section-3.2.1). +Specifically within either the username or passowrd the characters `: / ? # [ ] @ %` +_MUST_ be precent-encoded, other characters _MAY_ be percent encoded. +For example for the username `user123` and password `colon:at@321`: +``` +https://user123:colon%3aat%40321@localhost:5984 +``` Credentials must not be percent encoded when passing them via other configuration options besides `url`. -**Note**: If you pass in a `username`, `password`, and `url` that contains +If you pass in `username` and `password` options and a `url` that contains credentials, the `username` and `password` will supercede the credentials within the `url`. For example, `myusername` and `mypassword` will be used in the code below during authentication: