Skip to content

Instantly share code, notes, and snippets.

@stanorama
Last active April 8, 2024 06:32
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stanorama/bb52930e3cf70138d7f199338c064ae6 to your computer and use it in GitHub Desktop.
Save stanorama/bb52930e3cf70138d7f199338c064ae6 to your computer and use it in GitHub Desktop.
IIS Reverse Proxy and Windows Authentication for Streamlit

IIS Reverse Proxy and Windows Authentication for Streamlit

Introduction

Setting up a reverse proxy on IIS (Internet Information Services) allows us to take advantage of windows authentication.

This means we can limit access to a streamlit app to a specific Active Directory group, Local group or list of Active Directory users.

(I haven't tested https support yet).

IIS Setup

IIS must be installed with additional roles: Under the windows server manager, navigate to and select the Websocket Protocol. Web Server (IIS) → Web Server → Application Development → Websocket Protocol

image

Under the windows server manager, navigate to and select Windows Authentication. Web Server (IIS) → Web Server → Security → Windows Authentication

image

IIS Configuration

Download and install ARR (Application Request Routing)

https://www.iis.net/downloads/microsoft/application-request-routing

Download and install URL Rewrite

https://www.iis.net/downloads/microsoft/url-rewrite

Application Request Routing

Open IIS Manager, ARR is only available on the top level connection (it doesn;t show as a feature on individual sites).

Under actions - Select 'Server Proxy Settings'

image

Configure the Options:

  • Enable Proxy: ON
  • HTTP version: pass through
  • Keep alive: ON
  • Reverde rewrite host in response header: ON
  • Preserve client IP in the following header: X-Forwarded-For
  • Include TCP port from client IP: OFF

image

Create IIS site

Create a site for your streamlit app. (Sites - Add website...) Site Name: MyStreamLitApp (set an appopriate name) Physical Path: Set the path to where you have your python files (This is only used to save the web.config file). Port: 8666 (or any value you wish but do NOT set the same value as the port used by streamlit).

image

URL Rewrite (Site Level)

On your site (MyStreamLitApp) open URL rewrite and create a new inbound rule:

Name: ReverseProxy (Can be any name you choose) Pattern: .* Rewrite URL: http://localhost:8502/{R:0} (This port should match the port that the streamlit app is running on) Stop Processing of subsequent rules: ON

image

Firewall

In Windows firewall, create a rule to block domain and public access to the port that the streamlit app runs on (8502 in this example).

(You should still be able to access the streamlit app directly if you remote desktop to the server and use a local browser installed on the server).

This is to ensure that a user cannot bypass the IIS proxy and use the streamlit app directly on its tornado web server.

Ensure that the IIS site port (8666 in this example) is allowed.

Windows Authentication

On your site (MyStreamLitApp) open 'Authentication' and set the following:

  • Anonymous authentication: Disabled
  • Windows Authentication: Enabled

image

Windows Authentication Rules

On your site (MyStreamLitApp) open 'Authentication Rules'.

  • Remove any default rules.
  • Add a rule for each AD group, Local Group or AD user that will be permitted to access the streamlit app.

image

Checking web.config

The web.config file under c:\streamlit\MyStreamLitApp should look something like this:


<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="ReverseProxy" stopProcessing="true">
                    <match url=".*" />
                    <action type="Rewrite" url="http://localhost:8502/{R:0}" logRewrittenUrl="true" />
                </rule>
            </rules>
 
        </rewrite>
        <security>
            <authorization>
                <remove users="*" roles="" verbs="" />
                <add accessType="Allow" roles="MyADgroup" />
            </authorization>
        </security>
    </system.webServer>
</configuration>

Enabling Detailed Errors

While testing the configuration it may be helpful to return detailed errors to the browser: On the top level connection, goto 'Error Pages' and then 'Edit Deature Settings...' and select 'Detailed errors' Remember to turn this off once you go live.

image

Testing

Point your client browser to http://myserver:8502 (replace myserver with your server name!) This request should timeout as the firewall will be blocking this port.

Point your client browser to http://myserver:8666 If you are logged on as a user that has been granted access you should see the streamlit app. If you are logged in as a user that has not been granted access you should receive a 401 response (HTTP Error 401.2 - Unauthorized)

You can print the headers in the streamlit app, to see that the Authorization header has been passed.

    from streamlit.web.server.websocket_headers import _get_websocket_headers

    headers = _get_websocket_headers()
    print(headers)

Trial and Error

These steps are listed to show which settings were not necessary but may have been required with other web servers. I initially experimented with the following server variables (copied from the nginx setup), however I found they are not required.

<serverVariables>
    <set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
    <set name="HTTP_X_FORWARDED_SCHEMA" value="http" />
    <set name="HTTP_X_FORWARDED_PROTO" value="http" />
    <set name="HTTP_UPGRADE" value="websocket" />
    <set name="HTTP_CONNECTION" value="upgrade" />
</serverVariables>

Additionally the disabling of CORS and XSRF Protection do not matter with IIS.

[server]
enableCORS = false
enableXsrfProtection = false

Other

Unfortunately it is not possible to pass on the user name to streamlit, so the security is limited to accessible or not, it would not be possible to do fine grained control of streamlit page elements.

<serverVariables>
    <set name="HTTP_LOGON_USER" value="{LOGON_USER}" />
</serverVariables>

https://social.msdn.microsoft.com/Forums/en-US/cef5fd35-e38a-4673-9889-3ccbe64c3f97/url-redirect-based-on-logged-in-user?forum=iisurlrewritemodule

@piedhorse
Copy link

Hii, Can you help me on this? Please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment