How to forward user sessions in Next.js + Graphql decoupled architecture? - node.js

I'm building a next.js project and while I usually would just use the "Custom Express Server" method to implement my graphql API (using apollo-server-express), I thought that it might be a good idea if I decoupled the next.js project from the graphql API so that each of the servers are hosted on different machines.
But usually I would implement any session-related logic in the graphql API, using something like graphql-passport; I figured that's good practice because if I ever choose to add another frontend (maybe a mobile app or something) they can share the same session logic. But given that I'm server side rendering content with next.js, how do I forward the user's session info to the graphql server? Because the next.js server shouldn't have to redo authentication, right?
Let me know if there are any flaws in the architecture too, I'm kind of new to this.

Using the Next server to run the GraphQL service is certainly not a good idea, so yes, do separate the two.
Letting the Next server SSR-render pages with user specific content using the users session is probably not a good idea either, unless you have some specific use case that requires the served HTML pages to have the user specific data in them already. The reasons for this are:
SSR rendering will require lots of server side computations since all pages always will have to be rerendered.
NextJS is moving away (since v9.3) from the getInitialPros() way of doing things towards using getStaticProps() to generate a page that is common for all users and which can load its session dependent stuff straight from the GraphQL API once it is displayed on the client device.
This approach will generally have higher performance and scale much better.
Should you really want to go the "SSR with user session data" route you start in the getServerSideProps(context) method, where context.req is the actual request which will have all your session data in it (cookies or headers).
This session data you can then extract from the req and pass on to the GraphQL server requests that require authentication.

Related

Hide secret keys in network payload

I have a Vue Storefront which, out of the box, exists of a Nuxt.js front-end and a Express.js back-end.
In this project I created a custom Server Middleware (which is the Express.js part) that has an Axios call in it. My entire Vue Storefront project is hosted and deployed on a server where I also store the secret keys for the Axios call as eviorment variables. Whenever I request data via the Axios call on the deployed website, I can still see my secret keys in payload in the browser console.
Can these keys be hidden? Since the call is done in the VSF Server Middleware (which is a Express.js server under the hood) and my secret keys are defined on the server too... Not in a .ENV file.
The official docs also state the following about the server middleware:
Securely store credentials on the server without exposing them to
theend-users of your application,
I also have Server Side Rendering enabled, if this has any effect on this.
As explained in my previous answer here, you cannot really hide anything on a client side app.
The fact that you do have ssr: true and target: 'server' enables the usage of a serverMiddleware. Nuxt is also an Express server, so you could technically still totally hide stuff, the configuration of this one is detailed here. Please pay attention to the whole answer (especially the gotcha at the end).
The TDLR is as mentioned above: you'll need some kind of proxy to hide that, so you could do that:
directly with Nuxt2 but it's kinda tricky and hard to work with overall, on top of paying a whole Node.js server and a possible mistake exposing those tokens at some point
get another Node.js server to properly separate the concern and use that one as a proxy, it can be pretty light (no need for a beefy configuration), not as expensive price-wise
a serverless function could be the best idea here because it's light, cheap and you don't need to manage anything (send your query there, it will proxy the request with the secret token) but it can be a bit annoying regarding cold starts

Server handles sessions and restful Api in same server?

