Skip to content

Support automatic server-side encryption of Dash props #262

Open

Description

@nicolaskruchten

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?

Activity

  1. valentijnnieman commented on Oct 10, 2018

    @valentijnnieman
    Contributor

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

  2. nicolaskruchten commented on Oct 15, 2018

    @nicolaskruchten
    ContributorAuthor

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

  3. supernyv commented on Apr 15, 2024

    @supernyv

    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

  4. gvwilson commented on Jun 3, 2024

    @gvwilson
    Contributor

    @AnnMarieW will dcc.Store do encryption these days?

  5. AnnMarieW commented on Jun 3, 2024

    @AnnMarieW
    Collaborator

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

  6. BSd3v commented on Jun 3, 2024

    @BSd3v
    Contributor

    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
  7. self-assigned this
    on Jun 26, 2024
  8. removed their assignment
    on Aug 2, 2024
  9. gvwilson commented on Aug 7, 2024

    @gvwilson
    Contributor

    cc @ndrezn what do you think?

  10. reopened this on Aug 7, 2024
  11. changed the title [-]dcc.Store and encrypted props[/-] [+]Support server-side encryption of Dash props[/+] on Aug 7, 2024
  12. changed the title [-]Support server-side encryption of Dash props[/-] [+]Support automatic server-side encryption of Dash props[/+] on Aug 7, 2024
  13. ndrezn commented on Aug 7, 2024

    @ndrezn
    Contributor

    @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)
  14. nicolaskruchten commented on Aug 7, 2024

    @nicolaskruchten
    ContributorAuthor

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

  15. nicolaskruchten commented on Aug 7, 2024

    @nicolaskruchten
    ContributorAuthor

    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.

  16. ndrezn commented on Aug 12, 2024

    @ndrezn
    Contributor

    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.

  17. BSd3v commented on Aug 12, 2024

    @BSd3v
    Contributor

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3backlogfeaturesomething new

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions