Skip to content

Permalinks with kubeconfigID query parameter fail to navigate to the intended resource path on first access #4644

@pbochynski

Description

@pbochynski

Description

When accessing Busola with a permalink that includes both a resource path and kubeconfigID query parameter (e.g., https://busola.example.com/cluster/my-cluster/namespaces/default/pods?kubeconfigID=abc123), the user ends up at the cluster overview instead of the intended resource path on the first attempt.

The second click on the same link works correctly because the cluster configuration is already stored in session/local storage.

Expected Behavior

Accessing a permalink with kubeconfigID should:

  1. Load the kubeconfig from the kubeconfigID
  2. Authenticate the user (including OIDC flow if needed)
  3. Navigate to the intended resource path

Actual Behavior

User ends up at /cluster/{context-name}/overview instead of the intended path.


Root Cause Analysis

After analyzing the codebase, I identified three interconnected problems:

Problem 1: Context Name in URL Path is Unpredictable

The current URL structure requires the context name in the path:

/cluster/{contextName}/namespaces/default/pods?kubeconfigID=abc123

However, when using kubeconfigID:

  • The context name is not known until the kubeconfig is fetched and parsed
  • With multiple contexts in the kubeconfig, the user might select a different context than the one in the URL
  • The context name might change between kubeconfig versions

This makes it impossible to construct a reliable permalink that includes both kubeconfigID and a context-dependent path.

Problem 2: Race Condition in Cluster Configuration

Location: src/components/App/ClusterRoutes.jsx (lines 60-77)

useEffect(() => {
  if (cluster?.name === currentClusterName) return;
  const currentCluster = clusters?.[currentClusterName];
  const kubeconfigId = search.get('kubeconfigID');
  if (!currentCluster && !kubeconfigId) {
    removePreviousPath();
    alert("Such cluster doesn't exist");
    navigate('/clusters');
    return;
  }
  // ...
}, [currentClusterName, cluster, clusters, navigate, setCluster, setAuth, search]);

When the permalink is first accessed:

  1. The URL contains /cluster/my-cluster/namespaces/default/pods?kubeconfigID=abc123
  2. ClusterRoutes tries to find my-cluster in clusters state
  3. The cluster doesn't exist yet because useLoginWithKubeconfigID hasn't finished loading it
  4. The routing fails silently or redirects to overview

Problem 3: OIDC Redirect Loses the Resource Path

Location: src/state/authDataAtom.ts (lines 52-65)

export function createUserManager(
  oidcParams: { /* ... */ },
  redirectPath = '',  // <-- Always empty string!
) {
  return new UserManager({
    redirect_uri: window.location.origin + redirectPath,  // <-- Only origin, no path!
    // ...
  });
}

The OIDC redirect URI is set to window.location.origin only. When the OIDC provider redirects back:

  1. User is redirected to https://busola.example.com (just the origin)
  2. The kubeconfigID query parameter is lost
  3. The resource path is lost
  4. The savePreviousPath() mechanism doesn't help because it was called before the OIDC redirect

Proposed Solution

New URL Format for Permalinks

Instead of embedding the context name in the path, use a context-independent permalink format with a separate path query parameter:

https://busola.example.com/?kubeconfigID=abc123&path=/namespaces/default/pods

Or for cluster-scoped resources:

https://busola.example.com/?kubeconfigID=abc123&path=/nodes

Why This Approach is Better

  1. Context-independent: The path doesn't include the context name, so it works regardless of which context the user selects
  2. Predictable: The URL can be constructed without knowing the kubeconfig contents
  3. Survives OIDC: The path is stored in sessionStorage before any redirects
  4. Simple to implement: Minimal changes to existing code
  5. Backward compatible: Existing URLs without path parameter continue to work

Metadata

Metadata

Labels

kind/featureCategorizes issue or PR as related to a new feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions