Skip to content

Help need in implementing a custom authentication. #1197

@brahmos

Description

@brahmos

I'm trying to use the "implementation" part of the server.auth(name, options). But I think i'm making some silly mistake, may be because my lack of experience with node.js.

Can someone please help.

Here is my code for my custom auth. All i'm trying to do is authenticate the REST calls using two following headers

appId : 8983948934
appSecret : kjh23423hjk235234jkbk34

appSecret is dynamically generated and stored in a redis cache for a certain period. Clients get this key when they authenticate using OAuth

Code (auth.js which implements custom auth)

// Load modules

var Util = require('util');
var Hapi = require('hapi');


// Declare internals

var internals = {};


exports = module.exports = internals.Scheme = function (server, options) {

    Utils.assert(options, 'Invalid options');
    Utils.assert(options.scheme === 'api', 'Wrong scheme');
    Utils.assert(options.validateFunc, 'Missing required validateFunc method in configuration');
    Utils.assert(server, 'Server is required');

    this.settings = Utils.clone(options);                                               // Options can be reused
};


// Api Authentication

internals.Scheme.prototype.authenticate = function (request, callback) {

    var self = this;

    callback = Utils.nextTick(callback);

    var req = request.raw.req;
    var appId = req.headers.appId;
    var appSecret = req.headers.appSecret;

    if (!appId || !appSecret) {
        return callback(Hapi.boom.unauthorized(null, 'Api'));
    }

    var parts = authorization.split(/\s+/);

    if (appId = '') {
        return callback(Hapi.boom.unauthorized(null, "HTTP header appId, can't be empty"));
    }

    if (appSecret = '') {
        return callback(Hapi.boom.unauthorized(null, "HTTP header appSecret, can't be empty"));
    }


    var username = appId;
    var password = appSecret;


    this.settings.validateFunc(username, password, function (err, isValid, credentials) {

        credentials = credentials || null;

        if (err) {
            return callback(err, credentials, { log: { tags: ['auth', 'api'], data: err } });
        }

        if (!isValid) {
            return callback(Hapi.boom.unauthorized('Bad appId or appSecret', 'api'), credentials);
        }

        if (!credentials ||
            typeof credentials !== 'object') {

            return callback(Hapi.boom.badImplementation('Bad credentials object received for api auth validation'), null, { log: { tags: 'credentials' } });
        }

        // Authenticated

        return callback(null, credentials);
    });
};

Here is the code where i'm trying to use the "api" Auth scheme from above.

var Hapi = require('hapi');
Hapi.joi.version('v2');
var mongoose = require('mongoose');
var User = require('./models/user');
var routes = require('./routes');
var config = require('./config').development;
var apiAuth = require('./apps/auth/auth');

var validate = function (username, password, callback) {

// To be implemented, code will read the key from Redis and verify
};


var serverOptions = { 
    cache: {
            engine: 'redis',
            host: '127.0.0.1',
            port: 13257
    },
    auth: {
            'basic': {
                implementation: apiAuth,
                validateFunc: validate
            }
    },
    cors: true 
}

var debugOptions = {
  webSocketPort: 3000,
  debugEndpoint: '/debug/console',
  queryKey: 'debug'
};

var server = new Hapi.Server(config.hostname, config.port,serverOptions);

server.pack.require({ lout: { endpoint: '/docs' } }, function (err) {
    if (err) {
        console.log('Failed loading plugins');
    }
});

server.pack.require({ bassmaster: { batchEndpoint: '/v1/batch' } }, function (err) {
    if (err) {
        console.log('Failed loading plugins');
    }
});

server.pack.require('tv', debugOptions, function (err) {
  if (!err) {
    server.start();
  }
});


server.route(routes);

// Start the server
server.start(function () {
    console.log('server started on port: ', server.info.port);
    console.log('Debug console started at: ' + server.info.uri + server.plugins.tv.endpoint);
});

var cache = server.cache('authToken', { expiresIn: 60 * 60 * 1000 });

// Make the server available as the top-level export of this module.
module.exports.cache = cache;

I'm getting the following error.

Error: basic has invalid extension scheme implementation
    at Object.exports.assert (/Users/rakesh/Documents/code/cookit/node_modules/hapi/node_modules/hoek/lib/index.js:393:11)
    at internals.Auth.add (/Users/rakesh/Documents/code/cookit/node_modules/hapi/lib/auth/index.js:41:11)
    at /Users/rakesh/Documents/code/cookit/node_modules/hapi/lib/auth/index.js:81:14
    at Array.forEach (native)
    at internals.Auth.addBatch (/Users/rakesh/Documents/code/cookit/node_modules/hapi/lib/auth/index.js:79:27)
    at new module.exports.internals.Server (/Users/rakesh/Documents/code/cookit/node_modules/hapi/lib/server.js:198:20)
    at Object.<anonymous> (/Users/rakesh/Documents/code/cookit/index.js:52:14)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
9 Dec 20:46:18 - [nodemon] app crashed - waiting for file changes before starting...

Metadata

Metadata

Assignees

No one assigned

    Labels

    supportQuestions, discussions, and general support

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions