Authorization headers in callback API requests

I’m building a Dash app that is running behind an authentication middleware. The bearer token for authentication is accessible from localStorage localStorage.getItem('access_token'). However, the API calls to the _dash-update-component endpoint don’t include the Authorization header, only the CSRF header.

I noticed that the handleServerside method in dash_renderer.js (which is available in dash/dash-renderer/build/ path) is responsible for making the API request. While I can modify the JavaScript code to include the Authorization header with the access token stored in localStorage, I’m wondering if there’s a more generic solution that doesn’t involve modifying the Dash library code directly after installation.

Has anyone else faced this issue before? Is there a recommended best practice for adding the Authorization header to Dash’s _dash-update-component API request when using an authentication middleware? I’m hoping for a solution that doesn’t involve modifying the Dash library code directly.

Thanks in advance for your help!

Hello @chiragasourabh,

To use this, I think I would add the token to a header on the flask server itself. You could try to use after_request or before_request methods to add it if it doesn’t already exist. You’d have to do some checking to make sure that the request came from the proper site.

1 Like

@jinnyzor Thanks for your reply.

No. Since the Dash app is behind a proxy and an authentication server, only authenticated API requests will reach the Dash App(flask app) (static files can be loaded). So these Authentication headers should be part of the API requests that the UI makes.

I see that there can be hooks for request_pre (dash/callbacks.ts at e145b407bb41bd2845246dea231efe48e3391600 · plotly/dash · GitHub). However, it modifies only the payload and not the header.

found similar issues :
Request Hooks · Issue #65 · plotly/dash-renderer (github.com)
[Feature Request] Ability to add custom request headers · Issue #1329 · plotly/dash (github.com)

This includes get requests?

Or just post requests.

The initial app had to load as a get request, which means that you can apply a header to it.

only the POST APIs are failing with 401. the initial app loads fine by making a GET call to the root path and also loads all the javascript files fine.

The app is opened in an iframe with src referring to https://domain.com/somepath.

Hmm…

Is there any way that you could use a cookie instead?

no . cookies don’t contain the required information.

Here is a version that uses this:

import dash
from dash import Dash, html, dcc, Input, Output
from flask import request

app = Dash(__name__)

server = app.server

app.renderer = '''
var renderer = new DashRenderer({
    request_pre: (payload) => {
        // print out payload parameter
        console.log(payload);
        store.getState().config.fetch.headers['Authorization'] = localStorage.getItem("testing")
    },
    request_post: (payload, response) => {
        // print out payload and response parameter
        console.log(payload);
        console.log(response);
    }
})
'''

app.layout = html.Div(
    [html.Button(id='getHeader', children='get header'),
     html.Div(id='headerInfo'),
     dcc.Store(id='testing', storage_type='local', data='rawr')]
)

@app.callback(
    Output('headerInfo', 'children'),
    Input('getHeader', 'n_clicks'),
    prevent_initial_call=True
)
def showHeader(n):
    if request:
        print(request.headers)
        return request.headers['Authorization']

if __name__ == '__main__':
    app.run(debug=True)

Thanks @alexcjohnson

This looks promising to me. ill try it out.

is there any way to set it once and this will get reflected in all the dash app that is created (without customizing the DashRenderer for every App created.)?

You’d have to do it in each app that is not connected to the original.

You can run pages though, and it will use the same renderer.