johnbrett / hapi-auth-bearer-token

Simple Bearer authentication scheme plugin for hapi, accepts token by Header, Cookie or Query parameter.
MIT License
218 stars 46 forks source link

Error: Unknown authentication strategy #16

Closed technowar closed 9 years ago

technowar commented 9 years ago

I am trying to use this module to enable bearer token on my app. However, I am getting the error shown in the title.

I have been stuck for days now. Hoping anyone could help me.

I have user.js route

module.exports = [{
    'method' : 'GET',
    'path' : '/v1/users',
    'config' : {
        'handler' : function (request, reply) {
            User.find(function (error, data) {
                if (!error) {
                    reply(data)
                        .code(200)
                }
            });
        },
        'auth' : 'simple'
    }
}];

Now, inside my server.js,

Server.register([{
    'register' : require('hapi-auth-bearer-token')
}, {
    'register' : require('./api')
}], function (error) {
    if (!error) {
        Server.auth.strategy('simple', 'bearer-access-token', {
            'validateFunc' : function (token, callback) {
                if (token === "1234") {
                    callback(null, true, {
                        'token' : token
                    })
                } else {
                    callback(null, false, {
                        'token' : token
                    })
                }
            }
        });

        Server.start(function () {
            console.log('info', 'Server running at ' + Server.info.uri);
        });
    }
});

But I get Error: Unknown authentication strategy: simple in path: /v1/users

Complete error message:

    at Object.exports.assert (/var/nodevagrant/project/Interest/node_modules/hapi/node_modules/hoek/lib/index.js:663:11)
    at /var/nodevagrant/project/Interest/node_modules/hapi/lib/auth.js:139:14
    at Array.forEach (native)
    at internals.Auth._setupRoute (/var/nodevagrant/project/Interest/node_modules/hapi/lib/auth.js:136:24)
    at new module.exports.internals.Route (/var/nodevagrant/project/Interest/node_modules/hapi/lib/route.js:131:47)
    at internals.Connection._addRoute (/var/nodevagrant/project/Interest/node_modules/hapi/lib/connection.js:342:17)
    at internals.Connection._route (/var/nodevagrant/project/Interest/node_modules/hapi/lib/connection.js:334:18)
    at internals.Plugin._apply (/var/nodevagrant/project/Interest/node_modules/hapi/lib/plugin.js:432:14)
    at internals.Plugin.route (/var/nodevagrant/project/Interest/node_modules/hapi/lib/plugin.js:407:10)
    at Object.exports.register (/var/nodevagrant/project/Interest/api/index.js:8:9)
technowar commented 9 years ago

I figured it out.

johnbrett commented 9 years ago

Hi Johmel, glad you got sorted, can you post the solution so anyone else hitting the same problem will be able to figure it out? Thank you! Any other problems let me know.

On Thu, 22 Jan 2015 08:11 Johmel Rey Pintor notifications@github.com wrote:

I figured it out.

— Reply to this email directly or view it on GitHub https://github.com/johnbrett/hapi-auth-bearer-token/issues/16#issuecomment-70984902 .

technowar commented 9 years ago

Instead of adding

Server.auth.strategy('simple', 'bearer-access-token', {
  'validateFunc' : function (token, callback) {
        ....
  }
});

to my server.js file, I added it to my index.js inside my /api folder.

My index.js now looks like this,

var User = require('./controllers/user');

exports.register = function (plugin, options, next) {
  plugin.auth.strategy('simple', 'bearer-access-token', {
    'validateFunc' : function (token, callback) {
        ....
    }
 });

  plugin.route(User);

  next();
};

exports.register.attributes = {
  'name' : 'api',
  'version' : 1.0
};
johnbrett commented 9 years ago

Ah so you were registering a route with the 'simple' auth strategy before you had actually registered the 'simple' strategy itself, very easy to do. Thanks for posting the solution to the issue.

One thing I usually do for auth in Hapi is to create a plugin called authentication which register's the auth scheme plugin - hapi-auth-bearer-token in this case, and then also registers the strategy, that way each plugin has only one concern so you don't have your api plugin also responsible for authentication.

If you want to try this pattern let me know and I can elaborate more with code samples etc.

technowar commented 9 years ago

@johnbrett yes please.

johnbrett commented 9 years ago

Hey @technowar, here is an example of an authentication plugin, where you can encapsulate all auth related functionality, e.g. scheme registration, strategy function.

Registering the authentication plugin: https://github.com/johnbrett/hapi-level-sample/blob/master/index.js#L7 The auth plugin itself: https://github.com/johnbrett/hapi-level-sample/blob/master/plugins/authentication/index.js

Any questions or feedback on this approach are much welcomed, hope it helps :)

technowar commented 9 years ago

Thank you @johnbrett.

jgauna commented 9 years ago

