An authenticated Bokeh Application with a prefix defined not find any static resource

I have a bokeh application with basic authentication and a prefix defined, deployed from embedded bokeh server bootstrap.py file like this:

from bokeh.server.server import Server
from bokeh.server.auth_provider import AuthModule

from bokeh.command.util import build_single_handler_application

# Define Bokeh Prefix Web Context
prefix = "MP"

# Define Bokeh Authentication Module
auth_provider = AuthModule('./auth/auth.py')

# Define Bokeh application
bokeh_app = build_single_handler_application('./main.py')

# Define the server settings, including the cookie_secret
server_settings = {
    "cookie_secret": "my super secret",
}

# Embed the Bokeh server in the Tornado application with Authenticacion
bokeh_server = Server(
    {'/': bokeh_app},
    prefix=prefix,
    auth_provider=auth_provider,
    **server_settings)

# to resolve some bug in Bokeh Server I must to set the prefix manually
auth_provider._module.login_url = f'/{prefix}/login'
auth_provider._module.logout_url = f'/{prefix}/logout'

# Start Bokeh Server
bokeh_server.start()
bokeh_server.io_loop.start()

I have my project folder structure like this:

poc-bokeh-server |
   - auth |
     auth.py
     login.html
   - static |
     - images: 
       image_01.png
       image_02.png
     - css:
        styles.css
     bohek_app.py
     bootstrap.py

I start the bokeh server from poc-bokeh-server folder like this:

python boostrap.py

The application with prefix and authentication works ok, the login.html is showed but without any style the authentication works ok and redirect to my bokeh app, the logout works ok too.

My problem is the login.html view not load the styles and any images is not loaded too. The error obtain is:

http://localhost:5006/MP/static/css/styles.css 404 not found

NOTE: these resources works ok if not use any prefix using the prefix is impossible access to them using a prefix.

What is the problem?, I must to define these folders statically in tornado when start bokeh server? and how?

For more details the project can be clone and test it from this repo:
https://github.com/masalinas/poc-bokeh-auth

The static paths are at <prefix>/<app name>/static Since your repo seems to run bokeh serve you can add --log-level debug and it will print out all the tornado endpoints that are added. Or if you are running from your own script rather than bokeh serve you can set up Python basic logging and configure the log level yourself: logging.getLogger('bokeh').setLevel(log_level)

Finally I resolved the problem adding this static path to Tornado

# Define the static path
static_path = os.path.join(os.path.dirname(__file__), "static")

extra_patterns=[
      (r'/poc-bokeh-auth/static/(.*)', StaticFileHandler, {"path": static_path})
],

And loading the resources from:

<link rel="stylesheet" type="text/css" href="/MP/poc-bokeh-auth/static/css/styles.css">

I was thinking too hard about this, when the answer is simple. Automatic configuration of static paths can only happen for apps created with the DirectoryHandler because that configuration is relative to the specified directory. Your code passes a file main.py to build_single_handler_application, so DirectoryHandler is not used.

Finally this is my bootstrap file to start bokeh server with basic authentication and with static folders defined to have access to all my folder static resources and works ok. you said use DirectoryHandler to start my Bokeh App, but I need the embedded option to execute these lines to work ok

auth_provider._module.login_url = f'/{prefix}/login'
auth_provider._module.logout_url = f'/{prefix}/logout'

so how do you considere that I can improve this bootstrap code using DirectoryHandler option ?

# bootstrap.py

import os
import logging

from tornado.web import StaticFileHandler

from bokeh.server.server import Server
from bokeh.server.auth_provider import AuthModule
from bokeh.command.util import build_single_handler_application

# Set Loggin level for bokeh server
logging.getLogger('bokeh').setLevel(logging.DEBUG)

# Define Bokeh Server Prefix
prefix = 'MP'

# Define Bokeh Authentication Module
auth_provider = AuthModule('./auth/auth.py')

# Define Bokeh application
bokeh_app = build_single_handler_application('./main.py')

# Define the server settings, including the cookie_secret
server_settings = {
    'cookie_secret': 'my super secret',
}

# Define the allowed WebSocket origins (adjust for your domain and port)
websocket_origin = ['k8s.oferto.io:80', 'localhost:5006']

# Define the static path
static_path = os.path.join(os.path.dirname(__file__), "static")

# Embed the Bokeh server in the Tornado application with Authenticacion
bokeh_server = Server(
    {'/': bokeh_app},
    prefix=prefix,
    auth_provider=auth_provider,
    allow_websocket_origin=websocket_origin,
    extra_patterns=[
        (r'/poc-bokeh-auth/static/(.*)', StaticFileHandler, {"path": static_path})
    ],
    **server_settings)

# Some bug from Bokeh Server that not set the prefix for external views
auth_provider._module.login_url = f'/{prefix}/login'
auth_provider._module.logout_url = f'/{prefix}/logout'

# Start Bokeh Server
bokeh_server.start()
bokeh_server.io_loop.start()

Generally, don’t store a secret key directly in code, since it might accidentally get checked into revision control.

You should not need to set the login URL specially for the prefix. Please file aGitHub Issue with full details.

Ok perfect, thanks for your time. I will close the ticket and continue reading from github.