Deployment on AWS (with Authentication)

Hello everyone!

I’m not a regular poster around here but I have been working with Streamlit recently and absolutely love the tool. So much so that I used it in a recent project at AWS on model explainability. One of the requirements was a secure and robust dashboard deployment, and I separated this part into its own example that can be found on GitHub with CloudFormation templates included. I thought it might be useful for others looking to deploy their Streamlit applications with high uptime and access control.

AWS Architecture

Stepping through the architecture diagram above:

  • SageMaker is used to deploy the example pre-trained DistilGPT-2 text generation model
  • SageMaker is also used for Streamlit app development and testing (in Docker container)
  • Elastic Container Registry is used to store the Streamlit app Docker image
  • Elastic Container Service is used to run the Streamlit app Docker containers
  • Elastic Load Balancing is used to distribute traffic between Streamlit app Docker containers
  • Cognito is for user access management via username and password

User Access Management

All users of your dashboard will initially see a ‘Sign In’ screen, when trying to access the dashboard (unless you choose not to include this component in the CloudFormation template). You can create user accounts for the selected individuals who need to access the dashboard by providing their email addresses. They will receive a personalised email with their temporary credentials and a link to the dashboard. After first use, the user will be prompted to provide a new password. Cognito also supports other identity providers such as Google and Microsoft Active Directory, but that will need some tweaking of my CloudFormation template.

Resources

I’ve written everything up in more detail in a Medium blog post and there are lots of other details in the example notebooks. I’ve also provided a quick launch option for the CloudFormation template, so you can try the example out in your own AWS account in around 10 minutes.

Would be great to hear how others are deploying Streamlit on AWS (especially for the authentication part), and look forward to any feedback or questions.

18 Likes

Hey @thomelane, thanks for writing this up! This looks like a really detailed answer to a question we get pretty frequently.

1 Like

@thomelane: Wow. This is so, so valuable! Please let us know how we can support you! :slight_smile:

p.s. Welcome to the Streamlit community! :balloon:

2 Likes

Cheers for the warm welcome and glad it’s of use!

I think I’ll take you up on that offer of support :slight_smile: Just had a couple of questions really…

One area I couldn’t find much information about was security of the Streamlit itself (after getting past the secure Cognito authentication). What’s your roadmap looking like on this? Are there any production setting to disable stack traces on error, etc? My current approach was to manually catch exception and not pass upwards unless a debug flag was set.

Also while working on this project I was thinking how much of a game changer it would be if Streamlit could be deployed on AWS Lambda (serverless ‘functions’). Guessing it’s the long-running websocket connections that would get in the way here, but that could simplify the deployment architecture a lot and reduce costs quite a bit. Any thoughts here?

3 Likes

@thomelane thanks for this !

Would like to check using Amazon Cognito as a user authentication, is it possible to pass the user name into Streamlit such that I can allow specific users to access parts of the app ?

You get a token after successful authorization with Cognito and this token should contain the user name. I haven’t looked into where this is stored or how it would be accessed by Streamlit but it should be possible. Check this out for more details on the token.

1 Like

@thomelane I’m struggling to find a part where let’s say I already have my Streamlit server running on EC2 instance which I can access through http://ec2_instance_private_ip:port.

I’m mostly interested in converting this into https since Cognito won’t let me use http address. Can you point me to any relevant part in your GitHub repo? I can see you have added CloudFormation templets but since my Streamlit server is already running up; I’m mostly interested in putting it behind Cognito authentication so other people can access it.

So you need an SSL certificate for your domain for this. You’ll see some code in the repository where a self-signed certificate is generated and used if not provided by the user, but you’ll want your own certificate in practice. Also the certificate is given to the Application Load Balancer in this example, and that handles things for you. Just using a single EC2 instance, I think you might want to look at running a web server that supports SSL, something like nginx, over the top of your Streamlit server. I’m not much of an expert on that though unfortunately. Good luck!

2 Likes

Hi @thomelane, how would you go about adding the Cognito authentication without Cloudformation?

Thanks!

Hi, did you find out where the token is stored in the new streamlit versions ? I used to find in streamlit.server.Server.Server.get_current()._session_info_by_id.values().headers[""X-Amzn-Oidc-Data"]. Thanks in advance !

Hi again, I found out by myself (not an easy one since PyJwt syntax changed too). Here’s the solution:

import jwt
from streamlit.report_thread import get_report_ctx
from streamlit.server.server import Server

class User(object):
    def __init__(self) -> None:
        self.token_id = self._process_session_token()

    def _get_headers(self):
        session_id = get_report_ctx().session_id
        session_info = Server.get_current()._get_session_info(session_id)

        if session_info is None:
            raise RuntimeError("Couldn't get your Streamlit Session object.")
        if session_info.ws is None:
            return None

        return session_info.ws.request.headers

    def _process_session_token(self):
        headers = self._get_headers()

        if not headers or "X-Amzn-Oidc-Data" not in headers:
            return {}

        return jwt.decode(
            headers["X-Amzn-Oidc-Data"], algorithms=["ES256"], options={"verify_signature": False}
        )

Hi ,

I have deployed my app on Aws ec2 instance, how can I add authentication to it using Aws cognito?

Thanks

Hey - for anyone else looking in the future, here is some updated code to get the user’s details from cognito into the streamlit app. note you need pyjwt in order for this to work, it will not work with the standard jwt.


from streamlit.web.server.websocket_headers import _get_websocket_headers
import jwt
def process_session_token():
    '''
    WARNING: We use unsupported features of Streamlit
             However, this is quite fast and works well with
             the latest version of Streamlit (1.27)
             Also, this does not verify the session token's
             authenticity. It only decodes the token.
    '''
    headers = _get_websocket_headers()
    if not headers or "X-Amzn-Oidc-Data" not in headers:
        return {}
    return jwt.decode(
        headers["X-Amzn-Oidc-Data"], algorithms=["ES256"], options={"verify_signature": False}
    )

session_token = process_session_token()
st.write('Welcome: ', session_token['email'])

The discussion and code snippets posted here was very helpful for me, so I hope this is helpful to someone else in the future =)