apache / superset

Apache Superset is a Data Visualization and Data Exploration Platform
https://superset.apache.org/
Apache License 2.0
60.53k stars 13.07k forks source link

Superset Login Redirect After Guest Token Usage in Angular Iframe #29303

Open Ranindu15 opened 2 weeks ago

Ranindu15 commented 2 weeks ago

Bug description

This issue occurs when attempting to embed a Superset dashboard within an Angular application iframe using a guest token. After the initial load, the iframe redirects to the Superset login page instead of displaying the dashboard.

How to reproduce the bug

  1. Configure Superset to generate guest tokens.
  2. In an Angular application, fetch a guest token for a specific dashboard using the provided API endpoint.
  3. Embed the Superset dashboard URL within an iframe, including the guest token as a query parameter.
  4. Observe that the iframe redirects to the Superset login page instead of displaying the dashboard.

Screenshots/recordings

Image_20240619_135615_301

Superset version

master / latest-dev

Python version

3.9

Node version

16

Browser

Chrome

Additional context

After logging in once, the dashboard loads. However, clearing the cache redirects you to the login page again.

Checklist

dosubot[bot] commented 2 weeks ago

Hey @Ranindu15! 👋 I'm here to help you with this Superset issue while you wait for a human maintainer. I can assist with bug solving, answer questions, and support you in becoming a contributor.

To prevent the iframe embedding a Superset dashboard in an Angular application using a guest token from redirecting to the Superset login page after the initial load, ensure the guest token is correctly set up and handled. Here are the steps and code snippets to address this issue:

  1. Handle Unauthorized Access: Ensure that unauthorized access is handled by displaying a message instead of redirecting to the login page.

    /**
    * If there is a problem with the guest token, we will start getting
    * 401 errors from the api and SupersetClient will call this function.
    */
    function guestUnauthorizedHandler() {
     if (displayedUnauthorizedToast) return; // no need to display this message every time we get another 401
     displayedUnauthorizedToast = true;
     // If a guest user were sent to a login screen on 401, they would have no valid login to use.
     // For embedded it makes more sense to just display a message
     // and let them continue accessing the page, to whatever extent they can.
     store.dispatch(
       addDangerToast(
         t(
           'This session has encountered an interruption, and some controls may not work as intended. If you are the developer of this app, please check that the guest token is being generated correctly.',
         ),
         {
           duration: -1, // stay open until manually closed
           noDuplicate: true,
         },
       ),
     );
    }
  2. Set Up Guest Client: Ensure the guestUnauthorizedHandler is set as the unauthorizedHandler in the setupGuestClient function.

    function setupGuestClient(guestToken: string) {
     setupClient({
       guestToken,
       guestTokenHeaderName: bootstrapData.config?.GUEST_TOKEN_HEADER_NAME,
       unauthorizedHandler: guestUnauthorizedHandler,
     });
    }
  3. Refresh Guest Token Periodically: Ensure the guest token is refreshed periodically to avoid expiration.

    export async function embedDashboard({
     id,
     supersetDomain,
     mountPoint,
     fetchGuestToken,
     dashboardUiConfig,
     debug = false,
     iframeTitle = "Embedded Dashboard",
    }: EmbedDashboardParams): Promise<EmbeddedDashboard> {
     // ... other code ...
    
     const [guestToken, ourPort]: [string, Switchboard] = await Promise.all([
       fetchGuestToken(),
       mountIframe(),
     ]);
    
     ourPort.emit('guestToken', { guestToken });
     log('sent guest token');
    
     async function refreshGuestToken() {
       const newGuestToken = await fetchGuestToken();
       ourPort.emit('guestToken', { guestToken: newGuestToken });
       setTimeout(refreshGuestToken, getGuestTokenRefreshTiming(newGuestToken));
     }
    
     setTimeout(refreshGuestToken, getGuestTokenRefreshTiming(guestToken));
    
     // ... other code ...
    }
  4. Embed Dashboard Using Superset Embedded SDK: Follow the example provided in the documentation to embed a dashboard.

    import { embedDashboard } from "@superset-ui/embedded-sdk";
    
    embedDashboard({
     id: "abc123", // given by the Superset embedding UI
     supersetDomain: "https://superset.example.com",
     mountPoint: document.getElementById("my-superset-container"), // any html element that can contain an iframe
     fetchGuestToken: () => fetchGuestTokenFromBackend(),
     dashboardUiConfig: { // dashboard UI config: hideTitle, hideTab, hideChartControls, filters.visible, filters.expanded (optional), urlParams (optional)
         hideTitle: true,
         filters: {
             expanded: true,
         },
         urlParams: {
             foo: 'value1',
             bar: 'value2',
             // ...
         }
     },
    });

By ensuring the guest token is correctly generated, passed, and refreshed, you can prevent the iframe from redirecting to the Superset login page [1][2][3].

To continue talking to Dosu, mention @dosu.