how to turn a hapi auth plugin to be optional - node.js

I'd like to use the hapi jwt token auth plugin https://github.com/ryanfitz/hapi-auth-jwt but make a route with optional authentication. How can I prevent the route from returning a 401 and instead continue executing with a null request.auth.credentials.
I'd like all the other routes that are using it to keep the same implementation of returning a 401 on non authenticated requests.
server.register(require('hapi-auth-jwt'), function (error) {
server.auth.strategy('token', 'jwt', {
key: privateKey,
validateFunc: validate
});
//make this one allow anonymous while also reading logged in credentials
server.route({
method: 'GET',
path: '/',
config: {
auth: 'token'
}
});
server.route({
method: 'GET',
path: '/mystuff',
config: {
auth: 'token'
}
});
});
server.start();

You can set it to optional in route configuration:
server.route({
method: 'GET',
path: '/',
config: {
auth: {
strategy: 'token',
mode: 'optional'
}
}
});
Mode can be true, false, required, optional, or try. See the authentication tutorial for more details.

Besides the optional route's auth configuration, you can also use try.
server.route({
method: 'GET',
path: '/',
config: {
auth: {
strategy: 'token',
mode: 'try'
}
}
})
The difference between those two
optional: no authentication credentials needed, but if provided they need to be valid
try: if the user provides invalid authentication credentials they still get accepted and users will proceed to the route handler

Related

nuxt/auth middleware: ['auth'] when open

