Hello, everyone.
I'm implementing upload funcionality in my application, but since (as far as I know it) feathers services don't give us neither the request object nor the response object I'm using a middleware and a custom route to be able to receive the file contents and store it in an external file storage platform.
I'm worried about the security of my application, so I need a way to check if the user is authenticated and I also need to check his authorization to know the extents to which he is allowed to make file uploads in my system. In feathers services this is very easy to do, because the hook objcets already tell us the user who is making the request. But what about middlewares?
Is it possible to check these user's authentication and authorization properties inside middlewares? Another possible solution would be if it's possible for me to capture the incoming request object, because this way I would be able to process the file being uploaded and persist it in the persistent storage of my choice.
There is a middleware that that grabs the token in https://github.com/feathersjs/feathers-authentication/blob/master/src/middleware/express.js#L27 but getting the user happens at the service level in the populateUser hook.
I know this came up before, @ekryski what do you think about doing the user population (setting req.user and req.feathers.user) in the Express and Socket middleware already? That way it will be available at the lower level. I was also thinking that the auth plugin could smartly cache the user information (get it once and then listen to patched, updated and removed on the user service).
In my opinion it would be great to be able to [1]have access to the req and res objects inside feathers services and/or [2]to have access to the user object inside middlewares. I don't know how you work with these things internally, though, so it may be that from the software design and architecture stand point this may not be viable or even possible. Anyway, I'm looking forward for these improvements, because they would give us many possibilities as feathers developers.
In the meanwhile, @daffl , is there a workaround I can use to manually identify who is the user making the request to my middleware? Any low level solution/workaround would be welcome. So I could use the workaround and latter apply the official feathersjs solution which may be implemented in response to this issue.
Hey, I gave it a try.
Looking at the code of this file https://github.com/feathersjs/feathers-authentication/blob/master/src/hooks/verify-token.js I've created the following function inside the middleware I need to protect with authentication:
var jwt = require('jsonwebtoken');
// The app object must be passed to your middleware somehow. See as I do it below.
function checkIfUserIsAuthenticated() {
var options = app.get('auth');
if (options.algorithm) {
options.algorithms = [options.algorithm];
delete options.algorithm;
}
// The req passed to a custom route of our middleware.
jwt.verify(req.headers.authorization, options.token.secret, options, function (error, payload) {
if (error) {
// Invalid or expired token.
console.error("user not authenticated")
return false;
}
else {
// User is logged on in the application.
console.log("User is authenticated");
console.log(payload);
return true;
}
});
Then, when getting a reference to the middleware, I just pass the app object to it as a parameter:
var middleware = require("path/to/your/middleware.js")(app);
If someone can validate this funcion please, so that we can be sure that it really works in all cases, I think it's already enough and I'm going to close the issue. But if it needs some adjustment, please help us with how we can make this funcion reusable inside middlewares. Thanks very much.
I would also like to see a solution bundled with feathers and don't know the best workaround.
Just keep in mind that usually you need 2 service hooks for authentication. You are trying to replicate authHooks.verifyToken(), but you might also need authHooks.populateUser() to make sure that the user saved in the token matches the one in the database.
@juodumas I checked it with a manual test. Got my authentication token at /auth/local, then passed the token to a route processed by my middleware. Then, inside that function above, I logged the payload, which printed in screen the user id. Finally I opened the database and searched for a user with this id, and it was actually the user with which I made the login/authentication.
Is it possible that the payload ID may be different from the ID of the user who made the login and got the token which is passed to authenticate feathers requests?
No. But it's possible that the user has been deleted from the database.
Better yet, we can refactor this to be a middleware itself, passing it as a filter to routes we would like to check for user authentication:
var checkUserAuthenticityMiddleware = function (req, res, next) {
// ... all the code above
}
You can see how we are doing it in the upcoming 0.8.0 version of feathers-authentication right here.
Also somewhat related to the discussion here: https://github.com/feathersjs/feathers-authentication/issues/258.
I'm going to close in favour of tracking discussion in the authentication repo.
Anything new here?
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue with a link to this issue for related bugs.
Most helpful comment
There is a middleware that that grabs the token in https://github.com/feathersjs/feathers-authentication/blob/master/src/middleware/express.js#L27 but getting the user happens at the service level in the
populateUserhook.I know this came up before, @ekryski what do you think about doing the user population (setting
req.userandreq.feathers.user) in the Express and Socket middleware already? That way it will be available at the lower level. I was also thinking that the auth plugin could smartly cache the user information (getit once and then listen topatched,updatedandremovedon the user service).