Im building a chat that uses a api rest full, but i found a problem storage jwt in client side (cookies and his problems), so i opted to use sessions(it's a better option in security terms), that adds state to my app.
I should create a separate server that handles the sessions and also have my rest api?, and apart another server that implements some functionality such as a push server (which I plan to implement). Because I really don't like the idea of ​​having everything on one server, and if so, what should I take into account? (have more than an rest api server and other with his funcionality).
I'm a developer and i think so this require architecture knowledge, and i have no many idea about servers. If you can give me some idea about the topic to get better on it will be great, and what's the better option in this case.
Thanks, give a nice day

Securely decouple backend and frontend (node.js server)

I've been looking at node.js, REST APIs and WebSockets lately to further my knowledge about backend and frontend web development. Trying to go with best practices I see REST API comes up all the time. Now my problem which I don't seem to understand how to properly solve.
Say for example I'd like to have client / server decoupled and for this I implement a REST API in the backend so that my frontend will access and get data to render. Specific (imaginary) example: lets say I want to build a rental service website. Now I would like to have an endpoint for my frontend to access information about certain products, let's say the number of bikes that have been rented so far. I'd like to be able to show this on my frontend (through the help of the REST API) but I wouldn't like for other people who call this REST API to be able to get the data (because espionage is a serious business and I'd like to keep the evil ones away, yes they can webcrawl but bla bla). So in essence I'd like for the localhost machine to be able to access (part of) the REST API but not anyone else. Things get complicated because I'd also like people to be able to create a user on my website so then I'd like to have other endpoints which can then be accessed without restriction because I'm thinking, what if at some point I'd like to have a mobile app that is integrated with the service. Then it will be unfeasible to restrict all requests to localhost.
How would you architect a secure server / client as this one? Or in your opinion is it not that big of a deal to have the REST API exposed to others (the evil ones)?
The above goes for WebSockets as well. I know REST APIs are all nice and neat but I think the future lies in near-realtime connections and so I'm likewise as interested in WebSockets (through higher level modules of course, Socket.io, SockJS etc.).
There are many solutions to secure your API out there and many of them are opensource. Which one you'll use really depends your detailed needs.
But to get you started I will mention a solution that is very accepted and supported by a large community:
Have a look at JSON Web Token, which are for example explained in this Article.
Basically your client requests an authentication token from the server and then stores it locally to reuse it for every request to your API.
The Server on the other hand may protect your API as needed. That means you may also have a public API that does not expect a token in the HTTP Header.
Tokens may also expire. That is handy if you, for example, will allow a new user for registering on your site for a limited time.
Here is another article that explains things.
Now on to the websocket part of your question. YES, you definetly want to protect your server side sockets as well. So look out for a library that supports authentication. Again, I think there are a number of opensource libraries out there.
To mention one: Primus.
Primus is an abstraction layer for many socket libraries underneath and lets you quickly change the socket provider. But it also has an authentication hook that you can implement.
And guess what.. you can use it to check for a JSON Web Token!
Hope this gets you started.

SPA security using Backbone.js, Require.js and Laravel

I'm currently searching the best way for developing my next webapplication. I'm thinking about using Backbone.js and build a single page application. But I really can't imagine how to secure my app since nearly everything is done on client side. Of course I just could prevent the users from accessing my RESTful Api so they would not have access to my data. But all the view/model/collection/template js files are still accessible.
Or is there a known way to serve the js files with php (laravel), which would allow me to only serve the files I need for the respective user.
I just couldn't find a solution by searching the Web. But I just don't think that I am the lonely person who needs a clean and secure authentication method including different user rights.
Thank you in advance!
Your backend application will fetch data from a backend (= API), and probably send back some changes.
This code can't have "security holes / leaks" as long as your backend is secured.
If you are afraid of people stealing your code, you can always minify the JS (check grunt.js and almond.js for this)
To secure your backend you can make use of Laravel's auth class, and the auth filter as mentioned before.
Besides normal auth, you could implement roles, that you can assign to specific users, giving them more or less access to certain resources in your backend.
Here's the method I would try :
Separate the application in two parts.
One part - login via regular Laravel Auth on a separate page, and then when the user is logged in serve the single page app in a different view.
Wouldn't this work?
Web Services are no different than any other web application you build. At the end of the day you are exposing functionality to the client (which is also the attacker). It doesn't matter what the client is implemented in, if you expose dangerous functionality you will be hacked.
Have a session state, keep track of the user id and make sure that the user is only accessing resources they have been allowed to access.
I do not think that what JS/template files are exposed really matters. Essentially, you should only be allowing data interaction to authenticated users. Think of this as two separate applications.
The front-end application logs in, and a cookie is stored (or some other persistence is used).
The back-end application then uses the persistent authentication to validate every single user request for data, and every user action.
This way you don't have to worry about the security, the client can only fetch the data that the server allows it to, and, likewise, it can only interact with the data insofar as the server allows it. You shouldn't be relying on the client side for security anyway, even logged in, otherwise some malicious user could, conceivably, save all your frontend code and use it against you without authentication.

Single page applications, http or websockets, is connect/express done for?

This is a question involving single page web apps and my question is in bold.
WARNING:
I'm hardly an expert on this subject and please correct me if I'm wrong in part of my understanding of how I think HTTP and WebSockets work.
My understanding of how HTTP restful APIs work is that they are stateless. We use tools like connect.session() to interject some type of state into our apps at a higher level. Since every single request is new, we need a way to re-identify ourself to the server, so we create a unique token that gets sent back and forth.
Connect's session middleware solves this for us in a pretty cool way. Drop it into your middleware stack and you have awesome-sauce sessions attached to each request for your entire application. Sprinkle in some handshaking and you can pass that session info to socket.io fairly easily, even more awesome. Use a RedisStore to hold the info to decouple it from your connect/express app and it's even more awesome. We're talking double rainbow awesome here.
So right now you could in theory have a single page application that doesn't depend on connect/sessions because you don't need more than 1 session (initial handshake) when it comes to dealing with websockets. socket.io already gives you easy access to this sessionId, problem solved.
Instead of this authentication work flow:
Get the email and password from a post request.
Query your DB of choice by email to get their password hash.
Compare the hashes.
Redirect to "OK!" or "NOPE!".
If OK, store the session info and let connect.session() handle the rest for the most part.
It now becomes:
Listen for a login event.
Get the email and password from the event callback.
Query your DB of choice by email and get their password hash.
Compare the hashes.
Emit an "OK!" or "NOPE!" event.
If OK, do some stuff I'm not going to think of right now but the same effect should be possible?
What else do we benefit from by using connect? Here's a list of what I commonly use:
logger for dev mode
favicon
bodyparser
static server
passport (an authentication library that depends on connect/express, similar to what everyauth offers)
The code that loads the initial single page app would handle setting up a static server and favicon. Something like passport might be more tricky to implement but certainly not impossible. Everything else that I listed doesn't matter, you could easily implement your own debug logger for websockets.
Right now is there really anything stopping us from having a single http based index.html file that encapsulates a websocket connection and doesn't depend on connect at all? Would socket.io really be able to make that type of application architecture work without setting up your own HTTP restful API if you wanted a single page app while offering cross brower support through its auto-magical fallbacks?
The only real downside at this point is caching results on the client right? Couldn't you incorporate local storage for that? I think creating indexable/crawlable content pages for search engines wouldn't be THAT big of a deal -- you would basically create a tool that creates static html files from your persistent database right?
Check out Derby and SocketStream.
I think what you're asking for is if it is plausible (using socket.io) to create a website that is a single static page with dynamically changing content.
The answer is "yes", it can work. Several node.js web frameworks already do this although I don't know of any that use socket.io.

Resources