feathersjs-ecosystem / authentication-jwt

[MOVED] JWT authentication strategy for feathers-authentication using Passport
https://github.com/feathersjs/feathers
MIT License
30 stars 10 forks source link

Using feathers-authentication-jwt for api key authentication #18

Closed jlpellicer closed 7 years ago

jlpellicer commented 7 years ago

I want to add API keys authentication to my feathesjs app. It should work by sending a header with a key assigned to the client, which should be checked against a database for validation.

So, if I understand correctly, I could potentially use feathers-authentication-jwt to do this (https://docs.feathersjs.com/api/authentication/jwt.html) by tweaking the configuration and Verifier.

Seems that my problem is that I can't get my Verifier to work and the default one is invoked, so no authentication for you, let me show you.

// authentication.js
'use strict';

const authentication = require('feathers-authentication');
const jwt = require('feathers-authentication-jwt');
const local = require('feathers-authentication-local');
const apikey = require('feathers-authentication-jwt'); // <-- my api key authentication
const Verifier = require('feathers-authentication-jwt').Verifier; // <-- working? apparently yes

console.log('VERIFIER', Verifier); //<-- what is `Verifier`? It's a function

module.exports = function () {
    // do my own verification stuff
    class apiKeyVerifier extends Verifier {
        verify (req, payload, done) {
            console.log('VERIFY');
            done (null, payload);
        }
    }
    const app = this;
    const config = app.get('authentication');

    // Set up authentication with the secret
    app.configure(authentication(config));
    app.configure(jwt());
    app.configure(local());
    console.log('API VERIFIER', apiKeyVerifier); // <-- what is `apiKeyVerifier`? a class
    app.configure(apikey({
        name: 'apikey',
        service: 'api-keys',
        entity: 'api-keys',
        idField: 'api_keys_id',
        header: 'x-api-key',
        Verifier: apiKeyVerifier
    }));

    // The `authentication` service is used to create a JWT.
    // The before `create` hook registers strategies that can be used
    // to create a new valid JWT (e.g. local or oauth2)
    app.service('authentication').hooks({
        before: {
            create: [
                authentication.hooks.authenticate(config.strategies)
            ],
            remove: [
                authentication.hooks.authenticate('jwt')
            ]
        }
    });
};

What happens when I try to authorize? I try like this:

curl -X POST \
  http://localhost:5000/authentication \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/x-www-form-urlencoded' \
  -H 'x-api-key: &xh&vtK9s¿Gr<JG' \
  -d strategy=apikey

I get this response:

feathers-authentication:passport:authenticate Authentication strategy 'apikey' failed { JsonWebTokenError: jwt malformed
      at Object.module.exports [as verify] (/Users/transistor/Documents/WebServer/asc-api/node_modules/jsonwebtoken/verify.js:54:17)
      at Function.module.exports [as JwtVerifier] (/Users/transistor/Documents/WebServer/asc-api/node_modules/passport-jwt/lib/verify_jwt.js:4:16)
      at JwtStrategy.authenticate (/Users/transistor/Documents/WebServer/asc-api/node_modules/passport-jwt/lib/strategy.js:91:17)
      at /Users/transistor/Documents/WebServer/asc-api/node_modules/feathers-authentication/lib/passport/authenticate.js:131:18
      at /Users/transistor/Documents/WebServer/asc-api/node_modules/feathers-authentication/lib/passport/authenticate.js:38:14
      at Object.<anonymous> (/Users/transistor/Documents/WebServer/asc-api/node_modules/feathers-authentication/lib/hooks/authenticate.js:80:55)
      at process._tickCallback (internal/process/next_tick.js:103:7) name: 'JsonWebTokenError', message: 'jwt malformed' } undefined
info: error: authentication - Method: create: jwt malformed
error:  NotAuthenticated: jwt malformed
      at NotAuthenticated.ExtendableBuiltin (/Users/transistor/Documents/WebServer/asc-api/node_modules/feathers-errors/lib/index.js:21:28)
      at NotAuthenticated.FeathersError (/Users/transistor/Documents/WebServer/asc-api/node_modules/feathers-errors/lib/index.js:96:116)
      at new NotAuthenticated (/Users/transistor/Documents/WebServer/asc-api/node_modules/feathers-errors/lib/index.js:149:117)
      at /Users/transistor/Documents/WebServer/asc-api/node_modules/feathers-authentication/lib/hooks/authenticate.js:102:31
      at process._tickCallback (internal/process/next_tick.js:103:7)

Which, if I'm not mistaken, it means that my Verifier is not being used, so it fails because it isn't a jwt.

So, first, am I on the right track? I mean, can I use this strategy to authenticate by API keys?

Second, if so, what am I doing wrong?

Thanks!

kfern commented 7 years ago

Hi @jlpellicer

Have you made any progress? I am dealing with a similar problem trying to use passport-custom but I can`t find documentation about how integrate it with feathers.

I think "Authentication strategy 'apikey' failed" because you have not defined apikey strategy. passport-custom allow define your own strategy:

passport.use('strategy-name', new CustomStrategy(
  function(req, callback) {
    // Do your custom user finding logic here, or set to false based on req object
    callback(null, user);
  }
));

Any ideas will be welcome ;-)

Salu2 Fernando

roelvan commented 6 years ago

This one might help you guys out: https://docs.feathersjs.com/guides/auth/recipe.custom-auth-strategy.html (the Creating a Custom API Key Auth Strategy section esp.)