Set session from an http header

Hi,

We have multiple annotators and would like to capture the user who performed the annotation. We use Cloudflare in front of prodigy which adds authentication transparently. It's essentially just a reverse proxy and handily adds in an http header on each request:

Cf-Access-Authenticated-User-Email: user@example.com

We'd like to use this as the session id, but I can't figure out the best approach - it's the ner.manual recipe we'll be using primarily - could this be wrapped in a custom recipe?

thanks!

Barnaby

Hi! This is a nice idea and I wonder if we could implement this as a default feature, since it's a nice alternative to the query string-based session names. The underlying functionality is all there – only that Prodigy currently lets you set the session ID / name via a ?session= query parameter attached to the URL. This makes it easy to set sessions at runtime: https://prodi.gy/docs/api-web-app#multi-user-sessions

So if you can somehow set up a redirect that uses the user header to append the session to the URL when forwarding to Prodigy, that'd be the easiest solution. If you know the possible users, you can also set the PRODIGY_ALLOWED_SESSIONS env variable on startup to restrict the names of allowed session names. This isn't a replacement for authentication, but it helps prevent typos and/or mistakes and wrongly attributed annotations if the auth header isn't set correctly etc.

Thank you for the pointer - I knocked up a quick Cloudflare Worker script to do this redirect. The first javascript I've written in some time! :smile:

In case it's useful to any of your other users in future:

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

/**
 * Add session onto / requests, fetch directly all others.
 * @param {Request} request
 */
async function handleRequest(request) {
  let url = new URL(request.url);
  if (url.pathname == '/' && !url.searchParams.has("session")) {
    // add ?session=user onto requests to /
    const email = request.headers.get('Cf-Access-Authenticated-User-Email');
    const user = email.split('@')[0];
    url.searchParams.append("session", user);
    return Response.redirect(url, 302);
  } else {
    // send directly to origin
    return fetch(request);
  }
}
1 Like

Thanks for sharing, this looks pretty straightforward :smiley: Glad it worked!