medic / cht-conf

A command-line interface for configuring Community Health Toolkit applications
https://communityhealthtoolkit.org
GNU Affero General Public License v3.0
23 stars 25 forks source link

Use AuthSession cookie for login instead of basic auth #582

Open dianabarsan opened 10 months ago

dianabarsan commented 10 months ago

Describe the issue We're discussing increasing pbkdf2 iterations for CouchDb. This will mean that computing the hashed password every time basic auth is used will become a costly server-side operation.

Describe the improvement you'd like Instead of using basic auth for every request, make one initial _session request, and use the provided AuthSession cookie to authenticate all following requests within one conf run.

Describe alternatives you've considered None.

garethbowen commented 10 months ago

I've been working on a prototype for this...

garethbowen commented 9 months ago

@dianabarsan Here is my very simple test script for the cht-conf version of cookie auth:

This should be a very simple drop in solution for cht-conf which uses rpn in the api file, but it's blocked on https://github.com/medic/cht-conf/pull/583

const nodefetch = require('node-fetch');

let c;

const getAuthSessionCookie = async () => {

  if (c) {
    return c;
  }

  const headers = new nodefetch.Headers({
    'Content-Type': 'application/json'
  });

  const body = JSON.stringify({ username: 'iterations', password: 'pass' });
  const t0 = performance.now();
  const res = await nodefetch('http://localhost:5988/_session', { headers, method: 'POST', body });
  const t1 = performance.now();
  console.log(`BASIC AUTH: ${t1-t0}`);
  const cookies = res.headers.raw()['set-cookie']
  const cookie = cookies[0];
  const authSessionCookie = cookie.split(';')[0];
  c = authSessionCookie.split('=')[1];

  return c;
};

const makeRequest = async () => {
  const sessionCookie = await getAuthSessionCookie();
  const headers = new nodefetch.Headers({
    'Content-Type': 'application/json'
  });
  headers.append("cookie", `AuthSession=${sessionCookie}`);
  const t0 = performance.now();
  const res = await nodefetch('http://localhost:5988/medic/branding', { headers });
  const t1 = performance.now();
  console.log(`COOKIE AUTH: ${t1-t0}`);
  console.log(res.status);
  const body = await res.json();
  console.log(body);
};

const go = async () => {
  while(true) {
    await makeRequest();
    await new Promise(resolve => setTimeout(resolve, 20000));
  }
};

go();
garethbowen commented 2 months ago

@dianabarsan I think this is merged and released now - can you confirm?