Skip to content

SSO + OBO Flow for Declarative Agents Calling Microsoft Graph #15370

@mjfusa

Description

@mjfusa

Is your feature request related to a problem? Please describe.

When building a Declarative Agent that calls Microsoft Graph (/admin/serviceAnnouncement/messages), we could not get SSO working via identityProvider: MicrosoftEntra on the oauth/register step. The OBO (On-Behalf-Of) token exchange silently fails — Entra ID sign-in logs show the initial SSO token is issued successfully (scoped to the agent's own API), but the platform never performs the OBO exchange to acquire a Microsoft Graph access token. There is no error surfaced to the developer; the agent simply fails to retrieve data. Additionally, Entra ID sign-in logs recorded error 50011 (redirect URI mismatch), indicating the platform sends a redirect URI during the SSO flow that doesn't match what's configured on the Entra ID app registration — and the developer has no visibility into or control over what redirect URI the platform constructs.

Describe the solution you'd like

  1. Fix the OBO token exchange — When identityProvider: MicrosoftEntra is set and the SSO token is successfully obtained, the platform should execute the OBO exchange to acquire a downstream API token (e.g., Microsoft Graph) and surface a clear error if it fails.
  2. Surface diagnostic information — Provide logging or error output when the SSO+OBO flow fails, rather than failing silently. Developers should not need to manually inspect Entra ID sign-in logs to debug authentication issues.
  3. Resolve the redirect URI mismatch — The platform should either automatically configure the correct redirect URIs on the Entra ID app during oauth/register, or document exactly which redirect URIs must be present for SSO to work.
  4. Clarify identifierUris ownership — Document the interaction between oauth/register (which sets the Application ID URI to api://auth-{guid}/{clientId}) and aad.manifest.json (which can also define identifierUris). Setting it in the wrong place silently breaks the flow.
  5. Provide an end-to-end SSO+OBO sample — Publish a Declarative Agent sample that uses SSO to call Microsoft Graph as a downstream API, covering the full aadApp/createaadApp/updateoauth/register lifecycle.

Describe alternatives you've considered

  1. Implementing the OBO token exchange in custom code — In a traditional Bot Framework or Azure Function–backed agent, we could intercept the SSO token and call the Entra ID /oauth2/v2.0/token endpoint with grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer to exchange it for a Microsoft Graph token ourselves. However, Declarative Agents have no custom backend — they are purely manifest-driven configurations where the platform owns the entire auth and API call pipeline. There is no code entry point where a developer can insert an OBO exchange. This is why we need the platform to handle the OBO leg natively when identityProvider: MicrosoftEntra is set.

  2. Standard OAuth2 authorization code flow (current workaround) — We replaced SSO+OBO with OAuth2 auth code flow using PKCE + client secret (confidential client). This requires a one-time interactive consent prompt instead of silent SSO, but actually works. Specifically:

    • Removed identityProvider: MicrosoftEntra from oauth/register
    • Added clientId, clientSecret, and isPKCEEnabled: true to oauth/register
    • Added aadApp/create and aadApp/update steps to the provision lifecycle in m365agents.yml
    • Added explicit scopes (https://graph.microsoft.com/ServiceMessage.Read.All) to the OpenAPI spec's operation-level security

    With a confidential client, refresh tokens last ~90 days, so users only re-authenticate after prolonged inactivity. The UX trade-off is acceptable but SSO would be the ideal experience.

Additional context

  • Error evidence: Entra ID sign-in log entry with error code 50011 is captured in our repo at dev/signin-50011.json — the failure reason states the redirect URI in the request does not match the redirect URIs configured for the application.
  • Sign-in log observation: Logs showed successful AAD Graph SSO completions but zero Microsoft Graph token requests, confirming the OBO leg never fired.
  • Entra ID app config: The app registration included all required configuration — access_as_user scope, pre-authorized Teams/Office client app IDs, correct redirect URIs, idtyp optional claim, and requiredResourceAccess for User.Read + ServiceMessage.Read.All.
  • Architecture constraint: Declarative Agents are entirely manifest-driven with no custom backend. The platform is the only component that can perform the OBO exchange — there is no developer code path to work around this.
  • Toolkit versions: M365 Agents Toolkit, m365agents.yml schema v1.8.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs attentionThis issue needs the attention of a contributor.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions