feat(credentials): second auth modes for ServiceNow, Snowflake, Infisical, and Google Ads

Merged
WA
3d ago
+2000-239

Summary

Adds a second (or third) sign-in mode to integrations that already support saved credentials. Each one is a new authMethod or stored blob type, and every existing stored shape resolves exactly as before.

  • ServiceNow: OAuth client credentials. Sim mints a token at {instance}/oauth_token.do through the configured-endpoint egress guard and shares one coordinated token per client. Tools and attachment upload send it as a Bearer token. Saved username/password logins are unchanged (Basic).
  • Snowflake: key-pair JWT as a third mode, beside programmatic access tokens and keyless workload identity. Sim stores an unencrypted RSA key (2048 to 4096 bits) and signs an RS256 JWT for each run: iss is ACCOUNT.USER.SHA256:<fp>, sub is ACCOUNT.USER, both uppercased, valid 59 minutes, sent with X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT. The account comes from the host's first label. An account whose name has underscores signs as that name from either of its hostnames (myorg-my_account or myorg-my-account): organization names hold only letters and numbers and account names never hold a hyphen, so every hyphen after the first is a replaced underscore. It needs no workload identity, so organization credentials and deployments without a signing key can use it. The credential provider catalog (v2, Copilot, CLI) lists a Snowflake "Connection configuration" field that documents the key pair in every scope; the keyless hint is appended only where keyless is available. Host hints now name .snowflakecomputing.cn, which was already accepted.
  • Infisical: Universal Auth client ID and secret, logged in at {instance}/api/v1/auth/universal-auth/login through the new postToConfiguredTokenEndpoint guard. This replaces pasted access tokens that expire. One coordinated token per identity, served for at most a day. An expiresIn of 0 (an access token TTL of 0) is also served for a day. Revoked tokens and tokens past their use limit are answered with 401 by Infisical, so the existing 401 invalidation logs in again on the next call.
  • Google Ads: accepts the google-service-account JSON key (adwords scope; the service account is added as a user in Ads). Keyless Google credentials are still refused for Ads.
  • Shared, additive pieces:
    • exchangeClientCredentialsGrant takes an egress: 'configuredEndpoint' option. The request type is a discriminated union, so fetchOptions can't be combined with it.
    • readAccessTokenResponse holds the refusal classification, capped JSON read, token and lifetime checks, and lifetime cap. The grant and the Infisical login both use it.
    • OAuthConfig.optionalCredentialParams lets a tool policy name a mapped param that a credential mode lacks; it is cleared instead of failing.
    • Token descriptor fields take requiredForAuthMethods (token or client_credentials), the same vocabulary client-credential descriptors and the v2 catalog already use. ServiceNow's username is ['token']: it shows only in the pasted-token mode, is never required or stored in client-credentials mode, and the catalog says so.
    • authStyle gains bearer and snowflake-key-pair; both are authoritative, so caller or model values are stripped.

Vendor references: ServiceNow client credentials and grant workflow; Snowflake SQL API authentication and account identifiers; Infisical Universal Auth login, attach (TTL ranges) and Universal Auth; Google Ads service accounts and developer token sunset.

Not included: Infisical OIDC keyless. Infisical matches subjects as glob patterns, so Sim cannot pin a credential's subject, and this needs a security decision and a live proof first.

Product update (if relevant)

  • ServiceNow and Infisical can connect without storing a person's password or a token that expires.
  • Snowflake can connect with a key pair wherever keyless workload identity isn't available.
  • Google Ads reporting can run as a service account.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Other: ___________

Testing

  • Unit tests were written test-first for each grant and minter. They cover request shape through the egress guard, lifetime caps (including Infisical's expiresIn 0), refused and invalid responses, unsafe instance URLs, missing secrets (no request sent), and abort. The configured-endpoint guard's own cases (egress refused, unresolvable or transiently failing host, abort) are tested in client-credentials-grant.test.ts.
  • Snowflake JWT claims and fingerprint, locator accounts, underscore accounts from both hostnames, and key-shape refusals are tested.
  • Catalog contract tests check that the Snowflake key-pair field is listed for workspaces that can sign, workspaces that cannot, and organization scope, and that ServiceNow's username carries requiredForAuthMethods: ['token'].
  • Executor tests check that a ServiceNow login sends Basic as before, a minted token is sent as Bearer, and a caller-supplied username is never paired with the saved password.
  • Revert proofs: removing the user uppercasing, the optional-param clearing, or the zero-lifetime handling turns the matching tests red. The hyphen-host test was red before the account-name fix, and the catalog tests were red before the catalog changes.
  • Targeted Vitest passes. Generated-artifact and boundary checks pass: tool-metadata, deployment-config, openapi, cli-api, mcp-operations, egress-boundary, api-validation:strict.
  • Reviewers, please focus on:
    • Rolling deploys: old workers fail closed on the new blob types and authStyle values.
    • Keyless subject sweep: it treats a key-pair blob as keyed, so it never blocks keyless creation.
    • ServiceNow inline mode: authStyle cannot be set by an inline caller.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Screenshots/Videos

Connect dialogs: ServiceNow and Infisical gain an auth method picker; Snowflake gains a "Key pair (RSA private key)" option.