1

TL;DR The problem is how to get the the user information from a jwt

I'm trying to get the information of a user from the jwt if one is sent on the request but I don't want to close the endpoint to only logged in users.

I don't want to close the endpoint with the authenticate hook but I don't know how to get the user information without it.

I'm using a local strategy with jwt.

Joe
  • 41,484
  • 20
  • 104
  • 125
2JN
  • 553
  • 6
  • 11

4 Answers4

1

Even if you don't use the authentication hook, the authentication information of the request (if any) will be available in params.authentication. You can do whatever you want with it in your own hook:

module.exports = () => async context => {
  const { authentication } = context.params;
  // authentication will e.g. be { strategy: 'jwt', accessToken }

  // do whatever you like here including throwing errors
}

To get the user information or allow anonymous access see the Anonymous Authentication cookbook recipe.

Daff
  • 43,734
  • 9
  • 106
  • 120
  • this will include the token and the strategy, but not the decoded user etc. correct? that would need to be manual? – Joe Oct 01 '19 at 00:35
  • 1
    Yes but the anonymous strategy would handle all of that. – Daff Oct 01 '19 at 03:40
  • They way I did it since I was making a second call on the backend was that I just checked on the `params.header` if the token was been sent. ```if (params.headers && params.headers.authorization) await this.app.service('reservation').create(dataReserv, params) else await this.app.service('reservation').create(dataReserv)``` – 2JN Oct 01 '19 at 17:43
1

The method with "try/catch" is good, but there is another way based on hooks.

1) Create custom hooks isAuth.js:

module.exports = (context) => {
  return !!(context.params.headers.authorization
    && context.params.headers.authorization !== 'null'
    && context.params.headers.authorization !== '');
};

2) Fix the service hooks.js(app.service('/my-url').hooks(hooks)) in which method authorization will be optional. NOTE: if the user is not authorized, then in "params.user" object "user" will be absent.

const { iff } = require('feathers-hooks-common');
const { authenticate } = require('@feathersjs/authentication').hooks;
const isAuth = require('isAuth');

module.exports = {
  before: {
    find: [iff(isAuth, authenticate('jwt'))],
  },
  after: {}
};
Andrinux
  • 364
  • 5
  • 9
0

You can also do a try/catch around the authenticate hook to attempt to authenticate a route but not fail because of it e.g.

const tryAuth = async hook => {
  try {
    return await authenticate(hook); 
  } catch(err) {
    // do nothing?
    return hook;
  }
};

in which case, if there was a valid token, you'll have params.user and authenticated = true otherwise not.

Joe
  • 41,484
  • 20
  • 104
  • 125
0

This is the only method it worked for me.

const { iff } = require('feathers-hooks-common');
const { authenticate } = require('@feathersjs/authentication').hooks;

module.exports = {
    before: {
        all: [iff(
            (({ params: { headers: { authorization }}}) => authorization),
            authenticate('jwt')
        )],
        find: [],
        get: [],
        create: [],
        update: [],
        patch: [],
        remove: []
    },

    after: {
        all: [],
        find: [],
        get: [],
        create: [],
        update: [],
        patch: [],
        remove: []
    },

    error: {
        all: [],
        find: [],
        get: [],
        create: [],
        update: [],
        patch: [],
        remove: []
    }
};

I just verified that the authorization token was sent.

2JN
  • 553
  • 6
  • 11