azuredirect-line-botframeworkpower-platformmsalmicrosoft-copilot

How to bypass login popup when using Copilot Studio with manual authentication in a custom web app?


I'm integrating a Microsoft Copilot Studio agent into my company's custom groupware web app (C#), and I want to avoid showing any Microsoft login popups or authentication prompts inside the chat.

My Goal

What I’ve Tried

Problem

My Questions

  1. Is there any way to fully skip login prompts (MSAL popup or OAuth card) when using Copilot with manual authentication?
  2. Can App-only tokens (client_credentials flow) be accepted by Copilot during tokenExchange?
  3. If I already have UPN, Azure Object ID, etc., can I make Copilot trust that without Microsoft login?
  4. Can SAML login or other external auth be linked with Copilot’s OAuth flow?
  5. Is the only reliable option to force the user to manually authenticate once, so that silent MSAL login works afterward?

Any help or recommendations are greatly appreciated. 🙏
Let me know if you need code snippets from my exchangeTokenAsync() function or Web Chat configuration.


Solution

  • Note: To fully bypass login prompts in Microsoft Copilot Studio using manual authentication, you must pre-authenticate users in your app and securely pass a valid user-delegated access token (not an app-only token) to the token exchange endpoint.

    Microsoft Copilot Studio bots require user-delegated access tokens to provide user-specific experiences (contextual history, personalization, etc.). These tokens cannot be obtained silently unless the user has:

    Even if you have the user’s UPN, Object ID, or session in your system, Microsoft’s identity platform requires a login consent from the user to issue a token on their behalf.

    Note: Tokens from the client_credentials (app-only) flow will be rejected by Copilot’s tokenExchange because they don’t represent a user identity.

    Sample : Send Token to Bot via tokenExchange Event:

    const token = await getToken();
    
    window.WebChat.renderWebChat({
      directLine: window.WebChat.createDirectLine({ token: '<Your Direct Line Token>' }),
      userID: '<user-id>',
      store: window.WebChat.createStore({}, ({ dispatch }) => next => action => {
        if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
          dispatch({
            type: 'WEB_CHAT/SEND_EVENT',
            payload: {
              name: 'tokenExchange',
              value: { token }
            }
          });
        }
        return next(action);
      })
    }, document.getElementById('webchat'));