ConservationMetrics / guardianconnector-views

A Nuxt.js tool that reads data from a SQL database and renders it on different views (map, gallery, alerts dashboard)
MIT License
3 stars 0 forks source link

Implement authentication via JWT using a Login component or path parameter #7

Closed rudokemper closed 9 months ago

rudokemper commented 9 months ago

This PR adds authentication, a Login component, JWTs, and a path parameter to bypass logging in.

Specifically:

rudokemper commented 9 months ago

@IamJeffG to discuss Monday.

IamJeffG commented 9 months ago

to bypass logging in, I have added an option to pass a secret key query parameter via the browser path. This is handled by a /login/ GET endpoint that will generate a JWT if the query parameter matches the SECRET_JWT_KEY env var, and reload the page to be redirect to /map upon success.

This is NOT a safe method insofar as it can leave the secret key exposed

Is this JWT value hard-coded in the Superset dashboard?

Yeah, eventually we will need to figure out how to have the Superset dash pass some JWT that it somehow retrieves (or computes) just-in-time:

  1. Views generates a private key specific to the Superset deployment, which we probably store as an env variable for Superset. Even users of Superset should not have access to this private key.
  2. Superset uses that private key to generate a JWT for its next access (or next 5 minutes of access) to Views. This one is the mystery to me: somehow the Dashboard needs to run arbitrary code? either server-side Python or client-side JavaScript (but the latter case adds a concern about how to make sure the private key can't be leaked).
  3. Superset passes this JWT in the iframe, as you are doing via URL query parameter.

And Views will need to check the JWT expiry date (maybe it already does this) before trusting it. One potential threat avenue of how it is today is that someone has the never-expiring JWT, but we no longer trust that person. We have no way to cut off their access.

rudokemper commented 9 months ago

Setting the JWT to expire is actually a one-line change, and Views auth does check this, so that shouldn't be a problem.

But yes, the token being matched to generate a JWT is hard coded in the iframe URL so that remains a security risk, albeit that one has to actually log into Superset to access it so there is at least that much of a protection layer. But agreed we should still find a better way to have Superset handle this.

I'm imagining some kind of mechanism that generates a new token on a regular interval and passes that to both Superset and Views (and on the future, other apps), which are then adapted to know what to do with it. Not sure whether that's a Superset plugin, or something exterior to both apps.

EDIT: As I wrote that on my phone, I realize I didn't see your proposed workflow as it looked like quoted text on my device! It makes a lot of sense to me, but indeed some pieces to still figure out, also in relation to how other apps might handle this.

I still need to do more research on auth0 too. There could be some scaffolding for a solution there.

rudokemper commented 9 months ago

Interestingly, Superset itself has an embedded SDK which can be used to embed Superset dashboards via iframe using the host application's authentication.

https://medium.com/@huamichaelchen/end-to-end-example-of-setting-up-superset-embedded-dashboard-f72fc985559

https://medium.com/@khushbu.adav/embedding-superset-dashboards-in-your-react-application-7f282e3dbd88

rudokemper commented 9 months ago

Merging this to stack on successive PR(s) that will aim to build in auth0 support as a solution for our embedding ambitions.