feat(connectors): Microsoft checks share their sign-in row and Graph error rows

Merged
EV
1d ago
+1330-141

Description

Tenth backend PR for the connector checks redesign, stacked on #16200. It adds what the SharePoint, OneDrive and Outlook checks share. The three connector PRs that follow use it for their own rows.

Sign in to Microsoft (all three connectors)

  • One row for a failed sign-in. Every probe signs in first. Before, a bad secret made every check fail with the same error. Now every check after sign-in depends on it, so it shows "Not run: Sign in to Microsoft failed".
  • Name and lines. The sign-in check is "Sign in to Microsoft". Each sign-in refusal gives the design's line and description: "A required account field is empty", "Certificate file does not open", "Directory ID not found", "Secret or certificate was rejected", "App registration not found", "Microsoft did not issue a token", "Microsoft refused the sign-in request", "Microsoft sign-in is unavailable" and "Unexpected answer from Microsoft sign-in".
  • The fields to fix. A description names the account's fields with the connector's labels ("SharePoint Client ID", "OneDrive Certificate", "Microsoft Outlook Client Secret"). It names the fields of the account's sign-in method: the secret for a secret account, the certificate and its password for a certificate account.
  • Expiry. An expired client secret (AADSTS7000222) says so. A certificate account reads the certificate's end date from the .pfx, with no call to Microsoft. An expired certificate gives its end date. A passing sign-in gives "Certificate valid until YYYY/MM/DD", and a caveat when the certificate ends in 30 days or less.
  • Pass line. "Signed in as {app name}", from the access token's app_displayname claim. The claims are read without a signature check: they only name the app. Without the claim, the line names the app id.
  • Form run policy. On a form run, a sign-in that cannot reach Microsoft fails (fails_when_unreachable=True). Other runs keep it Incomplete.
  • Form unlock. OneDrive and Outlook sign-in now set validates_binding, as SharePoint does. Their authority host and Graph API host are bound to the credential (MicrosoftCloudBinding), and sign-in proves the credential works with them.

Graph errors (all Microsoft callers)

  • Rate limit. A 429 raises RateLimitedValidationError ("Microsoft is throttling requests"), which stops the run. Before, it was a generic unexpected error.
  • Unreachable. A request that gets no answer after retries raises UnreachableValidationError ("Cannot reach Microsoft").
  • Rejected token. A 401 gives "Microsoft rejected the app's token".
  • Unexpected answer. A 5xx or another status gives "Unexpected answer from Microsoft", with the name of the request.
  • Rows from the caller. raise_for_graph_error takes the row of a 403 (denied_row) and of a 404 or 423 (not_found_row). The connector PRs use them.
  • Error Details. MicrosoftGraphError is a SourceApiError. It carries the request method, the URL and the response body, so Error Details show them (redacted as in #16160).

Gateways. The three check_token operations return one shared MicrosoftTokenInfo (lifetime, app name, app id, certificate end date). The three connector token models are removed.

Deviations from the design

  • "Directory ID not found" and "Cannot reach Microsoft sign-in": the design's descriptions end with "(HTTP 429)". A missing directory is not a 429, and a 429 at sign-in is the shared rate-limit row. I left the status out of both.
  • "Secret or certificate was rejected" and "A required account field is empty": the design's text names only the secret fields. A certificate account gets the certificate fields.
  • "Sign-in timed out": not done. The runner owns the timeout text for every source, so this row keeps the runner's "Timed out" line.

How Has This Been Tested?

  • New unit tests (test_microsoft_check_rows.py): every sign-in refusal line, the expired secret and certificate, the token request statuses (429, no answer, 5xx, 4xx, a body that is not JSON), the Graph rate limit, unreachable, 401 and caller rows, Error Details from a Graph refusal, the certificate end date from a real .pfx, the app name from the token, and the expiry caveat. For each of the three connectors: a failed sign-in stops the other checks, an unreachable sign-in fails only a form run, and a throttled sign-in stops the run.
  • Existing SharePoint, OneDrive and Outlook tests updated to the shared token model.
  • Connector, server and EE unit tests: 5527 passed, 1 failed (web/test_browser_lifecycle.py, a web connector test that also fails without this change). ty and pre-commit are clean.
  • The live SharePoint test (test_sharepoint_capability_checks_live.py) checks the new sign-in line and the stopped checks. I did not run it: the test tenant's secrets are in AWS Secrets Manager, and this session has no AWS access.

Additional Options

  • [Optional] Please cherry-pick this PR to the latest release version.
  • [Optional] Override Linear Check

Generated by Claude Code


Summary by cubic

Unifies the SharePoint, OneDrive, and Outlook capability checks around one shared sign-in probe and shared Graph error rows. A failed sign-in now shows a single "Sign in to Microsoft" row, and every check after it reports "Not run" instead of failing with the same error.

Sign-in row

  • Sign-in refusals map to the design's lines and descriptions, naming the account's fields with the connector's labels.
  • An expired client secret or certificate says so; a certificate account reads the certificate's end date from the .pfx, with a caveat in the last 30 days.
  • A passing sign-in shows "Signed in as {app name}" from the token's claims, or the app id when the claim is missing. A name too long for the summary is cut there and given in full in the description.
  • An unreachable sign-in fails on a form run and stays Incomplete otherwise. OneDrive and Outlook sign-in now validate the credential binding, as SharePoint already did.

Graph errors and Error Details

  • A 429 stops the run as RateLimitedValidationError; no answer becomes UnreachableValidationError; a 401 and unexpected answers have their own rows.
  • Callers pass the rows for a 403 and a 404 or 423.
  • MicrosoftGraphError is now a SourceApiError carrying the request method, URL, and response body, so Error Details show them.
  • The three connector token models are replaced by one MicrosoftTokenInfo.

Summary by CodeRabbit

  • New Features

    • Improved SharePoint, OneDrive, and Outlook connection checks with consistent sign-in status, account details, and actionable guidance.
    • Added app identity and certificate information to successful sign-in results.
    • Added certificate expiration warnings and clearer credential validation messages.
    • Capability checks now run in the correct order and stop when authentication fails.
  • Bug Fixes

    • Improved handling and reporting for throttling, unreachable services, permission issues, and Microsoft Graph errors.
    • Error details now provide more useful request and response context.
  • Documentation

    • Documented shared Microsoft connector sign-in and capability-check behavior.