mardi 8 mai 2018

Design pattern for proxy auth

I want to make authenticated requests to certain API using a service account. Only certain users would be able to do these requests. So I have a double authentication schema:

  1. Check that the user is logged in: If there's an Authorization Bearer header and it's valid, I accept the request.

  2. Make authenticated request: I get a token that expires every 4 hours. With this token I make the proxied requests to the real backend

authorized requests by proxy

QUESTION: Is there already a pattern to do so? Maybe certain way of organizing functions and code, or even a library? Any article about it?

Right now I use something like this toy-code:

const express = require('express')
const app = express()
// moc function
const getFromDb = () => ({user: '1234', pass:'asdf'});
// information for the login process
const API_CREDENTIALS = getFromDb();
// result from the login
let API_AUTHORIZATION = {};


/**
 * Use API_CREDENTIALS to get API_AUTHORIZATION
 */
function login(){
  API_AUTHORIZATION = {
    last: +new Date(),
    token: '23k4jblck2j3h4lkjcvhs|f2kvlkj'
  };
  console.log('loged in with credentials:', API_AUTHORIZATION);
  return Promise.resolve(API_AUTHORIZATION);
}

/**
 * Make the request to the proxied endpoint
 */
function apiEndpointRequest(endpoint){
  const isTokenFresh = API_AUTHORIZATION.last + 240 * 60 * 1000 > new Date();
  if (API_AUTHORIZATION.token && isTokenFresh) {
    // some logic here
    const data = {data:'there be data'};
    console.log('called api function:');
    return Promise.resolve(data);
  }
  else return Promise.reject(new Error('No token, or expired one'));
}

/**
 * Return the authorized request. If it fails run the login and repeat
 */
function apiAuthorizedRequest(endpoint){
  return apiEndpointRequest(endpoint)
    .catch(err => {
      console.error('An error occurred:', err.message);
      console.log('loging in...');
      return login().then(() => {
        return apiAuthorizedRequest(endpoint);
      });
    })
}

/**
 * Implement the interaction between the the user and the proxied API
 */
function requestHandler(req, res){
  const endpoint = req.url;
  apiAuthorizedRequest(endpoint).then(data => {
    console.log('computed data:', data);
    res.send(data);
  });
}

/**
 * Map all requests to the handler
 */
app.all('*', requestHandler);
app.listen(3000, () => {console.log('listening on port 3000')});

Aucun commentaire:

Enregistrer un commentaire