hapijs / basic Goto Github PK
View Code? Open in Web Editor NEWBasic authentication plugin
License: Other
Basic authentication plugin
License: Other
So, this might be a weird case, but I've got a structure where by I have hapi
installed in my project root, but then I have another module with hapi
as a peerDependency
, that module has hapi-auth-basic
as a dependency
, and when I do an install, I get two copies of hapi
installed, rather than just the one that's in the project root.
Thoughts?
It seems like the calling conventions for the server.register function have evolved over time, and it's not particularly clear how to wire up hapi-auth-basic in the register() function, especially if another plugin is already being registered.
For instance,
server.register(
[
{
register: require('hapi-bookshelf-models'),
options: {
knex: {
...
},
function(err) {
...
}
and I can't figure out how to slot in Basic into this style of invocation. Any help?
Just need to add attributes
.
How to pass the username and password to the validate func, should the request header contain keys username and password?
hapi should go to 11.x.x
lab should go to 7.x.x
Hi @mtharrison
At present the hapi-auth-basic plugin checks for the username
and password
in the authorization
header per the rfc2617 spec
This has to be base64 encoded Buffer which is not immediately apparent in the README.
Also requiring the username
and password
to be sent in the auth header is not as beginner-friendly to as sending them in POST payload
... would you accept a _pull request_ extending the plugin to accept the credentials via payload
(with tests and additions to the readme) ?
Hi,
I'm trying to run tests on my basic auth validate-function. How can I perform that? My setup is as follows: the validator-function is defined as a plugin and it does the following to register things:
server.pack.register(require('hapi-auth-basic'), function (err) {
if (err) {
throw "Basic-auth registration failed: " + JSON.stringify(err);
} else {
server.auth.strategy('gatekeeper', 'basic', {
validateFunc: validate
});
server.auth["default"]('gatekeeper');
}
});
The problem currently is such that when I setup a server in my test module, and load the gatekeeper-plugin there, it seems as if it is not called. Here's the calling part:
lab.test("login with real credentials, no AD", function (done) {
server.inject({
url: url.format(urlObj),
credentials: {
password: 'XXX',
username: 'YYY'
}
}, function (res) {
console.error("RES: %j", res);
Lab.expect(res.statusCode).to.equal(200);
done();
});
});
RES-printout's last property is strategy: "bypass"
. Where does that come from? How can I force my gatekeeper-strategy to be used?
I was testing this and was confused that when an error is provided to the validateFunc callback, that the status code is 200.
This stems from
https://github.com/hapijs/hapi-auth-basic/blob/master/lib/index.js#L68
I feel that when the authentication failed, it should always return an unauthorized Status code. Or am I missing something? What is the background for providing the error with a 200 Status code?
Hello hapi-auth-basic,
I am tinkering with your plugin and want to use a web form to set my authorization. Is this possible? Looking at your code I don't know what triggers the HTTP Auth modal to appear in my browser.
I probably have a shitty understanding of the way that authentication is supposed to occur in hapi, but the flow I naively want is.
{
method: 'POST',
path: '/login',
config: {
handler: function(request, reply) {
var username = request.payload.username;
var password = request.payload.password;
request.headers.authorization = // Set the auth header to "Basic base64unamepass"
return reply.redirect('/secretPageThatTequiresTheBasicAuthStrategy');
}
}
},
Then instead of the ugly little prompt asking me to put in my uname and pass it just refers to what i set in the login and I take advantage of the plugin to handle isAuthenticated and credentials.
If I am way off base please refer me to what you guys think is the best option.
Summary of changes required:
const
and let
where appropriateThere is probably a better way, but I was adding route level configuration in hapi for cors: { exposedHeaders: [''] }
to eliminate the WWW-Authenticate
header locally to get around google chrome's Authentication Required
pop-up. Is there a better way to go about this?
Do others use something like onPreResponse
to Alter Basic ...
to something like X-Basic ...
to get around browser triggers in this way. I obviously want to handle the form myself.
I think using dist-tags latest would be good for stable versions if there are rc versions around, as you do with hapi 7.
Hi,
can someone help to find place where I made mistake?
Problem - I couldn't log in, log in modal window opens again and again after forms filling.
The same behavior on auth plugin homepage example.
const Hapi = require("hapi");
const inert = require("inert");
const pino = require("hapi-pino");
const Bcrypt = require("bcrypt");
const basicAuth = require("hapi-auth-basic");
const port = process.env.PORT || 3000;
const host = process.env.HOST || "0.0.0.0";
const users = {
lex: {
username: "lex",
password: "qwerty",
name: "Lex Ushakov",
id: 0
},
vasili: {
username: "vasili",
password: "123456",
name: "Vasili Ushakov",
id: 1
}
};
async function validate(request, username, password) {
const user = users[username];
if (!user) return { credentials: null, isValid: false };
const credentials = { id: user.id, name: user.name };
const isValid = await Bcrypt.compare(password, user.password);
return { credentials, isValid };
}
process.on("unhandledRejection", err => {
console.error(err);
process.exit(1);
});
(async () => {
const server = Hapi.server({ port, host });
await server.register(basicAuth);
server.auth.strategy("simple", "basic", { validate });
await server.register(inert);
await server.register({
plugin: pino,
options: {
prettyPrint: true,
logEvents: ["onPostStart", "response"]
}
});
server.route({
method: "GET",
path: "/",
options: {
auth: "simple"
},
handler: (request, h) => {
request.logger.info("Used handler: %s", request.path);
return "Index Page";
}
});
server.route({
method: "GET",
path: "/{component}",
handler: (request, h) => {
request.logger.info("Handled path: %s", request.path);
return `Used component name: ${encodeURIComponent(
request.params.component
)}`;
}
});
server.route({
method: "GET",
path: "/static",
handler: (request, h) => {
request.logger.info("handled path: %s", request.path);
return h.file("./static.html");
}
});
await server.start();
console.log(`Listening at ${server.info.uri}.`);
})();
Hi!
I would like to customize the error response. I need some control over the output: headers, body. I assume I could set up an event and manipulate the response in it, but this isn't a good solution IMO.
Thanks for your work,
K.
How do you log out a previously authenticated user?
This is a very puzzling one for me.
If I have two strategies defined on a route (hapi-auth-basic and hapi-auth-jwt2) Chrome 58/Mac will never put up a basic auth prompt, and only seems to try for JWT authentication. The exact same set up, in Safari, leads to the prompt, as expected.
I've tested side-by-side in regular and incognito mode in both browsers.
I've also tested with a dummy auth scheme, that simply returns reply(boom.unauthorized(null, 'Token'))
— same thing.
I recently matched my error handling with this plugin thinking this was a good example, turns out this plugin does not allow chaining strategies or am I doing something wrong?
🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨
To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.
Since we didn’t receive a CI status on the greenkeeper/initial
branch, it’s possible that you don’t have CI set up yet.
We recommend using:
If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/
.
Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.
Could you pass the request
object as a parameter of the validateFunc
function? For testing purposes it's very useful, dependency injection, stubs and those things.
sorry to disturb you, its my first issue on github and I`m a newly developer focus on node.js.
I try to run the example code of hapi-auth-basic, but failed to build bcrypt, so I tried to use hapi-auth-basic withou bcrypt, and here is my code:
"use strict"
// const Bcrypt = require('bcrypt');
const Hapi = require('hapi');
const Basic = require('hapi-auth-basic');
const server = new Hapi.Server();
server.connection({port: 3006});
const users= {
john: {
username: 'zhang',
password: 'secret', //secret
name: 'zhang',
id: '123456'
}
};
const validate = function (request, username, password, callback) {
const user = users[username];
if(!user) {
return callback(null, false);
}
// Bcrypt.compare(password, user.password, (err, isValid)=> {
// callback(err, isValid, {id: user.id, name: user.name});
// });
console.log("in process!\n");
console.log(user.password+" | "+password);
// if (password === user.password) {
// let err=null;
// let isValid=true;
// callback(err, isValid, {id: user.id, name: user.name});
// }
callback(null, true, {id: user.id, name: user.name});
};
server.register(Basic, (err) => {
if (err) {
throw err;
}
server.auth.strategy('simple', 'basic', {validateFunc: validate});
server.route({
method: 'GET',
path: '/',
config: {
auth: 'simple',
handler: function (request, reply) {
reply('hello, '+ request.auth.credentials.name);
}
}
});
server.start((err) => {
if(err) {
throw err;
}
console.log('server running at: '+ server.info.uri);
});
});
Unfortunately it didnt work and nothing printed in console, the auth window just appear again after I click 'yes', I don
t know how to solve this problem, I'll appreciate it very much if you could help me!
Its my careless that I forgot to change the key of user information, thank you very much @mtharrison .
Could you please provide a way to test endpoints protected with this authentication strategy?
Hapi's server.inject
method has authentication object in its options, how can one provide credentials to this object?
I've tried this so far:
server.inject({
method: 'GET',
url: '/users',
auth: {
username: 'admin',
password: 'password'
}
}, function (response) {
// assertions...
done();
});
After define first 3 lines below, basic auth affects every routes, including route w/o basic auth option (static route). Is there a way to exclude certain routes from getting basic auth check? thx
// -------------
await server.register(require('hapi-auth-basic'));
server.auth.strategy('simple', 'basic', { validate });
server.auth.default('simple');
// api route
server.route({
method: 'GET',
path: '/api/v1',
options: {
auth: 'simple'
},
handler: async function (request, h) {
return 'GET successful!';
}
});
// static route (no basic auth option defined here)
server.route({
method: 'GET',
path: '/{param*}',
handler: {
directory: {
path: 'public',
redirectToSlash: true,
index: true
}
}
});
$ curl -H "Content-Type: application/json" -X GET http://
{"statusCode":401,"error":"Unauthorized","message":"Missing authentication"}
{
method: 'GET',
path: '/api/profile',
config: {
handler: function(req, rep) {
return rep({
code: 'ok',
body: {}
}),
auth: 'simple'
}
}
When using the hapi-router, I always get the error when I set authentication ({auth: 'simple'}) on the route.
code:
`import blipp from 'blipp'
import Bcrypt from 'bcrypt'
import Hapi from 'hapi'
import hapi_router from 'hapi-router'
import hapi_auth_basic from 'hapi-auth-basic'
const users = {
admin: {
username: 'admin',
password: 'XXXXXXXXXX' //pass hash password
}
}
const validate = (request, username, password, cb) => {
let user = users[username]
if (!user) {
return cb(null, false)
}
Bcrypt.compare(password, user.password, (err, isValid) => {
cb(err, isValid, user)
});
}
let server = new Hapi.Server({ debug: { request: ['error'] } })
server.log(['error', 'database', 'read'])
server.connection({port: process.env.PORT || 8080, host: process.env.HOST || '0.0.0.0'})
server.register([
{
register: blipp,
options: {}
},
{
register: hapi_router,
options: {
routes: 'src/routes/**/Route.js' // if enable in config {auth: 'simple'} generate error:
/ ../node_modules/hoek/lib/index.js:736
throw new Error(msgs.join(' ') || 'Unknown error');
^
Error: Unknown authentication strategy simple in /api/v1/testeroute
*/
}
},
{
register: hapi_auth_basic
}
], err => {
if (err) {
throw err
}
server.auth.strategy('simple','basic', {validateFunc: validate})
server.route({ method: 'GET', path: '/',
config: { auth: 'simple', // is OK
handler: (request, reply) => {
console.log(request.auth)
reply('ok')
}
}
})
server.start( err=> {
if (err) {
throw err
}
console.log('Server rurnning at: ', server.info.uri)
console.log(server.registrations)
})
})
`
I'm using Express rather than hapi. The de facto auth library there is passport, which hasn't been maintained in years.
Then I found this. Am I able to use it without hapi?
Hello,
can you update hoek to supported version, please. Version 5.x.x is not supported any more.
Thank you
Jan Opravil
I'm trying to use the hapi-auth-basic plugin to perform basic authentication for an account, and on success, return a JWT token that will be generated and used by hapi-auth-jwt. I can get the authentication working just fine via hapi-auth-basic, I just need to generate the key, and to do that, I need the username. I looked through the request object (first param in the route handler), but I didnt see it, where can I grab the credentials?
Thanks
There is an error in the example code on the website (http://hapijs.com/tutorials/auth).
When the validate function is declared, three parameters are passed (username, password, callback) but it needs four (request, username, password, callback).
Could you add the request object inside the validation function, in order to access to feature like request.server.methods or all the server staff.
Like you say in #26 a work around is to fork,
but to be honest is not cool to increase entropy but having yet another project that do the same things.
Could you reconsider this Feature Request, because it could be useful for at least 2 peoples and your project could be considered as an official plugin in hapijs github repo?
Apology me be advance, to reopen a previous issue,
Best Regards
I have not been able to make the try
mode work at all.
The hapi docs say:
It may also be set to a string with the name of the strategy to use, or an object with mode, strategies, and payload parameters.
Yet, the module complains that only a string can be set.
Can you give a simple code example of using try
mode (on a route)?
The split method chops the password into parts if the password contains a colon, then the total credentialsParts.length > 2. The HTTP Basic Authentication spec does not restrict passwords this way.
var credentialsParts = new Buffer(parts[1], 'base64').toString().split(':');
if (credentialsParts.length !== 2) {
return reply(Boom.badRequest('Bad header internal syntax', 'Basic'));
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.