How to handle authorization token

451 Views Asked by At

I would like to add auth token to http request header every time a http request sent and if authorization fails, I want to redirect user to the login. Should I decorate Http Driver or is there a better way to do it?

I came with a solution that decorates http driver. But I'm not sure this is the correct way of doing it. Here's the code so far I have written:

import Rx from 'rx';
import {makeHTTPDriver} from '@cycle/http';

function makeSecureHTTPDriver({eager = false} = {eager: false}) {

    return function secureHTTPDriver(request$) {
        const httpDriver = makeHTTPDriver(eager);

        const securedRequest$ = request$
            .map(request => {
                const token = localStorage.getItem('token');

                if (token) {
                    request.headers = request.headers || {};
                    request.headers['X-AUTH-TOKEN'] = token;
                }

                return request;
            });

        const response$ = httpDriver(securedRequest$);
        //todo: check response and if it fails, redirect to the login page

        return response$;
    }
}

export default makeSecureHTTPDriver;

Here is the code how I use makeSecureHttpDriver

const drivers = {
        DOM: makeDOMDriver('#app'),
        HTTP: makeSecureHttpDriver()
    };

2

There are 2 best solutions below

0
On

I'm not sure if this will help but HTTP driver is superagent under the hood so you can pass it an object like with required info like here.

But in regards to your issue I think that the HTTP driver might need this option added to the driver it self so you can dictate if the driver should be secure or not eg:

const drivers = {
    DOM: makeDOMDriver('#app'),
    HTTP: makeSecureHttpDriver({secure:true})
};

Because your implementation looks ok to me, it might be worth having it in the driver itself. I'd create an issue in the HTTP driver repo and see what the community think, you can also ask people to interact via the gitter channel :-)

0
On

This is a little late, I don't frequent SO very much. I'd suggest using other drivers instead to avoid placing any logic in your drivers.

import storageDriver from '@cycle/storage'
import {makeHTTPDriver} from '@cycle/http'

function main(sources) {
 const {storage, HTTP} = sources
 const token$ = storage.local.getItem('token')
  .startWith(null)

 const request$ = createRequest$(sources)

 const secureRequest$ = request$.withLatestFrom(token$, 
   (request, token) => token ? 
     Object.assign(request, {headers: {'X-AUTH-HEADER' : token }) : 
     request
 )
 return {HTTP: secureRequest$, ...}
}

Cycle.run(main, {
 ...
 storage: storageDriver,
 HTTP: makeHTTPDriver()
})