From 73771cb58cea6d1b7e69e4f339e2a1ef19826b75 Mon Sep 17 00:00:00 2001 From: GareArc Date: Sun, 26 Apr 2026 23:24:56 -0700 Subject: [PATCH] refactor(api): drop vestigial Accepts.APP from validate_bearer (Phase A.2) Accepts.APP and the matching app- short-circuit existed to let routes declare "I accept either OAuth or app- tokens", but no production caller ever did, and the short-circuit returned without doing the tenant/app/end-user setup that app- tokens actually need (that lives in service_api/wraps.py:validate_app_token). After this change, validate_bearer is OAuth-only. app- bearers fall through the prefix dispatch and surface as InvalidBearer -> 401, which is what we already promised on /openapi/* (no app- accepted) and what the docstring claimed all along. Pre-check rg "Accepts\\.APP" returned zero hits outside the function being edited; no callers to update. Plan: docs/superpowers/plans/2026-04-26-openapi-migration.md (in difyctl repo). --- api/libs/oauth_bearer.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/api/libs/oauth_bearer.py b/api/libs/oauth_bearer.py index d82250a622..6eb7aedab0 100644 --- a/api/libs/oauth_bearer.py +++ b/api/libs/oauth_bearer.py @@ -318,7 +318,6 @@ def _row_from_cache(data: dict) -> ResolvedRow: class Accepts(StrEnum): USER_ACCOUNT = "user_account" USER_EXT_SSO = "user_ext_sso" - APP = "app" ACCEPT_USER_ANY: frozenset[Accepts] = frozenset({Accepts.USER_ACCOUNT, Accepts.USER_EXT_SSO}) @@ -355,8 +354,9 @@ def _extract_bearer(req) -> str | None: def validate_bearer(*, accept: frozenset[Accepts]) -> Callable: """Opt-in: omitting it leaves the route unauthenticated. - Coexists with legacy ``app-`` keys (tenant+app scoped, resolved in - ``service_api/wraps.py``) and user-level OAuth bearers (resolved here). + Resolves user-level OAuth bearers (``dfoa_`` / ``dfoe_``). Legacy + ``app-`` keys belong to ``service_api/wraps.py:validate_app_token`` + and are rejected here as the wrong auth scheme for this surface. """ def wrap(fn: Callable) -> Callable: @@ -366,12 +366,6 @@ def validate_bearer(*, accept: frozenset[Accepts]) -> Callable: if token is None: raise Unauthorized("missing bearer token") - # app- keys bypass the OAuth authenticator (work even when disabled). - if token.startswith("app-"): - if Accepts.APP not in accept: - raise Unauthorized("app-scoped keys not accepted here") - return fn(*args, **kwargs) - if _authenticator is None: raise ServiceUnavailable( "bearer_auth_disabled: set ENABLE_OAUTH_BEARER=true to enable"