Persist property to following middlewares in Express - javascript

My express app has some auth middleware which determines the current user from the session ID. I want to "persist" the user through to the following middlewares. I've tried attaching the user object to the res object, but this doesn't work (presumably because JS doesn't pass function arguments by reference).
I realise that something like Passport handles this specific scenario for you, but I'm interested in solving the general problem of persisting a value through to all subsequent middlewares.
The fact that I can't find any references to this on SO or elsewhere leads me to believe I'm trying to do something Fundamentally Wrong™ so please feel free to call me out. I'd love to hear alternative design approaches.

You can use something called locals
res.locals
for example in your case you can set
res.locals.id = 'something'
this value will persist throughout the request in all middlewares, until the response is sent.

Related

Is it bad practice to put additional claims for authorization

I want to implement authorization layer on my microservices project. I have 3 microservices customer-service, workspace-service and cloud-service. So if a customer want to create a cloud instance he will create on behalf of a workspace which means that the cloud instance will belong to the workspace instead of him and also he may invite other customer to the workspace, and have access to the cloud instance. The data structure may looks like this.
// workspace
{
"workspaceId": "ws-123",
"customers": ["customer-123", "customer-456"]
}
// cloud-instance
{
"cloudId": "cloud-123",
"workspaceId: "ws-123"
}
I want to implement authorization logic that check if a user has access to a particular cloud instance. In order to do that I need to have workspaceId somewhere else in my authentication object. One thing that I can think of is that to put workspaceId in the jwt claims so my jwt may looks like this.
header.{ ..., workspaceId: ["ws-123"] }.signature
but the drawback of this solution is that the workspaceId claim won't be updated until the token has been refresh.
another solution that is to implement a service that query data from workspace-service and use it to validate.
const hasAccess = (customerId, workspaceId_on_cloud_instance) => {
let actual_workspaceId_that_he_has = workspace_service_exposed_api.findWorkspaceByCustomerId(customerId)
return actual_workspaceId_that_he_has == workspaceId_on_cloud_instance
}
but this approach would heavily rely on workspace-service if workspace-service is down then the other service can not handle a request at all since it doesn't have access to workspaceId.
So IMHO I would rather go for the 1st option since I use oauth2.0 and token will be refresh every 30s, but is it bad practice to do that? I wonder if there's better solution.
Having 3 microservices you cannot implement functionality with assumption that one service is down. I have feeling that access token lifespan is also defined based on this restriction - to have up to date data in the token. As I correctly understand, in worst case there is also ~30 sec. delay related to workspaceId update in token payload.
Token claim will change only when you invite or remove person from workspace so this service must work anyway. I would use 2nd solution with longer token lifespan to not generate it so often.
Another solution is to generate new token every time when workspace is changed - you can treat adding/removing to workspace as a business logic that invalidates token, but probably in this case communication to workspace service is also required.
If you are afraid that microservice will be down or you will have problem with communication, maybe you should focus more on app infrastructure or choose a new solution based on monolith application.
And back to question from title - adding any custom claim to token payload is standard approach.

NodeJS - Store value globally from request header

I need to store the value from a request header and use it in several parts of my app. Which is the best way to accomplish this?
Here is an example on how I get the value (app.js)
app.get('*', (req, res) => {
global.exampleHeader = req.headers['example-header'];
});
And then use this value whenever I want in all my app.
For the example I use the global object which solves my issue, but I'm not sure if it's the best way of doing something like this. Any other suggestions or improvement?
Thanks in advance!
res.locals
An object that contains response local variables scoped to the request, and therefore available only to the view(s) rendered during that request / response cycle (if any). Otherwise, this property is identical to app.locals.
This property is useful for exposing request-level information such as the request path name, authenticated user, user settings, and so on.
source: http://expressjs.com/en/4x/api.html#res.locals

With Sails.js how can I make /users/me a route that works with associations?

I have a main model Accounts, then I have a few Has Many models like Notifications and Friends
In my main.js
I'd like to be able to do things like:
socket.get('/users/me/notifications');
instead of like:
socket.get('/users/ + g_userAccountId + '/notifications');
^^ That works for right now, but it is set asynchronously so if any code loads before g_userAccountId is set it will try to use undefined instead which is bad.. Very bad..
I understand policies and all that I'm just wondering how I can make this work with the REST blueprints and what not. If I'm not clear please let me know
Is there a way to do this without setting findOne methods in each controller? Like to automatically fill in /me/ with 1
The easiest way I can imagine doing this without setting findOne methods in each controller would be to create a policy that matches the /users/me/notifications route, redirecting it to the current session's user id. You could potentially use something like the following, and update the /config/policy file.
if (session.authenticated) {
return res.redirect('/users/' + req.session.user.id + '/notifications');
}
If you wanted to do something to handle anytime the /users/me route is hit, you could modify this policy, tweak the req.url and redirect to the new one that uses the user ID, and apply it to all relevant routes in policy config file, or setup a custom middleware to handle the problem the same way.

How to make per user base logging with hapi js

I am using winston logging framework and logging on basis of log level, but now i am facing difficulties in tracking down bugs. So we decided to make logging on per user basis, and this is where i ran into problem.
What i want to acheive?
log file for every user will be generated on every hour. (We can skip every hour constraint in this thread) and every user has unique identifier 'uid'.
What i have?
I have followed architecture as used here 'https://github.com/agendor/sample-hapi-rest-api'. Some additional lib modules exist too.
Currently i am using winston library (but i can afford to replace this if needed).
Brief introduction of flow
Currently, i have access to request object in handler function only, but i want to log events in DAO, library functions too ( on per user basis). 'Uid' is available to me in handler function in request object as i put uid in request in authentication middleware.
My solution (which is not elegant)
pass request object ( or only uid) to every function and log (using winston) event. Custom transport will determine where (in which file, on basis of uid) to put the log.
Certainly, this is not elegant way as every function must have uid parameter in order to log event, which seems bad.
What i want from you?
A better, elegant approach which is scalable too.
Related post: https://github.com/hapijs/discuss/issues/51
Try taking a look at Continuation-Local Storage:
https://github.com/othiym23/node-continuation-local-storage
Heres a good article on implementing it within express:
https://datahero.com/blog/2014/05/22/node-js-preserving-data-across-async-callbacks/

Multiple Users Issues Node.js

I am working on a budgeting application and everything works great... or at least i thought it did. Test it out at http://budgeter.pattmorter.webfactional.com/! Now you can login and add stuff and edit your profile and it works great, the only problem is that if someone else logs in after you, and you refresh your page, it'll set your session to the person that logged in after you.
I'm not really sure why it happened but it has to do with my main app.js node. I think my problem is that when the user logs in i have a currentUser variable in app.js which is passed too all of the different routing but I don't think that is correct because it is causing these errors. Anyone suggest a better way of doing this?
My app.js file is here -- https://github.com/M-Porter/bearded-wookie/blob/master/production/app.js
Basically, I don't understand how to do what i want without a variable in the app.js space. Any push in the right direction would be great.
Node.js in Action (great book) suggests using built in session middleware for things like this. It uses signed cookies so you will also need the cookieParser middleware. It should look something like:
app.use(express.cookieParser('your secret'));
app.use(express.session());
Then you have access to req.session to keep track of your current user.
Edit 1: I just looked at your code more closely. Looks like you were already on track with cookieParser and session middleware. Just try storing your current user in session. It also sounds like passport can retrieve the username on subsequent request. Check out http://passportjs.org/guide/configure/

Categories

Resources