Skip to content

[ENG-4086] feat(catalog,api): declarative surface for multi-step custom auth#371

Merged
RajatPawar merged 4 commits into
mainfrom
rajatspawar/universal-custom-auth
Jul 14, 2026
Merged

[ENG-4086] feat(catalog,api): declarative surface for multi-step custom auth#371
RajatPawar merged 4 commits into
mainfrom
rajatspawar/universal-custom-auth

Conversation

@RajatPawar

@RajatPawar RajatPawar commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Extends the custom-auth schema so multi-step flows (browser redirects and/or server-side credential-exchange calls) can be expressed, and adds the endpoint that drives them. Step definitions and handlers live in the connectors library, so there are no function/step schemas here.

catalog.yaml

  • CustomAuthInput: add fieldType (text/password/select) and options; new CustomAuthInputOption (value/label).
  • CustomAuthOpts: add providerInputs (builder-configured inputs, routed to storage by fieldType) and multiStep (the flag that tells "multi-step custom" apart from static "custom").

api.yaml

  • POST /custom-auth/connect — start or resume a flow (namespaced sibling of /oauth-connect; inherits global auth like oauth-connect).
  • Schemas: CustomAuthConnectRequest, CustomAuthConnectResponse (oneOf redirect/connection), RedirectResponse.

Regenerated the derived JSON specs.

Review follow-ups (7419dbc)

  • Response enforces exactly one of redirect/connection via oneOf.
  • Clarified that provider/customAuth are required only on the first call (when sessionId is absent), validated at the app layer.

Extend the custom auth schema so multi-step flows (redirects and/or
server-side credential-exchange calls) can be expressed declaratively.
Step definitions and handlers live in the connectors library; the catalog
only carries the signal + inputs clients need.

catalog.yaml:
- CustomAuthInput: add fieldType (text/password/select) and options, so the
  UI can render masked/unmasked/dropdown fields.
- Add CustomAuthInputOption (value/label) for select fields.
- CustomAuthOpts: add providerInputs (builder-configured inputs, routed to
  storage by fieldType) and multiStep (tells "multi-step custom" apart from
  plain static "custom" at a glance; clients route to /custom-auth-connect).

api.yaml:
- Add POST /custom-auth-connect (sibling of /oauth-connect) to start/continue
  a flow, with CustomAuthConnectRequest, CustomAuthConnectResponse, and
  RedirectResponse schemas.

Regenerated the derived JSON specs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread api/api.yaml
Comment thread api/api.yaml Outdated
Comment on lines +4914 to +4922
CustomAuthConnectResponse:
title: Custom Auth Connect Response
type: object
description: Response from /custom-auth/connect. Exactly one of redirect or connection is set. A redirect means the client should open the URL and call again with sessionId + callbackParams; a connection means the flow is complete.
properties:
redirect:
$ref: "#/components/schemas/RedirectResponse"
connection:
$ref: "#/components/schemas/Connection"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Schema does not enforce "exactly one of redirect or connection" constraint. The description states this but the OpenAPI schema allows both fields to be set, both to be absent, or exactly one. This will allow invalid response objects to pass validation.

CustomAuthConnectResponse:
  title: Custom Auth Connect Response
  type: object
  description: Response from /custom-auth/connect...
  oneOf:
    - required: [redirect]
      properties:
        redirect:
          $ref: "#/components/schemas/RedirectResponse"
    - required: [connection]
      properties:
        connection:
          $ref: "#/components/schemas/Connection"

Without this constraint, clients cannot reliably determine the response state and may encounter runtime errors when accessing fields.

