Coder Social home page Coder Social logo

Comments (43)

pld avatar pld commented on June 2, 2024 2

Sure, but that's unrelated to this discussion. The point is I need to hear a solid argument for how the backend increases security, which I have not heard, before it's justified to add it for security purposes.

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024 2

How does this proposal prevent sensitive information from being exposed?

For me, it boils down to this one question: are cookies set by client side applications less secure than cookies set by server side applications? (I'll go into detail on why we are considering just cookies below.)

I would argue that the answer here is yes. Mainly because the number of things that you can do to secure cookies on the client side are limited. For instance, one truly big deal is that client side applications cannot issue "httponly" cookies.

Why cookies?

Cookies are the standard place to store sensitive values in the browser currently.

In our case, if we have an access token that we need to store:

  • Client-side applications: we will store the actual token in a cookie
  • Server-side applications: we will likely store the token somewhere on the server side and then set a cookie that proves to the server that you have legit access to the token

In both cases, cookie security is paramount.

What is at stake?

If the access token is compromised in any way, you have full and unlimited access to whichever server issued the token (which is likely OpenSRP or Onadata or Superset or Canopy tables via Superset for us). This can be really very bad and we want to secure against it as much as possible.

Other ways in which have a server-side applications helps in security

  1. Layering - we can more easily enhance security via layering i.e. securing not just the cookie but other things. For example we have more leeway to try and make the session id (which is stored in a cookie) more cryptographically secure.
  2. The web server itself serves as a middleman that further mitigates risk, by:
    • The client can only access what the server side application allows it to access
    • The server side application can be configured to try and detect and then invalidate any intrusions
  3. Most popular web servers are battle tested and have well thought out and well implemented measures to prevent most if not all of the popular vulnerabilities that web applications are exposed to. This would not be the case if we decide to kind of roll our own mechanism of securing cookies in our client side applications

Are there any good examples of this proposal in the wild we can look at? (aside from kaznet)

I cannot find a definite, documented example of this kind of setup. However, the idea is not new and is pretty well known, in my opinion. For me, it is actually quite similar to what Google refers to as a "reverse-proxy front end" in their Google Infrastructure Security Design Overview. From this document it seems that if I am logged in to Gmail, for example, and I make a request to another Google server - let's say contacts - the request from the client/browser will not go directly to the Google contacts service, but will go to the Gmail service which will then get what it needs from the contacts service and then give this back to the client/browser. I stand to be corrected on this, however.

Sources and further reading:

from reveal-frontend.

pld avatar pld commented on June 2, 2024 2

tl;dr I see trade-offs, not a clear answer. I think the question is when do we need a frontend proxy server. I've scheduled a meeting Monday 8am/3pm to review this

This is great information. I think the question is a bit more complex, but regardless my main concern with this line of argumentation is it that if an attacker has enough access to the browser to retrieve API credentials, they'll have enough access to use the authentication to the intermediary to access the API (by sending requests to the intermediary as the client).

I disagree with the what is at stake section, you'll only have as much information as was given to that token, and in a well-designed API you'd have no more access than the user of the website already has (my understanding is that's how Ona Data works).

I do agree that if we have flaws in the frontend that create XSS attack opportunities, HTTPOnly will mitigate against those, but those could theoretically be fixed through a more secure frontend. But in practice I certainly see this as a Pro for an intermediary.

I agree with everything in the "other ways..." section in theory but in practice it depends on the use case. Layering's pro is as you stated, but the con is that you've now created a whole new attack surface, with just an API an attacker would have to breach the API, but now with a backend an attacker can try to use the client to go through the backend, they can try to attack the backend directly. Minimizing attack surface is a general rule, a larger attack surface creates more opportunities for vulnerabilities. On the other hand, if you have an insecure back-end, especially if it's one you can not control, moving that behind a firewall and using another web service as a proxy/facade in a "DMZ" before you can access the insecure backend is very reasonable (like when you have a thin web service that proxies access to a database).

The increased attack surface is an argument for why this approach either is less secure than front-end only, or introduces trade-offs that make it no more secure.

Stepping back though (and I believe you've said this yourself Kelvin) we should use this to decide our organization wide policy for storing credentials. I think Zebra has shown we can do this reasonably well through the fact that it exposes temporary tokens on the client side and has been vulnerability tested by a number of (I think at least 3 now?) researchers and that part of the architecture has not been the problem (to my understanding). If we decide that temp tokens being client side is not OK, this means big changes to every Gisida site and smaller changes to Zebra, I don't know if this is workable for Gisida.

from reveal-frontend.

ivermac avatar ivermac commented on June 2, 2024 1

I'd like to think for any of our dashboards that uses oauth access token, we need a backend to persist the token and keep it safe. We can borrow zebra's architecture. Have a server-side that sets cookie used for authentication. The server could have a key-value store like redis whose key would be the cookie and value could be a json like object containing both the access and refresh tokens. The server side would then make requests to API using the access-token on behalf of the client side and when the API returns a response, the server-side should send that response to the client-side.
The times when the API will be returning a 401 response, the server-side should have functionality to renew the access token using the refresh token.

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024 1

I've been reading about this over the last few days. And I still feel uncomfortable about how we have agreed to solve this. As discussed above we can make any credentials/secrets temporary to limit our exposure, but I am convinced we should try and find a better more secure solution. I don't think that being insecure for ten hours or an hour or 30 minutes or any amount of time is something that we should accept. I hope that you agree with me on this? That we should not learn to live with a known vulnerability in our apps? And that instead we should strive for something better?

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024 1

And in my case, for Reveal, my plan is to move away from having a fully client-side only application. To have Reveal be a hybrid web app with a tiny backend that powers the frontend. Once/when/if this is done then any secrets that need to be stored can be safely managed by that backend.

An example of where we did this before is Kaznet. The Kaznet front-end is a React application that is deployed as a view of the Kaznet backed which is a Django application. Django is completely in charge of storing any secrets in a way that is as secure as any other Django web app out there. In this case, the Kaznet frontend does not even need to care about authentication because it is only exposed in a Django view that a user has already authenticated to.

I want to do the same thing for the Reveal web. Not with Django, of course, but with something like express.js.

I hope that you see where I am coming from, and that you agree with me? :)

from reveal-frontend.

pld avatar pld commented on June 2, 2024 1

The session and CSRF tokens are exposed to the browser and could be used by an attacker to communicate with the API.

How is this more secure?

from reveal-frontend.

cKellyDesign avatar cKellyDesign commented on June 2, 2024 1

Sorry, just getting caught up to speed:

@moshthepitt

  1. What's a CSRF token and how is it different? Can you share a link or two for reference?
  2. Are there any good examples of this proposal in the wild we can look at? (aside from kaznet)
  3. How does this proposal prevent sensitive information from being exposed?

from reveal-frontend.

pld avatar pld commented on June 2, 2024 1

I can tackle (1.) this is cross-site request forgery token, it's a token generated server-side unique for each page sent to the client and it's embedded in rendered forms. The client is expected to send this token with any POST requests.

https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern

from reveal-frontend.

cKellyDesign avatar cKellyDesign commented on June 2, 2024 1

Yeah totally, right now I think the only credentials Gisida saves to the client is the onadata oAuth token (which is used for both onadata API requests and superset connector authentication).

Future integrations of internal (OpenSRP/MRS, RapidPro, etc) and external (HDX, DHIS2, etc) services will need to store credentials in accordance with our policy. AND, internal integrations should also keep in mind SSO.

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024 1

Thanks everyone. Closing this issue. The next steps will be handled here: #156

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

The solution to this problem might be useful for other client-side only web apps that we build

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

I am currently leaning towards persisting the redux store (only the one reducer that contains the access token) on the server in a DB such as RethinkDB or Redis.

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

This one faced the same issue: rt2zz/redux-persist#46

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

from reveal-frontend.

ukanga avatar ukanga commented on June 2, 2024

OpenSRP is the backend to Reveal, right? Why not use OpenSRP?

In general, the last we talked about this it seemed that api.ona.io could be the person that provides the necessary cookies for authenticated access to resources. In the case of Reveal, I believe this would be OpenSRP and in that event, it is a matter of ensuring every related service is behind the same domain even if they use subdomains.

I do think all our dashboards should have a backend, however how minimal that is. And since they are all build using javascript, NodeJS makes the most sense to me, Express.js being the most stable web application framework.

What's the value proposition for RethinkDB?

from reveal-frontend.

mlberg avatar mlberg commented on June 2, 2024

We don't have a proper backend for OpenSRP yet just OpenMRS. This is something mPower has started for OpenSRP that we are going to build off of

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

@ukanga

OpenSRP is the backend to Reveal, right? Why not use OpenSRP?

Right now the oAuth access token that we are referring to is actually from OpenSRP. Unless the auth mechanism changes we cannot easily/cleanly use OpenSRP to store this access token.

In general, the last we talked about this it seemed that api.ona.io could be the person that provides the necessary cookies for authenticated access to resources. In the case of Reveal, I believe this would be OpenSRP and in that event, it is a matter of ensuring every related service is behind the same domain even if they use subdomains.

I'll investigate this with @githengi and report my findings back here. Although one spanner in the works is that since in the Reveal web app we are using Superset via the SupersetConnector, we need to use oAuth to be able to authenticate with Superset.

I do think all our dashboards should have a backend, however how minimal that is. And since they are all build using javascript, NodeJS makes the most sense to me, Express.js being the most stable web application framework.
What's the value proposition for RethinkDB?

RethinkDB would represent the database or data store that the express.js backend uses. Does not have to be RethinkDB - might be Redis/postgres/whatever else. RethinkDB, however, looks really interesting with the solution I had in mind (I will detail this below in a different comment).

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

We don't have a proper backend for OpenSRP yet just OpenMRS. This is something mPower has started for OpenSRP that we are going to build off of

@mberg do you have more details on what mPower have?

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

So since we are using Redux to store global state, and we have this oAuth access token in Redux already, I was thinking of a solution along the lines of being able to persist the Redux store or parts of it via a tiny express.js based backend. Possibly using a tool such as Redux Persist to manage the syncing/refreshing etc of the Redux store.

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

Also we should keep in mind that this is not a Reveal only problem. Any one of our client side web apps that needs to store secrets such as access tokens should not do it in the browser (with cookies, local storage etc).

from reveal-frontend.

pld avatar pld commented on June 2, 2024

What's the problem with having the frontend fetch this token from OpenSRP server when we need it?

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

The problem is that every time you refresh the browser you need to log in again because the token is not persisted.

https://web.reveal-stage.smartregister.org/

from reveal-frontend.

pld avatar pld commented on June 2, 2024

The token is not persisted in OpenSRP?

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

No the token is not persisted in the web app which is currently not deployed in the same place as OpenSRP.

from reveal-frontend.

pld avatar pld commented on June 2, 2024

I understand it's not in the web app, but here it sounds like you're saying the token is available from the OpenSRP service, which is what I was asking about fetching from

from reveal-frontend.

ukanga avatar ukanga commented on June 2, 2024

The problem is about maintaining a cookie session that is secure about being logged in and how to authorize with the backend and request for a new token when the current one expires without going through the authorization process on every page reload.

from reveal-frontend.

cKellyDesign avatar cKellyDesign commented on June 2, 2024

Linking the convo from a Slack thread to this ticket for posterity: https://onaio.slack.com/archives/CBSU8L2SC/p1560914226123600

from reveal-frontend.

pld avatar pld commented on June 2, 2024

Is that issue? It's not clear, I thought the issue was about how to store this temporary token on the client? And my recommendation is it's fine to store temporary token on the client in a persistent way which will mean no need reauthorize on reload.

BUT in will mean needing to reauthorize after that token expires. To prevent reauthorization on expiration, we may (probably will) need an intermediary backend. I.e. client sees temp token is expired, makes request to backend for a new temp token, backend stores a refresh token and uses that with the originator of OpenSRP to a request a new temp token, gives that temp token back to the client, this is all opaque to the user.

from reveal-frontend.

ukanga avatar ukanga commented on June 2, 2024

from reveal-frontend.

pld avatar pld commented on June 2, 2024

from reveal-frontend.

cKellyDesign avatar cKellyDesign commented on June 2, 2024

Yea that's exactly what I'm saying but I thought this was about how to store the access token.

Correct, also from the description it sounds like this ticket is more about storing the access token in a secure location/manner, which is in some way accessible to the react-redux webapp upon initialization.

Currently the webapp does not persist any tokens / information when refreshing (@moshthepitt @kahama94, correct me if i'm wrong!), thus forcing the user to log in through the complete oAuth flow every time the page refreshes.

from reveal-frontend.

cKellyDesign avatar cKellyDesign commented on June 2, 2024

How we persist this access token securely is what's being called to question in the Slack thread.

While, as Peter's points out, the temporary nature of the access token provides innate security, is there more we can do to make it more secure to prevent even an hour of breached security?

Also this: 👇

Also we should keep in mind that this is not a Reveal only problem. Any one of our client side web apps that needs to store secrets such as access tokens should not do it in the browser (with cookies, local storage etc).

from reveal-frontend.

pld avatar pld commented on June 2, 2024

I don't see a way around this, won't we always need to store credentials in the client? Whether it's a token to interact with a server or cookie to interact with a server it will not secure against a malicious client (e.g. a malicious user of a logged in session or malicious browser code). Our strategy has been to make them more secure by making them temporary.

How we persist this access token securely is what's being called to question in the Slack thread.

While, as Peter's points out, the temporary nature of the access token provides innate security, is there more we can do to make it more secure to prevent even an hour of breached security?

Also this: 👇

Also we should keep in mind that this is not a Reveal only problem. Any one of our client side web apps that needs to store secrets such as access tokens should not do it in the browser (with cookies, local storage etc).

from reveal-frontend.

cKellyDesign avatar cKellyDesign commented on June 2, 2024

Created ticket onaio/js-tools#69 for the gatekeeper module so we can address this DRY-ly.

from reveal-frontend.

pld avatar pld commented on June 2, 2024

I don't agree that this approach is more secure. I wasn't proposing we do something less secure, I was pointing out that the changes don't increase the security.

from reveal-frontend.

mlberg avatar mlberg commented on June 2, 2024

I don't think we should be against having a light backend. There is a lot of stuff we can probably do simply there and vs trying to manage everything in redux. We will want a DB we can store state too for stuff that may not fit within opensrp's core data model as an example.

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

@pld I'll come up with a more detailed proposal but roughly speaking:

  • The front end will not use API keys or tokens or other similar secrets directly
  • It will rely on sessions from the tiny backend to communicate with that backend
  • For communicating with third parties, the front end will make a CSRF secured call to the tiny backend, and that backend will make the actual API call to the third party and asynchronously put the results of that request in the Redux store for the front end to use

With this kind of arrangement the token/api key/secret is never exposed to the browser. Indeed it is a lot of extra work, but I think it is worth the effort.

from reveal-frontend.

moshthepitt avatar moshthepitt commented on June 2, 2024

On Hacker News today there is a really interesting discussion about "Why is Stack Overflow trying to start audio?".

It is kind of relevant to our discussion here because this essentially represents some kind of XSS exploit (probably not intentional) and that script can execute js on Stack Overflow itself. If Stack Overflow was using cookies or whatever that is accessible to javascript to store secrets then this script would have full access to those secrets.

It is another example of just how hard it is to properly and completely guard against XSS attacks; and - for me - yet another reason why we must not trust client side apps to keep our secrets.

from reveal-frontend.

cKellyDesign avatar cKellyDesign commented on June 2, 2024

The oAuth functionality in Gisida is a little adhoc and will very likely need to be refactored, and should be to utilize shared modules (eg GateKeeper) and to be aligned with our FE security strategy in general.

As far as impact on Gisida sites, only a few Gisida clients are actually utilizing oAuth, AND those that do have modular implementations wherein we inject functionality to save/access/remove the token from memory. Meaning that if we develop a shared client-side module to handle persisting authentication, the impact of implementing just that should be pretty light.

cc @KipSigei @kahama94

from reveal-frontend.

pld avatar pld commented on June 2, 2024

Cool, to clarify, the policy will be for any client side credentials not just OAuth.

Are you considering any credentials for remote servers we have client side?

from reveal-frontend.

cKellyDesign avatar cKellyDesign commented on June 2, 2024

Oh, Gisida also has API keys being exposed via config files.

from reveal-frontend.

pld avatar pld commented on June 2, 2024

After a lengthy discussion, we've agreed that (given we can build, maintain, and deploy it securely) using an intermediary will increase security against browser based attacks.

Fuller notes are here, see action items at the bottom, SRE will keep track of these action items. @moshthepitt I imagine we can close this issue now or via an issue w/the draft spec for the intermediary.

from reveal-frontend.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.