mirror of
https://github.com/openai/codex.git
synced 2026-10-20 17:38:45 +00:00
Add explicit gateway OAuth sign-in to app-server (#47207)
## Why Clients with a gateway sign-in UI need to control when browser authorization starts and inspect credential readiness before making authenticated requests. ## What changed - Add `initialize.capabilities.explicitGatewayOauth` to require explicit login while allowing existing credentials to refresh. Preserve automatic authorization for clients that omit the capability, and prevent later connections from undoing explicit opt-in. - Add `account/gatewayOAuth/read`, `account/gatewayOAuth/login`, and `account/gatewayOAuth/cancel`, plus `account/gatewayOAuth/changed` notifications. Send the authorization URL only to the initiating connection and cancel its login on disconnect. - Check gateway authentication before returning cached results from `model/list`, with restart guidance when provider settings have changed. - Update protocol schemas, TypeScript and Python bindings, and document capability probing and the sign-in lifecycle. ## Testing Add tests for passive readiness reads, credential reuse after login, token exchange failures, cancellation and immediate retry, connection ownership, legacy versus explicit login, and model-list authentication checks. GitOrigin-RevId: a26e116a62c9f3db84dc238a40b7f4e816eb1594
This commit is contained in:
@@ -27,6 +27,7 @@ from .v2_all import FileChangePatchUpdatedNotification
|
||||
from .v2_all import FsChangedNotification
|
||||
from .v2_all import FuzzyFileSearchSessionCompletedNotification
|
||||
from .v2_all import FuzzyFileSearchSessionUpdatedNotification
|
||||
from .v2_all import GatewayOAuthChangedNotification
|
||||
from .v2_all import GuardianWarningNotification
|
||||
from .v2_all import HookCompletedNotification
|
||||
from .v2_all import HookStartedNotification
|
||||
@@ -109,6 +110,7 @@ KnownNotificationPayload: TypeAlias = (
|
||||
| FsChangedNotification
|
||||
| FuzzyFileSearchSessionCompletedNotification
|
||||
| FuzzyFileSearchSessionUpdatedNotification
|
||||
| GatewayOAuthChangedNotification
|
||||
| GuardianWarningNotification
|
||||
| HookCompletedNotification
|
||||
| HookStartedNotification
|
||||
@@ -172,6 +174,7 @@ KnownNotificationPayload: TypeAlias = (
|
||||
)
|
||||
|
||||
NOTIFICATION_MODELS: dict[str, type[KnownNotificationPayload]] = {
|
||||
"account/gatewayOAuth/changed": GatewayOAuthChangedNotification,
|
||||
"account/login/completed": AccountLoginCompletedNotification,
|
||||
"account/rateLimits/updated": AccountRateLimitsUpdatedNotification,
|
||||
"account/updated": AccountUpdatedNotification,
|
||||
|
||||
@@ -1830,6 +1830,27 @@ class FuzzyFileSearchSessionUpdatedNotification(BaseModel):
|
||||
session_id: Annotated[str, Field(alias="sessionId")]
|
||||
|
||||
|
||||
class GatewayOAuthCancelResponse(BaseModel):
|
||||
pass
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
|
||||
|
||||
class GatewayOAuthLoginResponse(BaseModel):
|
||||
pass
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
|
||||
|
||||
class GatewayOAuthStatus(Enum):
|
||||
not_ready = "notReady"
|
||||
started = "started"
|
||||
succeeded = "succeeded"
|
||||
failed = "failed"
|
||||
|
||||
|
||||
class GetAccountParams(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -2094,6 +2115,13 @@ class InitializeCapabilities(BaseModel):
|
||||
description="Opt into receiving experimental API methods and fields.",
|
||||
),
|
||||
] = False
|
||||
explicit_gateway_oauth: Annotated[
|
||||
bool | None,
|
||||
Field(
|
||||
alias="explicitGatewayOauth",
|
||||
description="Use explicit gateway OAuth login instead of automatic browser authorization. Applies to this app-server's gateway runtime; later connections cannot undo it.",
|
||||
),
|
||||
] = None
|
||||
extensions: Annotated[
|
||||
dict[str, Any] | None,
|
||||
Field(description="MCP extension settings declared by the app-server client."),
|
||||
@@ -7249,6 +7277,41 @@ class ModelListRequest(BaseModel):
|
||||
params: ModelListParams
|
||||
|
||||
|
||||
class AccountGatewayOAuthReadRequest(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
id: RequestId
|
||||
method: Annotated[
|
||||
Literal["account/gatewayOAuth/read"], Field(title="Account/gatewayOAuth/readRequestMethod")
|
||||
]
|
||||
params: None = None
|
||||
|
||||
|
||||
class AccountGatewayOAuthLoginRequest(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
id: RequestId
|
||||
method: Annotated[
|
||||
Literal["account/gatewayOAuth/login"],
|
||||
Field(title="Account/gatewayOAuth/loginRequestMethod"),
|
||||
]
|
||||
params: None = None
|
||||
|
||||
|
||||
class AccountGatewayOAuthCancelRequest(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
id: RequestId
|
||||
method: Annotated[
|
||||
Literal["account/gatewayOAuth/cancel"],
|
||||
Field(title="Account/gatewayOAuth/cancelRequestMethod"),
|
||||
]
|
||||
params: None = None
|
||||
|
||||
|
||||
class ModelProviderCapabilitiesReadRequest(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -8092,6 +8155,41 @@ class FunctionCallOutputContentItem(
|
||||
]
|
||||
|
||||
|
||||
class GatewayOAuthChangedNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
auth_url: Annotated[
|
||||
str | None,
|
||||
Field(
|
||||
alias="authUrl",
|
||||
description="Authorization handoff, sent only to the connection that started login.",
|
||||
),
|
||||
] = None
|
||||
error: str | None = None
|
||||
provider_id: Annotated[str, Field(alias="providerId")]
|
||||
status: GatewayOAuthStatus
|
||||
|
||||
|
||||
class GatewayOAuthReadResponse(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
error: str | None = None
|
||||
provider_id: Annotated[str, Field(alias="providerId")]
|
||||
provider_name: Annotated[str, Field(alias="providerName")]
|
||||
required: Annotated[
|
||||
bool,
|
||||
Field(
|
||||
description="Whether the selected provider uses gateway OAuth, even when already signed in."
|
||||
),
|
||||
]
|
||||
status: Annotated[
|
||||
GatewayOAuthStatus | None,
|
||||
Field(description="Null when the effective provider does not use gateway OAuth."),
|
||||
] = None
|
||||
|
||||
|
||||
class GetAccountResponse(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -9207,6 +9305,24 @@ class AccountUpdatedServerNotification(BaseModel):
|
||||
params: AccountUpdatedNotification
|
||||
|
||||
|
||||
class AccountGatewayOAuthChangedServerNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
emitted_at_ms: Annotated[
|
||||
int | None,
|
||||
Field(
|
||||
alias="emittedAtMs",
|
||||
description="Unix timestamp (in milliseconds) when app-server emitted this notification.",
|
||||
),
|
||||
] = None
|
||||
method: Annotated[
|
||||
Literal["account/gatewayOAuth/changed"],
|
||||
Field(title="Account/gatewayOAuth/changedNotificationMethod"),
|
||||
]
|
||||
params: GatewayOAuthChangedNotification
|
||||
|
||||
|
||||
class TurnModerationMetadataServerNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -12337,6 +12453,9 @@ class ClientRequest(
|
||||
| TurnInterruptRequest
|
||||
| ReviewStartRequest
|
||||
| ModelListRequest
|
||||
| AccountGatewayOAuthReadRequest
|
||||
| AccountGatewayOAuthLoginRequest
|
||||
| AccountGatewayOAuthCancelRequest
|
||||
| ModelProviderCapabilitiesReadRequest
|
||||
| ExperimentalFeatureListRequest
|
||||
| PermissionProfileListRequest
|
||||
@@ -12444,6 +12563,9 @@ class ClientRequest(
|
||||
| TurnInterruptRequest
|
||||
| ReviewStartRequest
|
||||
| ModelListRequest
|
||||
| AccountGatewayOAuthReadRequest
|
||||
| AccountGatewayOAuthLoginRequest
|
||||
| AccountGatewayOAuthCancelRequest
|
||||
| ModelProviderCapabilitiesReadRequest
|
||||
| ExperimentalFeatureListRequest
|
||||
| PermissionProfileListRequest
|
||||
@@ -12701,6 +12823,7 @@ class ServerNotification(
|
||||
| McpServerStartupStatusUpdatedServerNotification
|
||||
| McpServerEventStreamNotificationServerNotification
|
||||
| AccountUpdatedServerNotification
|
||||
| AccountGatewayOAuthChangedServerNotification
|
||||
| AccountRateLimitsUpdatedServerNotification
|
||||
| AppListUpdatedServerNotification
|
||||
| RemoteControlStatusChangedServerNotification
|
||||
@@ -12789,6 +12912,7 @@ class ServerNotification(
|
||||
| McpServerStartupStatusUpdatedServerNotification
|
||||
| McpServerEventStreamNotificationServerNotification
|
||||
| AccountUpdatedServerNotification
|
||||
| AccountGatewayOAuthChangedServerNotification
|
||||
| AccountRateLimitsUpdatedServerNotification
|
||||
| AppListUpdatedServerNotification
|
||||
| RemoteControlStatusChangedServerNotification
|
||||
|
||||
Reference in New Issue
Block a user