Suggested change
CustomAuthConnectResponse:
title: Custom Auth Connect Response
type: object
description: Response from /custom-auth/connect. Exactly one of redirect or connection is set. A redirect means the client should open the URL and call again with sessionId + callbackParams; a connection means the flow is complete.
properties:
redirect:
$ref: "#/components/schemas/RedirectResponse"
connection:
$ref: "#/components/schemas/Connection"
CustomAuthConnectResponse:
title: Custom Auth Connect Response
type: object
description: Response from /custom-auth/connect. Exactly one of redirect or connection is set. A redirect means the client should open the URL and call again with sessionId + callbackParams; a connection means the flow is complete.
oneOf:
- required: [redirect]
properties:
redirect:
$ref: "#/components/schemas/RedirectResponse"
- required: [connection]
properties:
connection:
$ref: "#/components/schemas/Connection"

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@RajatPawar RajatPawar changed the title feat(catalog,api): declarative surface for multi-step custom auth [ENG-4086] feat(catalog,api): declarative surface for multi-step custom auth Jul 13, 2026
@linear

linear Bot commented Jul 13, 2026

Copy link
Copy Markdown

ENG-4086

@RajatPawar RajatPawar requested a review from laurenzlong July 13, 2026 21:58
- CustomAuthConnectResponse: use oneOf to enforce exactly one of
  redirect/connection.
- CustomAuthConnectRequest: clarify provider/customAuth are required only on
  the first call (sessionId absent), enforced at the app layer; sessionId doc
  notes the resume case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@RajatPawar

Copy link
Copy Markdown
Contributor Author

Addressed both review comments in 7419dbc:

  • CustomAuthConnectResponse now uses oneOf to require exactly one of redirect/connection.
  • CustomAuthConnectRequest: provider/customAuth are conditionally required (first call only, i.e. when sessionId is absent) — clarified in the field descriptions and enforced at the application layer, since OpenAPI can't cleanly express first-call-vs-resume requirements. Kept projectIdOrName as the sole schema-level required field.

Values are fieldTypeText/fieldTypePassword/fieldTypeSelect instead of
text/password/select. A bare "password" value collided with other enums
(e.g. Oauth2Opts grantType) and forced oapi-codegen to prefix every enum
const in the connectors package, breaking existing references.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread api/generated/api.bundled.json Outdated
"post": {
"operationId": "customAuthConnect",
"summary": "Start or continue a multi-step custom auth flow",
"description": "Drives a multi-step custom auth flow (browser redirects and/or server-side credential-exchange calls). Call it once with the flow inputs to start; if the response contains a redirect, open it, then call again with the returned sessionId and the provider's callback params to continue. Repeat until the response contains a connection. Used by the prebuilt UI components; only providers whose ProviderInfo has customOpts.multiStep set use this endpoint.\n",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"description": "Drives a multi-step custom auth flow (browser redirects and/or server-side credential-exchange calls). Call it once with the flow inputs to start; if the response contains a redirect, open it, then call again with the returned sessionId and the provider's callback params to continue. Repeat until the response contains a connection. Used by the prebuilt UI components; only providers whose ProviderInfo has customOpts.multiStep set use this endpoint.\n",
"description": "Drives a multi-step custom auth flow (browser redirects and/or server-side credential-exchange calls). Call it once with the flow inputs to start; if the response contains a redirect, open it, then call again with the returned sessionId and the provider's callback params to continue. Repeat until the response contains a connection. Used by the prebuilt UI components; only providers whose ProviderInfo has customOpts.multiStep present can use this endpoint.\n",

Comment thread api/generated/api.bundled.json
Comment thread api/generated/api.bundled.json Outdated
- Reword the endpoint description (multiStep present can use this endpoint).
- Document that groupRef/groupName/consumerRef/consumerName are supplied on
  the first call and ignored on resume (the parked flow's identity is used).
- Drop providerWorkspaceRef from CustomAuthConnectRequest: custom auth carries
  workspace via providerMetadata (and the flow can capture it), so the field is
  redundant here.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@RajatPawar RajatPawar merged commit 2e1dd6e into main Jul 14, 2026
2 checks passed
@RajatPawar RajatPawar deleted the rajatspawar/universal-custom-auth branch July 14, 2026 00:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants