Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

After a successful login with redirect the user does not get redirected back to redirectStartPage #7440

Open
2 tasks
Stralos opened this issue Nov 26, 2024 · 1 comment
Labels
bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-browser Related to msal-browser package msal-react Related to @azure/msal-react Needs: Attention 👋 Awaiting response from the MSAL.js team public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.

Comments

@Stralos
Copy link

Stralos commented Nov 26, 2024

Core Library

MSAL.js (@azure/msal-browser)

Core Library Version

3.27.0

Wrapper Library

MSAL React (@azure/msal-react)

Wrapper Library Version

2.2.0

Public or Confidential Client?

Public

Description

I have an issue that is occurring quite often where users are not redirected back to the provided redirectStartPage after successfully logging in via loginWithRedirect.

It seems that the navigation client is not being invoked after the user logs in (I have log events fired in those functions, and I don't see an event being fired)

Error Message

No error message, the thing just not happens

MSAL Logs

No response

Network Trace (Preferrably Fiddler)

  • Sent
  • Pending

MSAL Configuration

msal: {
    auth: {
      clientId: "****",
      authority: "****",
      redirectUri: "****",
      knownAuthorities: ["****"],
      protocolMode: "OIDC",
    },
    scopes: {
      login: ["openid", "profile", "api.backend"],
      token: ["api.backend"],
    },
  },
};

// I have blured out thins to keep it anonymous

Relevant Code Snippets

import {
  IPublicClientApplication,
  PublicClientApplication,
} from "@azure/msal-browser";
import type { Config } from "auth/config";

export async function getMSAL(config: Config) {
  const auth = config.appConfig.msal.auth;
  const msal = new PublicClientApplication({ auth });

  return msal.initialize().then<IPublicClientApplication>(() => msal);
}

---------PROVIDER

class CustomNavigationClient extends NavigationClient {
  private appInsights: ApplicationInsights;
  private history: ReturnType<typeof useRouter>["history"];

  constructor({
    appInsights,
    history,
  }: {
    history: ReturnType<typeof useRouter>["history"];
    appInsights: ApplicationInsights;
  }) {
    super();
    this.history = history;
    this.appInsights = appInsights;
  }

  async navigateInternal(
    url: string,
    options: NavigationOptions
  ): Promise<boolean> {
    try {
      if (options.noHistory) {
        this.history.replace(url);
        this.appInsights.trackEvent({
          name: "navigation-client",
          properties: { target: url, variant: "replace" },
        });
      } else {
        this.history.push(url);
        this.appInsights.trackEvent({
          name: "navigation-client",
          properties: { target: url, variant: "push" },
        });
      }
      return false;
    } catch (e) {
      this.appInsights.trackException({
        exception: isError(e)
          ? e
          : new Error("Navigation client navigate internal fail"),
        severityLevel: SeverityLevel.Error,
      });
      throw e;
    }
  }
}


export function MSALContext({
  children,
  msal,
}: PropsWithChildren<{ msal: IPublicClientApplication }>) {
  const appInsights = useAppInsights();
  const { history } = useRouter();

  const setAuthenticatedUserContext = useCallback(
    (account: AccountInfo | null) => {
      if (account) {
        const session = createSession(account);
        appInsights.setAuthenticatedUserContext(session.patientId);
      } else {
        appInsights.clearAuthenticatedUserContext();
      }
    },
    [appInsights]
  );

  const instance = useMemo(() => {
    const result = msal;
    msal.setNavigationClient(
      new CustomNavigationClient({ appInsights, history })
    );

    /**
     * Event list
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/events.md
     */
    result.addEventCallback((message) => {
      const failureEvents = new Set<EventType>([EventType.LOGIN_FAILURE]);
      if (!failureEvents.has(message.eventType)) {
        return;
      }

      appInsights.trackException({
        error: message.error ?? undefined,
        exception: message.error ?? undefined,
        severityLevel: SeverityLevel.Error,
      });
    });
    result.addEventCallback((message) => {
      if (message.eventType !== EventType.LOGIN_SUCCESS) {
        return;
      }
      const payload = message.payload as AuthenticationResult;
      result.setActiveAccount(payload.account);
      setAuthenticatedUserContext(payload.account);
    });
    result.addEventCallback(({ eventType }) => {
      if (eventType !== EventType.INITIALIZE_START) {
        return;
      }
      const activeAccount = result.getActiveAccount();
      setAuthenticatedUserContext(activeAccount);
    });

    return result;
  }, [appInsights, msal, setAuthenticatedUserContext, history]);

  return <MsalProvider instance={instance}>{children}</MsalProvider>;
}

---AUthenticated wall:
export function Authenticated({
  children,
  ErrorView,
}: PropsWithChildren<AuthenticatedProps>) {
  const { error, login } = useMsalAuthentication(InteractionType.Redirect, {
    scopes,
    redirectStartPage,
    redirectUri,
  });
  const loginCallback = useCallback(() => {
    return login(InteractionType.Redirect, {
      scopes,
      redirectStartPage,
      redirectUri,
    });
  }, [login, scopes, redirectStartPage, redirectUri]);

  useEffect(() => {
    if (!error) {
      return;
    }

    appInsights.trackException({
      exception: error,
      severityLevel: SeverityLevel.Error,
    });
  }, [error, appInsights]);

  useEffect(() => {
    // Means the ID token has expired and we need to re-login
    if (error?.errorCode === "invalid_grant") {
      login();
    }
  }, [error?.errorCode, login]);

  // if Id token has expired, we don't want to show an error screen
  if (error && error.errorCode === "invalid_grant") {
    return null;
  }

  if (error) {
    return <ErrorView login={loginCallback} error={error} />;
  }

  const isReady = !!(isAuthenticated && session);

  return (
      {isReady && <>{children}</>}
  );
}

Reproduction Steps

I can't find a way to reproduce it (works on my machine)

Expected Behavior

After user logs in, I expect them to be redirected back to the url they came from.

I see this trend only on IOS safari users

Identity Provider

Entra ID (formerly Azure AD) / MSA

Browsers Affected (Select all that apply)

Safari

Regression

No response

@Stralos Stralos added bug-unconfirmed A reported bug that needs to be investigated and confirmed question Customer is asking for a clarification, use case or information. labels Nov 26, 2024
@github-actions github-actions bot added msal-browser Related to msal-browser package msal-react Related to @azure/msal-react public-client Issues regarding PublicClientApplications labels Nov 26, 2024
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs: Attention 👋 Awaiting response from the MSAL.js team label Nov 26, 2024
@Stralos
Copy link
Author

Stralos commented Nov 26, 2024

I found some related issues: here with solution suggested here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-browser Related to msal-browser package msal-react Related to @azure/msal-react Needs: Attention 👋 Awaiting response from the MSAL.js team public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.
Projects
None yet
Development

No branches or pull requests

1 participant