Hapi.js is a small Node framework for developing back end web apps.
In this article, we’ll look at how to create back end apps with Hapi.js.
Cookie
We can add cookie authentication easily with a few lines of code.
For example, we can write:
const Bcrypt = require('bcrypt');
const Hapi = require('@hapi/hapi');
const users = [{
username: 'john',
password: '$2a$10$iqJSHD.BGr0E2IxQwYgJmeP3NvhPrXAeLSaGCj6IR/XU5QtjVu5Tm',
name: 'John Doe',
id: '1'
}];
const start = async () => {
const server = Hapi.server({
port: 4000,
host: '0.0.0.0'
});
await server.register(require('@hapi/cookie'));
server.auth.strategy('session', 'cookie', {
cookie: {
name: 'sid-example',
password: '!wsYhFA*C2U6nz=Bu^%A@^F#SF3&kSR6',
isSecure: false
},
redirectTo: '/login',
validateFunc: async (request, session) => {
const account = await users.find(
(user) => (user.id === session.id)
);
if (!account) {
return {
valid: false
};
}
return {
valid: true,
credentials: account
};
}
});
server.auth.default('session');
server.route([{
method: 'GET',
path: '/',
handler (request, h) {
return 'Welcome to the restricted home page!';
}
},
{
method: 'GET',
path: '/login',
handler (request, h) {
return `<html>
<head>
<title>Login page</title>
</head>
<body>
<h3>Please Log In</h3>
<form method="post" action="/login">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit" value="Login"></form>
</body>
</html>`;
},
options: {
auth: false
}
},
{
method: 'POST',
path: '/login',
handler: async (request, h) => {
const {
username,
password
} = request.payload;
const account = users.find(
(user) => user.username === username
);
if (!account || !(await Bcrypt.compare(password, account.password))) {
return h.view('/login');
}
request.cookieAuth.set({
id: account.id
});
return h.redirect('/');
},
options: {
auth: {
mode: 'try'
}
}
}
]);
await server.start();
console.log('server running at: ' + server.info.uri);
};
start();
We have the users
array with the user data.
password
is the hash of the password. It’s 'secret'
in plain text.
The start
function has the code for our app.
The Hapi.server
function creates the server.
We register the @hapi/cookie
module with:
await server.register(require('@hapi/cookie'));
Then we add the user authentication fucntion with:
server.auth.strategy('session', 'cookie', {
cookie: {
name: 'sid-example',
password: '!wsYhFA*C2U6nz=Bu^%A@^F#SF3&kSR6',
isSecure: false
},
redirectTo: '/login',
validateFunc: async (request, session) => {
const account = await users.find(
(user) => (user.id === session.id)
);
if (!account) {
return {
valid: false
};
}
return {
valid: true,
credentials: account
};
}
});
We call the server.auth.strategy
method to add authentication.
'session'
is the name. 'cookie'
is the strategy.
The object has the validation logic. cookie
sets the cookie secret.
redirect
adds the redirect when auth fails.
validateFunc
has the logic to validate the credentials.
We check if the user has a valid cookie with:
const account = await users.find(
(user) => (user.id === session.id)
);
We return an object with the valid
property to indicate whether the credentials are valid.
credentials
has the credentials for the account.
Then we call server.route
to add the routes. The GET /
route is the restricted route.
GET /login
displays the login form.
We set options.auth
to false
to let us access the page without authentication.
The POST /login
route lets us search for the user with the given username and password.
We validate the password with Bcrypt.compare
.
And then we call h.redirect
to the route we want to access if the username and password are valid.
Otherwise, we redirect to the login route.
Conclusion
We can create an app with a login page and cookie authentication easily with Hapi.