Skip to content

Commit

Permalink
feat: session token authentication
Browse files Browse the repository at this point in the history
Add support for AuthSession cookie
  • Loading branch information
paulpascal authored Jun 20, 2024
1 parent cd135b6 commit efbc9cf
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 12 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ If a different username is required, add the `--user` switch:

**NB** - When specifying the URL with `--url`, be sure not to specify the CouchDB database name in the URL. The CHT API will find the correct database.

### Using a session token for authentication

CHT Conf supports authentication using a session token by adding `--session-token` parameter:

cht --url=https://example.com:12345 --session-token=*my_token*

### Into an archive to be uploaded later

cht --archive
Expand Down
153 changes: 147 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"pouchdb-adapter-http": "^7.2.2",
"pouchdb-core": "^7.2.2",
"pouchdb-mapreduce": "^7.2.2",
"pouchdb-session-authentication": "^1.3.0",
"properties": "^1.2.1",
"queue-promise": "^2.2.1",
"readline-sync": "^1.4.10",
Expand Down
28 changes: 27 additions & 1 deletion src/lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,34 @@ const log = require('./log');
const url = require('url');

const cache = new Map();
const sessionCookieName = 'AuthSession';

// Helper function to create request headers with session token (if available)
const withSessionCookie = (...args) => {
const options = typeof args[0] === 'object' ? Object.assign({}, args[0]) : { url: args[0] };

if (args.length > 1) {
// Merge remaining arguments
Object.assign(options, ...args.slice(1));
}

const sessionToken = environment.sessionToken;
if (sessionToken || options.headers) {
options.headers = Object.assign(
{},
options.headers || {},
sessionToken ? { Cookie: `${sessionCookieName}=${sessionToken}` } : {}
);
}

return options;
};

const _request = (method) => (...args) => {
const requestOptions = withSessionCookie(...args);
return retry(() => rpn[method](requestOptions), { retries: 5, randomize: false, factor: 1.5 });
};

const _request = (method) => (...args) => retry(() => rpn[method](...args), { retries: 5, randomize: false, factor: 1.5 });
const request = {
get: _request('get'),
post: _request('post'),
Expand Down
6 changes: 4 additions & 2 deletions src/lib/db.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const PouchDB = require('pouchdb-core');
PouchDB.plugin(require('pouchdb-adapter-http'));
PouchDB.plugin(require('pouchdb-mapreduce'));
PouchDB.plugin(require('pouchdb-session-authentication'));

const ArchivingDB = require('./archiving-db');
const environment = require('./environment');
Expand All @@ -10,6 +11,7 @@ module.exports = () => {
return new ArchivingDB(environment.archiveDestination);
}

return new PouchDB(environment.apiUrl, { ajax: { timeout: 60000 } });
return new PouchDB(environment.apiUrl, {
session: environment.sessionToken,
});
};

7 changes: 5 additions & 2 deletions src/lib/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const initialize = (
apiUrl,
force,
skipTranslationCheck,
skipValidate
skipValidate,
sessionToken
) => {
if (state.initialized) {
throw Error('environment is already initialized');
Expand All @@ -28,7 +29,8 @@ const initialize = (
pathToProject,
force,
skipTranslationCheck,
skipValidate
skipValidate,
sessionToken
});
};

Expand All @@ -54,6 +56,7 @@ module.exports = {
get force() { return getState('force'); },
get skipTranslationCheck() { return getState('skipTranslationCheck'); },
get skipValidate() { return getState('skipValidate'); },
get sessionToken() { return getState('sessionToken'); },

/**
* Return `true` if the environment **seems** to be production.
Expand Down
3 changes: 2 additions & 1 deletion src/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ module.exports = async (argv, env) => {
apiUrl,
cmdArgs.force,
cmdArgs['skip-translation-check'],
skipValidate
skipValidate,
cmdArgs['session-token'],
);

if (requiresInstance && apiUrl) {
Expand Down
1 change: 1 addition & 0 deletions test/api-stub.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ module.exports = {
const port = server.address().port;
const couchUrl = `http://admin:pass@localhost:${port}/medic`;
sinon.stub(environment, 'apiUrl').get(() => couchUrl);
sinon.stub(environment, 'sessionToken').get(() => undefined);
module.exports.couchUrl = couchUrl;
module.exports.gatewayRequests = [];
},
Expand Down
Loading

0 comments on commit efbc9cf

Please sign in to comment.