I can't figure out how to solve this issue. I'm using this hapi js boilerplate https://github.com/poeticninja/hapi-ninja from @poeticninja and I have this code:

base.js

    createOrder: {
        handler: function(request, reply) {
            (...)
            server.methods.createOrder(json, function (err, result) {
                if (err) {
                    reply(err).code(500);
                } else {
                    reply(json).code(200);
                }                
            });
        },
        validate: {
            payload: {
               (...)
            }
        },
        auth: 'simple',
        id: 'createOrder'
    },

And in plugins.js

server.register([
    {
        register: require('hapi-auth-bearer-token'),
        options: function() {
            server.auth.strategy('simple', 'bearer-access-token', {
                allowQueryToken: true,              // optional, true by default
                allowMultipleHeaders: false,        // optional, false by default
                accessTokenName: 'access_token',    // optional, 'access_token' by default
                validateFunc: function( token, callback ) {
                    // For convenience, the request object can be accessed 
                    // from `this` within validateFunc.
                    var request = this;
                    // Use a real strategy here, 
                    // comparing with a token from your database for example
                    if(token === "1234"){
                        callback(null, true, { token: token })
                    } else {
                        callback(null, false, { token: token })
                    }
                }
            });
        }
    },
    {
        register: require('hapi-mongo-models'),
        options: mongoOptions
    },
    {
        register: require("good"),
        options: goodOptions
    },
    {
        register: require("hapi-assets"),
        options: assetOptions
    },
    {
        register: require("hapi-named-routes")
    },
    {
        register: require("hapi-cache-buster")
    }
], function (err) {
    if (err) {
        console.error('Failed to load a plugin:', err);
        throw err;
    }
});

I'm getting Error: Unknown authentication strategy: simple in path: /createOrder

johnbrett commented 9 years ago

Hi @jgauna, the options parameter in server.register() generally expects an object of configuration properties, although I suppose you can use it for whatever you want if its your own plugin. Either way, hapi-auth-bearer-token doesn't expect the default strategy to be passed in that way, so never calls the function passed in meaning the simple strategy is never set. Is there any reason you were trying to set your authentication strategy there out of curiosity?

To fix - you need to take the server.auth.strategy() code outside of the options parameter - move it into the callback of server.register() after:

], function (err) {
    if (err) {
        console.error('Failed to load a plugin:', err);
        throw err;
    }
    // -- put the server.auth.strategy(...) code here --
});

Let me know if you've any troubles with this :)

jgauna commented 9 years ago

That won't work. Here's what I did:

server.js

(...)
// Bootstrap Hapi Server Plugins
require('./server/config/plugins');

// Bootstrap Hapi Server Plugins
require('./server/config/methods');

// Bootstrap Auths
require('./server/config/auths');
(...)

auths.js

// Load the server
var settings = require('./settings'),
    server = require(settings.rootPath + '/server'),
    crypto = require('crypto'),
    md5 = require('MD5');

server.auth.strategy('simple', 'bearer-access-token', {
    allowQueryToken: true,              // optional, true by default
    allowMultipleHeaders: false,        // optional, false by default
    accessTokenName: 'access_token',    // optional, 'access_token' by default
    validateFunc: function(token, callback) {
        // For convenience, the request object can be accessed 
        // from `this` within validateFunc.
        var request = this;

        console.log("TOKEEEEN")
        console.log(token)

        console.log(request)
        // Use a real strategy here, 
        // comparing with a token from your database for example
        if (token === "1234") {
            callback(null, true, { token: token })
        } else {
            callback(null, false, { token: token })
        }
    }
});

Thanks!

johnbrett commented 9 years ago

I've a feeling the server variable in your auths.js is not actually a connection instance, just what is returned from Hapi.Server (presuming you are using Hapi 8 ??).

server.auth.strategy() needs to be run against an actual server connection instance (acquired by running server.connection()).

Can you attach the rest of server.js so I can see how you're passing the connection instance to auths.js?

Is this project on Github by any chance? If I could see the code and error I could diagnose this much quicker :) What error are you actually receiving also?

jgauna commented 9 years ago

I figured it out. I have this working now. The only issue I have is the one I opened in:

https://github.com/johnbrett/hapi-auth-bearer-token/issues/19

ahmad-moussawi commented 8 years ago

@johnbrett thanks for this, very useful. https://github.com/johnbrett/hapi-level-sample/blob/master/plugins/authentication/index.js

johnbrett commented 8 years ago

No prob @ahmad-moussawi - thanks for letting me know it was useful, makes it all the worthwhile :)

johnbrett commented 7 years ago

you mention: var bearerSimple= require('hapi-auth-bearer-simple')

hapi-auth-bearer-simple is a different module to this one, this is hapi-auth-bearer-token.

You're best off opening an issue on their repo: https://github.com/Salesflare/hapi-auth-bearer-simple ;)

LovikaJain commented 7 years ago

Yeah just noticed thanks :)