I've got an issue when trying to protect my loopback endpoints with the oauth2 component.
I use a custom user model and a custom application model.
Here's are my oauth2 options
var options = {
dataSource: app.dataSources.db, // Data source for oAuth2 metadata persistence
userModel: 'LAccount',
applicationModel: 'LOAuthClientApp',
resourceServer: true,
authorizationServer: true,
//useAccessTokenModel: true,
authorizePath: '/oauth/authorize',
tokenPath: '/oauth/token',
supportedGrantTypes: [
'clientCredentials',
'refreshToken',
'resourceOwnerPasswordCredentials'
]
};
var oauth2 = require('loopback-component-oauth2').oAuth2Provider(
app, // The app instance
options // The options
);
I'm trying to protect some of my api endpoints
app.use([ '/api/mymodel/whoami', '/coordinator_noscope'], oauth2.authenticate({session: false}));
router.get('/coordinator_noscope', function(req, res) {
console.log(req.accessToken);
res.json({ 'result': 'done' });
});
Here my "MyModel" route
MyModel.remoteMethod('whoami', {
accepts: {arg: "options", type: "object", http: "optionsFromRequest"},
returns: { arg: 'object', type: 'object', root: true },
http: {path: '/whoami', verb: 'get'}
});
MyModel.whoami = function(options, callback) {
console.log(options.accessToken);
callback(null, new Success('done'));
};
When I'm getting an access token with a client (with the /oauth/authorize), the /coordinator_noscope route works, but the /api/mymodel/whoami get me a 401 (AUTHORIZATION_REQUIRED) error ..
I don't have any acls configured on "MyModel" model.
I don't understand what is the auth difference between the router.get route and the loopback api routes
Related
I'm currently creating an auth system using Mongo as database, Node with express as backend, and Nuxt as frontend.
I've found this authentication module https://auth.nuxtjs.org/ followed the doc, and the youtube video. I'm using Local scheme for Jwt system.
My issue is the login doesn't work successfully.
I think it doesn't work because of my user route on the backend, but not sure about that.
I also read that their is a user.autoFetch but dont know how to use it.
nuxt.config.js
modules: [
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
'#nuxtjs/auth'
],
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
baseURL: 'http://localhost:3000/'
},
auth: {
strategies: {
local: {
endpoints: {
login: { url: 'api/auth/login', method: 'post', propertyName: 'token' },
user: { url: 'api/auth/user', method: 'get', propertyName: 'data.attributes' },
logout: false
},
tokenType: ''
}
}
},
login.vue
async submit() {
try {
let response = await this.$auth.loginWith('local', { data: this.login })
console.log(response)
} catch (err) {
console.log(err)
}
// await this.$router.push('/dashboard');
},
The response send me back a 200 status, a token, and the userId (which is in my db) but the $auth still send me loggedIn at false and I can't get information like $auth.user.email.
I tried to change the auth endpoints in the nuxt.config.js
Changed tokenType: '' to tokentype: 'Bearer'
Changed the #nuxtjs/auth version to the same as the video tutorial. (4.8.4)
I added a controller for the route user :
route :
router.get('/user', userCtrl.getUser);
controller:
exports.getUser = (req, res, next) => {
User.findOne({ _id: req.params.id })
.then(thing => res.status(200).json(thing))
.catch(error => res.status(404).json({ error }));
}
Do not hesitate to ask me more details, on the configuration, other parts of the code, or anything like that.
Thank you in advance for any kind of help !
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) ?
i have an app with Webserver implemented using Hapi JS, and whenever i opened an application with browser's tab i am able to see the cookies are injected in Request header.
but if i load my app inside third application through Iframe. there is missing cookies from the header . can you please some body help here .
Hapi JS code
server.auth.strategy('session', 'cookie', {
password: 'longpassword-should-be-32-characters-for-pulse',
cookie: 'my-app-sid',
redirectTo: '/',
ttl: 86400000,
isSecure: false,
validateFunc: isAuth
});
and my API call where the cookies missing from req header
getBookDetails = () => {
return {
auth: {
strategy: 'session'
},
handler: {
proxy: {
mapUri: (request, callback) => {
let url = 'https://mydemoapp.com'
let tokenHeaders = { token: request.auth.credentials.token,
assetid: request.headers['assetid'],
asseturl:request.headers['asseturl'],
deviceid: deviceid,
appversion: request.headers['appversion'],
'user-agent': request.headers['user-agent'],
'accept-language': request.headers['accept-language']
};
url = url + '/book/' + request.params.bookId;
callback(null, url, tokenHeaders);
},
onResponse: (err, res, request, reply) => {
wreck.read(res, { json: true, gzip: true }, (err, payload) => {
reply(payload);
});
}
}
}
}
}
i am suspecting that since my app is loaded inside the iframe of third party app. and while requesting the webserver URL mentioned above getBookDetails() it could'nt read the cookies by Iframe from the Parent app (Third party app).
can some one help please
I think the first place should be checked in your browser.
I'm trying to create a custom method for a User based model in Loopback.
The method calls login and then retrieves user's role and adds it into response so the login request holds token and role info at once.
My problem is that once I have the token information I don't know how to call Role & RoleMapping methods from the one I'm creating...
How can I add those models to the current scope?
How can I access rootScope from this method?
This is how I've made it:
module.exports = function(TiUser) {
TiUser.auth = function(credentials, include, fn) {
var self = this;
self.login(credentials, include, function(err, token) {
var role = // Here I would retrieve Role related info
authInfo = {
token: token,
role: role
};
fn(err, authInfo);
});
};
TiUser.remoteMethod(
'auth',
{
description: 'Login method with Role data information embedded in return',
accepts: [
{arg: 'credentials', type: 'object', required: true, http: {source: 'body'}},
{arg: 'include', type: ['string'], http: {source: 'query' },
description: 'Related objects to include in the response. ' +
'See the description of return value for more details.'}
],
returns: {
arg: 'accessToken', type: 'object', root: true,
description: 'User Model'
},
http: {verb: 'post'}
}
);
};
You can get back to app from your models like so TiUser.app
So the way that I call other Model methods is:
TiUser.app.models.Roles.find etc.
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).