I have a problem setting permissions when open a project
i have use nuxt\auth for authorization and it works great, gets the token, exits, etc.
I have the following settings in nuxt.config.js
export default {
loading: '~/components/loading.vue',
router: {
extendRoutes(routes) {
routes.push({
path: '/',
component: '~/pages/dashboard/sales/index.vue'
});
},
middleware: ['auth']
},
auth: {
redirect: {
login: '/auth/login',
home: '/',
logout: '/auth/login',
callback: '/'
},
strategies: {
local: {
//...... some token settings
endpoints: {
login: { url: 'http://api.local:5002/api/v2/Account/login', method: 'post' },
refresh: { url: 'http://api.local:5002/api/v2/Account/refreshToken', method: 'post' },
logout: false,
user: { url: 'http://api.local:5002/api/v2/User/settings', method: 'get' }
}
}
}
},
modules: [
'bootstrap-vue/nuxt',
'nuxt-i18n',
'#nuxtjs/axios',
'#nuxtjs/auth-next'
],
// .... order settings
}
according to the settings, all my pages require authorization, routing works like this, when I follow some link, if I am not authorized, I am redirected to the authorization page
however, if I open the project in a browser, I go to the page without authorization
http://local:3000/
and according to settings - page (" \ ") is http://local:3000/pages/dashboard/sales/index.vue
which should be closed to guests.
I think this is happening because nuxt's auth isn't doing the transition yet, so the auth check isn't triggered.
i try add middleware: 'auth' in sales/index.vue but that not help, page open for guest when start
export default {
name: 'Sales',
head() {
return {
title: `Sales Dashboard`
};
},
middleware: 'auth',
data() {
return {
title: 'Welcome !'
}
}
};
I also tried to add a plugin where there will be an authorization check, but the redirect does not work
export default function ({ $auth, redirect }) {
if (!$auth.loggedIn) {
console.log('test');
return redirect('/auth/login');
}
}
I see the text in the console, however the redirect is not happening
how to correctly, when broweser open site -> check whether an authorized user has entered the site, or a guest, and if the guest then immediately redirect to the authorization page (to http://local:3000/auth/login) ?

Nuxt update session cookie with each request

I am building a Nuxt app that uses fastify for the backend API. I am using httpOnly session-cookies for authentication. So far everything works fine but the issue i have is that Nuxt just has a hardcoded cookie timeout of 30 minutes. I have updated this to 24hrs but what i really want to do is have Nuxt refresh the timeout after each request.
I see in my database that the fastify session cookie get updated after each request and the session expiration gets updated after ANY user API request. So, this looks like the backend is functioning correctly but the frontend need to update the auth._token_expiration.local value.
You can see in the config that i manually set the maxAge to 24hrs, cant i have the frontend update the auth._token_expiration.local value automatically when making successful API requests? my token is stored as sessionId
nuxt.config.js
auth: {
redirect: false,
strategies: {
local: {
token: {
required: false,
type: false,
maxAge: 86400 // seconds - 1 day
},
user: { property: false },
endpoints: {
login: {
url: '/user/login',
method: 'post',
withCredentials: true
},
logout: {
url: '/user/logout',
method: 'post',
withCredentials: true
},
user: {
url: '/user/profile',
method: 'get',
withCredentials: true
}
}
},
localStorage: false,
cookie: true
}
},
So i discovered that the sessionId Expires data DOES get updated after each api request, so that is good. To make this function i also had to set the nuxt.config token maxAge to 0. This solved my issues.

Oauth2 request token from AWS Lambda

I am testing my AWS Lambda nodejs locally via SAM, and I need to make an Oauth2 request to a third party API which I also have running locally.
I am trying to do this:
request({
url: 'http://localhost:4040/auth/token',
method: 'POST',
auth: {
user: 'xxx',
pass: 'xxx'
},
form: {
'grant_type': 'client_credentials'
}
}, function(err, res) {
var json = JSON.parse(res.body);
console.log("Access Token:", json.access_token);
});
However, I am getting this info when invoking my function:
ERROR Uncaught Exception {"errorType":"TypeError","errorMessage":"Cannot read property 'body' of undefined","stack":["TypeError: Cannot read property 'body' of undefined","
I am not sure what I am doing wrong here? Any pointers?

How to authenticate at MongoDB Atlas API using digest authentication?

I want to get a list of projects in MongoDB using its API "https://cloud.mongodb.com/api/atlas/v1.0/groups" but every time I get error as "401 You are not authorized for this resource".
According to the docs digest authentication is used.
Seems like I am passing the Private_key and Public_key in the wrong way.
Below is my request object
{
url: 'https://cloud.mongodb.com/api/atlas/v1.0/groups',
method: 'GET',
headers: {
'Accept': 'application/json',
},
auth: {
user: 'Public_Key',
pass: 'Private_key'
}
}
Can anyone please help me with this.
What you are missing is the key "sendImmediately". You need to send it in your auth object as follows :
request({
method: 'GET',
auth: {
"user": Public_Key,
"pass": Private_key,
"sendImmediately": false
},
url: 'https://cloud.mongodb.com/api/atlas/v1.0?pretty=true'
})

hapi-auth-cookie not setting cookie

For my node app im using the bell and hapi-auth-cookie plugins to use the Yahoo api. With the current code, I am able to authenticate with Yahoo and then am redirected to the homepage. However, request.auth seems to be empty once I get to the homepage. From what I can tell, I'm doing everything exactly as the example, yet I have no authentication once I get back to the homepage. Any help is appreciated! Here's what I've got:
var Path = require('path');
var Hapi = require('hapi');
var cookieSession = require('cookie-session');
var serverOptions = {
views: {
engines: {
html: require('handlebars')
},
path: Path.join(__dirname, './app/www/public/pages'),
layoutPath: Path.join(__dirname, './app/www/public/pages')
}
};
var server = new Hapi.Server(8003, serverOptions);
server.pack.register([
require('bell'),
require('hapi-auth-cookie')
], function(err) {
if (err) {
throw err;
}
server.auth.strategy('yahoo', 'bell', {
provider: 'yahoo',
password: 'cookie_encryption_password',
clientId:'2kj3kj2',
clientSecret: '3kj2k3jl',
isSecure: false // Terrible idea but required if not using HTTPS
});
server.auth.strategy('session', 'cookie', {
password: 'secret',
cookie: 'sid-example',
redirectTo: '/login',
isSecure: false
});
server.route({
method: ['GET', 'POST'], // Must handle both GET and POST
path: '/login', // The callback endpoint registered with the provider
config: {
auth: 'yahoo',
handler: function (request, reply) {
var creds = request.auth.credentials;
request.auth.session.clear();
request.auth.session.set(creds);
return reply.redirect('/');
}
}
});
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply.view('index', { title: 'hello world' });
}
});
server.start();
});
To expound upon and extend Eran's answer:
If you want to have access to the authentication/session data for a route that doesn't need authentication to view (such as a home page) it is possible but not very intuitive in my opinion. You have to set the auth scheme on the route but then change the mode to 'try' and also set a route specific hapi-auth-cookie parameter to prevent an unauthenticated user from being redirected to the login page as such:
server.route({
method: 'GET',
path: '/',
config: {
handler: homepage,
auth: {
mode: 'try',
strategy: 'session'
},
plugins: { 'hapi-auth-cookie': { redirectTo: false } }
}
});
mode: 'try' will allow a user to proceed to the route path even if not authenticated and redirectTo: false will stop an unauthenticated request for the route being redirected to the login page. This way, users can get to this route without authentication (typical for a home page) but once authenticated the cookie data set via hapi-auth-cookie is available for use.
You home page is missing authentication. You need to configure '/' to use your cookie auth scheme.
Even with things setup correctly, I've seen issues lately with Facebook and Twitter (so I could see Yahoo doing the same) depending on which version of Bell was used (4.0 has issues with Facebook for sure) and if the calls were from node_modules or not. As crazy as that sounds, these issues can be seen in recent versions of Clapper where hapi-bell-auth-cookie-plugin works fine using the exact same approach (but not as a node_module).

Resources