Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support automatic server-side encryption of Dash props #262

Open
nicolaskruchten opened this issue May 30, 2018 · 12 comments
Open

Support automatic server-side encryption of Dash props #262

nicolaskruchten opened this issue May 30, 2018 · 12 comments
Labels
feature something new P3 backlog

Comments

@nicolaskruchten
Copy link
Contributor

nicolaskruchten commented May 30, 2018

Enable e.g. dcc.Store to encrypt/decrypt its data-* props on the server, and possibly expand to other components.

#254 was a first cut at implementing this in dash.py and some design discussion is available there. It seems like the way forward here is to make the base component class extensible with server-side transform/inverse_transform extension points.

@chriddyp is there an existing issue that captures other needs/thoughts around the base component extension idea?

@valentijnnieman
Copy link
Contributor

@nicolaskruchten Can this be closed now that dash-core-components has a new Store component?

@nicolaskruchten
Copy link
Contributor Author

No, because the data stored there is still unencrypted :)

@supernyv
Copy link

Hi guys,

Nice to see this discussion. This is exactly what I am looking for, a dcc.Store that has the capability to encrypt and decrypt its data, and it will probably help a lot of developers

@gvwilson
Copy link
Contributor

gvwilson commented Jun 3, 2024

@AnnMarieW will dcc.Store do encryption these days?

@AnnMarieW
Copy link
Collaborator

No, this feature is still not available, but I could see how it could be useful.

@BSd3v
Copy link
Contributor

BSd3v commented Jun 3, 2024

Gonna pop in here, encryption is a good thought, but what has to do the decrypting?

  • if the clientside is doing the decryption, then you could capture the process of decryption by viewing the code
  • if the server, then there is the encrypted version that would be in the store and then the other side that would take the data, process and send it back for whatever it is used for.
  • if we are doing it server side, then what is the point of even sending the data to the client in its raw form? Wouldnt something like serverSide output work from dash-extensions?

A couple of notes:

  • if a dcc.Store is stored in memory, you cant view it unless you access the React props, but getting to this nested Store would be a bit of a chore, although possible.
  • it is possible for a developer to encrypt / decrypt in their own flows on the server side as well while using a dcc.Store, which means that the developer would be responsible for maintaining the secureness of their keys for the process

@gvwilson gvwilson self-assigned this Jun 26, 2024
@gvwilson gvwilson removed their assignment Aug 2, 2024
@gvwilson
Copy link
Contributor

gvwilson commented Aug 7, 2024

cc @ndrezn what do you think?

@ndrezn ndrezn closed this as completed Aug 7, 2024
@ndrezn ndrezn reopened this Aug 7, 2024
@ndrezn ndrezn changed the title dcc.Store and encrypted props Support server-side encryption of Dash props Aug 7, 2024
@ndrezn ndrezn changed the title Support server-side encryption of Dash props Support automatic server-side encryption of Dash props Aug 7, 2024
@ndrezn
Copy link
Member

ndrezn commented Aug 7, 2024

@nicolaskruchten could you explain your transform/inverse_transform idea a bit more...? Maybe there's a ticket somewhere I'm missing.


Though to be honest I'm not totally sure whether automatic encryption of dcc.Store props is super useful or significantly simplified by having it be automatic.

The use case I can imagine is if you want to store your complete dataset in dcc.Store but only show the end user a subset of that data (and therefore hide the non-shown data). But at this point a database backing the app is probably safer and easier to work with. But if there are other use cases I'm all ears.

Here's a small example showing something similar to @nicolaskruchten's PR implementation but in this case using callbacks + dcc.Store:

Code snippet
from dash import dcc, html, Input, Output, State, callback, Dash, no_update
from cryptography.fernet import Fernet
import base64

# Generate a key for encryption and decryption
key = Fernet.generate_key()
cipher_suite = Fernet(key)

app = Dash(__name__)

app.layout = html.Div(
    [
        dcc.Input(
            id="input-data",
            type="text",
            placeholder="Enter data to encrypt",
            style={"marginBottom": "10px"},
        ),
        html.Button("Submit", id="submit-button", n_clicks=0),
        dcc.Store(id="encrypted-store"),
        html.Div(id="output"),
    ]
)


@callback(
    Output("encrypted-store", "data"),
    Input("submit-button", "n_clicks"),
    State("input-data", "value"),
)
def encrypt_data(n_clicks, value):
    if n_clicks > 0 and value:
        encrypted_data = cipher_suite.encrypt(value.encode())
        # Encode to base64 to store in dcc.Store
        encoded_data = base64.b64encode(encrypted_data).decode()
        return encoded_data
    return no_update


@callback(Output("output", "children"), Input("encrypted-store", "data"))
def decrypt_data(encoded_data):
    if encoded_data:
        # Decode from base64 and decrypt
        encrypted_data = base64.b64decode(encoded_data)
        decrypted_data = cipher_suite.decrypt(encrypted_data).decode()
        return f"Encrypted data: {encoded_data}\n Decrypted data: {decrypted_data}"
    return "No data stored"


if __name__ == "__main__":
    app.run_server(debug=True)

@nicolaskruchten
Copy link
Contributor Author

the transform/inverse thing was in a comment from Chris in my initial PR #254

@nicolaskruchten
Copy link
Contributor Author

not totally sure whether automatic encryption of dcc.Store props is super useful or significantly simplified by having it be automatic.

The idea here was to provide a first-class/recommended way of doing things that doesn't require users to copy-paste boilerplate around.

@ndrezn
Copy link
Member

ndrezn commented Aug 12, 2024

For my own reference, @chriddyp puts the use case well in: https://community.plotly.com/t/writing-secure-dash-apps-community-thread/54619

  1. dcc.Store Data is accessible, even if it’s not visible

All of the data that is returned in a callback can be accessed by the current user of the app, even if that data isn’t necessarily visible.

So, be careful not to store secret or sensitive data in dcc.Store or other callbacks if you don’t intend all users to be able to access the data.

For example, if you have a dataframe that has several unused but sensitive columns (e.g. data about a particular client), then remove those columns before saving it in a dcc.Store. Even if your app doesn’t use those columns, the data is still accessible in the browser session.

@BSd3v
Copy link
Contributor

BSd3v commented Aug 12, 2024

What if Plotly added support for Server Side stores, much like dash-extensions. Then you wouldnt have to worry about keeping things private.

Also, another thing to point out for a dcc.Store and encrypting on the server, you wouldnt be able to utilize the data on the browser via a clientside callback. So, the point of even having the data go to the client doesnt make much sense.

This of course would be different if for some reason you wanted to send the data via an api call by the client...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature something new P3 backlog
Development

No branches or pull requests

7 participants