How can I share authentication information between all the server? - javascript

I'm developing a web service that have following structure:
Web Server: this is implemented with NextJS which do Server-Side Rendering and serve server-side rendered webpage data to Client.
API Server: and this one is implemented with NestJS. Clients will send graphql queries/mutations to this server.
Client: any clients can visit my web service and sign in (or sign up)
and I want to implement authentication feature for my web server, but problem is came up here. how can I share the auth data between Web Server, API Server, Client? if you signed in on your own browser, eventually a signing request will be sent to the API server.
but there's literally no way to know whether the client is signed in or not from Web Server. I mean, auth data (whether if user has signed in or not) will be stored only at API Server.
I had searched and spent a lot of time about this and I've got an answer that I have to use JWT Token but there were several ways to store it:
Storing it on clients' web storage: I don't think this can be an answer since the Web Server shouldn't able to get clients' web storage data. this means SSR (server-side rendering) wouldn't work well.
Storing it on Cookie: this is bad too. because we send a signing in request to the API Server that will be on different container (or server) and domain. we cannot set cookies from different domain with proper way. and if we get token and store it cookies directly from client side (setting cookie from javascript), It will be really huge security issue since attackers can take users' token with XSS.
Using Cookie but set from other subdomains with specifying Domain: we can specify domain for setting cookie. as far as I know, a response from api.example.com can set cookies for example.com with specifying Domain property of Set-Cookies value. read this
yeah, method 3 seems pretty neat to have but I absolutely don't know that setting cookies from another sub-domains will cause big security hole. my web service will process about users' money so security issues will come very critical.
someone I know advised me that I can use reverse proxy with paths not domain. I mean, if API Server was serving on api.example.com, we can serve it on example.com/api/* so now we can share the cookies between all the server and client. but we should store cookies on web storage too since cookies will be flagged as HttpOnly. this will cause increasing complexity of development.
In this case, which method will be the best answer for my case? are these methods I've mentioned above are really safe to do?

Related

React SPA with Express Backend API - Storing JWT in localstorage and limiting API access to SPA's web server IP only

I'm working on a project that involves an SPA web application built with React, connected to an API that runs Express.
I have read many articles and questions on stackoverflow. (Especially this link has a very detailed answer on it). However, there is a point that I couldn't understand. I searched the questions and couldn't find any answer that includes IP restriction on the backend API side.
I want to send JWT to authorized users that login from the SPA and store JWT in localstorage on the client side. The backend API will only be accessible from the SPA's IP address and will be closed to any other IPs. CORS will be configured to work only with the SPAs domain name as well.
So with this configuration in mind, is it still not safe to store JWTs in localstorage? As the API can only be still accessible by one IP, how can an attacker use the access Token after grabbing it with an XSS attack?
There are several attacks that can be applied in order to access the server:
Ip spoofing
SSRF
Ip validation vulnerabilities, think of the fact that you need to check ip, ip has many forms, ipv4, ipv6, hex, oct etc...
Firewall / Reverse proxy exploits
Best practices are meant to avoid mistakes, follow them.
BTW, I always recommend this article to make sense of JTW auth. (I've changed my app implementation after I've read it :) )

How to prevent end user from seeing network calls made through browser console

I need to send a particular header parameter in all ajax calls which is a very confidential information. I don't want from the end user to see any of the requests made in network tab of any browser. Is there any way to prevent it? or is it possible to make ajax calls directly from node server which doesn't go through browser?
Any call made on the client side cannot be hidden, as it's "client" side of the website. Even if you'd success to hide it in browser, any software could monitor it with tools such as network sniffers / monitors, WireShark for instance.
So the answer is no
When you go to a restaurent and order something, can the waiter subsequently make you forget your last instruction/order? The answer is NO, same as the answer to this question.
It all starts with client making a request to the server, hence client is the driving force of the whole interaction. Server just serves as per the instructions from client (and maliciously does some extra work on its own, say auditing, database update, cookie addition etc.).
Hence there is no way a 'server' can restrict client to see its own instructions.
Just simply don't send sensitive information directly via headers. Encrypt them via your client side code and add them within cookies or any other HTTP header(s).
Quoting from internet:
Client/server architecture is a producer/consumer computing
architecture where the server acts as the producer and the client as a
consumer. The server houses and provides high-end, computing-intensive
services to the client on demand. These services can include
application access, storage, file sharing, printer access and/or
direct access to the server’s raw computing power.
Client/server architecture works when the client computer sends a
resource or process request to the server over the network connection,
which is then processed and delivered to the client. A server computer
can manage several clients simultaneously, whereas one client can be
connected to several servers at a time, each providing a different set
of services. In its simplest form, the internet is also based on
client/server architecture where web servers serve many simultaneous
users with website data.
Never trust to client. Ever. Never ever. Doesn't matter what you do assume its been cracked. Hackers have all the tools and complete control of the client and all software running on it. Assume they've written their own network stack, their own TLS implementation, their own browser, their own operating system...
If you need to keep it secure, keep it on your servers. If you need to communicate 'privileged' information (assuming you remember that once you've sent it to a client they can access it) don't, tokenise it on your server and send them the token. And if you're generating tokens make sure they're very random and utterly opaque - don't encrypt anything in the token because you should assume they can crack that too, regardless how secure you think the library you are using is (assume it'll one day be cracked).
Never expose the confidential data on the client-side.
The best practice is to encrypt your confidential data on the server-side, send it to the client, and decrypt on the server end when the client sends you back.
If you don't want encryption or this confidential information is result of user actions itself then make a key-value pair in a database, where the key is something which can be exposed to the client (let's say username) and value is the confidential information. Hence now we have 1-1 mapping, so fetch this confidential information on server-side from database using the key we are getting from the frontend.
I hope this will help.
Good Luck!!

Where and how to store service credentials on pure front-end application

I wish to build a pure front-end app with JavaScript running on client-side, i.e. browser. My app is supposed to make requests to 3rd part services, which require some sort of authentication method.
Backend frameworks provide config files for this sort of thing, but since JS code is all interpreted on the client machine, the config files cannot be part of the bundle.
Is there any way of securely storing the service API keys, credentials and such within the client or do I need a backend solution for this also?
Search for most popular frameworks (Angular and React) for config files resulted only in storing environment-specific URLs. I'm starting to think that I've hit a dead-end and this simply can't be done.
Depends... You don't want the user to be able to sniff out any secrets you have to send to the third party, but in the case of an Implicit Grant with OAuth2, you can actually initiate and complete it in the browser.
You'll redirect to the 3rd party for login/authentication, then the user will be sent back to you with an access token good for a period of time.
That token is actually sent in a URL fragment, per the spec, so it's being sent to the browser and NOT your server. If you want to get the access token to a server, you'd need front-end code to parse the URL fragment and send its contents.
If the API will allow you to connect from the browser, you could keep everything in the browser and not need a backend server to handle credentials. But not every API will allow purely front-end authentication and API calls.
So, it depends...
Can you store service api creds in the client cache, or in cookies etc? Yes. Will it be secure to send them over the wire and store in the browser? No.
If keeping credentials secure is part of the requirements, I would do the work to authenticate on the backend or use a third party service that does this for you.

JavaScript REST Client and session management

I've been looking around for an answer to this question, but it looks like that nobody does this. Imagine you are designing a javascript REST client, and you want to create a login page. Surely, after the login you will be authenticated.
So the following requests to the REST API will depend on your current user id, which should be stored on the client side following the RESTful way.
My question is how to store this "session" information using Javascript. I've looked into cookies, but it seems to me too much plain text for one to trust. Also using cookies one could store there an session id that maps to the user information on the server, but this violates the Stateless concept from REST.
Which the best approach to solve this problem?
We are also building similar kind of architecture where RESTful API will be accessed by a javascript client.
We will authenticate client with client credentials and generate an authentication token and that will be sent to client. Client will store it in cookie or in local data store. Further requests to API from this client will be sent using HTTP authorization header and including that token in the header. We will authorize the request at API end for the given token and request will be served once it is authenticated.
Until n unless you don't access cookie information on server side I don't think this will violate stateless principle of REST as we are not maintaining any state of the client on server (we are but not binding it to any server). Regarding the authentication process using token, I don't think we are binding the server and client here, because we have multiple servers and using load balancer and still this request may be served by any server (similar to Google api).
Note: We are doing this using HTTPS protocol so we are sure that all this communication is secured.

Secure way to communicate OAuth token to javascript client

I am designing a multi-platform application at the moment (clients would include internally developed mobile apps, and an AJAX heavy javascript client initially) centred around a REST API. Since in the future the API may be open to third parties, I am looking at using OAuth 2.0 for authentication and authorization with the API.
I am trying to get my head around some of the security issues with this arrangement, particularly with regard to the javascript client. I don't want this client to behave like a third party client might, with a whole bunch of redirects and popups and stuff, which is what most OAuth documentation seems to focus on. Since it will be delivered from my own domain, I am thinking that the server side of the webapp can be the actual client, and store the client secrets and refresh tokens, while the javascript retrieves new auth tokens from the server as it needs them.
To put it in step by step form:
The user logs in using non-ajax html form, generating auth and refresh tokens which are stored server side. This sets a HTTP-only login session cookie.
The javascript client code is sent to the user's browser after login.
The javascript client makes a request to a resource that is part of its own application (not part of REST api) to retrieve the token. The session cookie ensures that the client is genuine, and the referer will also be checked. Auth token is returned.
The javascript client validates the token with the REST API.
The client can now use the token to make requests against the REST API until it expires.
If the auth token expires or the page is closed and re-opened, the javascript client can request a new token. The server side of the webapp takes care of refreshing the token and sends the new token, as long as the login session cookie is still valid.
Does this make sense, or would it leave massive holes in the system? In particular, is it insane to have a resource on the web that hands out authentication tokens based on a cookie being set?
Just make sure that any communication to browser is HTTPS, so that no one in the middle can steal your tokens. And set the "secure" flag on your auth cookies.
Most browser authorization schemes nowadays boil down to a session token that's passed in a cookie. The OAuth 2 scheme is a couple steps ahead because a) the tokens (can be) dumb tokens with no dangerous user info inside, and b) they expire.
(Just to put that comment in context: one time I popped open a session token from a site and discovered my home address and phone number was in there. Ack!)
I've seen code that does HMAC signing of requests inside the brower javascript, but it came with a huge disclaimer: don't use this in production. A signing scheme requires the client (javascript) to know a "secret" string, but the browser/javascript is so insecure that it amounts to handing your secret strings to the world.
But if you keep all your commuinication over HTTPS, then you're really just putting an OAuth twist on the familiar scheme of passing session tokens as cookies.

Categories