dify/api/controllers/oauth_device_sso.py
GareArc 71e9e8dda6
feat(api): lift SSO branch device-flow handlers to /openapi/v1 (Phase D.15-16)
The four EE-only SSO handlers (sso_initiate, sso_complete,
approval_context, approve_external) move from controllers/oauth_device_sso.py
to controllers/openapi/oauth_device/. Each is registered on openapi_bp
via @bp.route at the canonical path:

  /openapi/v1/oauth/device/sso-initiate
  /openapi/v1/oauth/device/sso-complete
  /openapi/v1/oauth/device/approval-context
  /openapi/v1/oauth/device/approve-external

sso-complete moves under /oauth/device/ from its previous orphan path
/v1/device/sso-complete; the IdP-side ACS callback URL hardcoded in
sso_initiate now points to the canonical path. Operators must
re-register the ACS callback with each IdP before Phase F deletes the
legacy alias.

oauth_device_sso.py shrinks to a thin re-mount file: same legacy bp
with attach_anti_framing applied, four bp.add_url_rule() calls binding
the legacy paths to the imported view functions. Same handler runs
for both mounts — no duplicated logic.

attach_anti_framing(openapi_bp) added in controllers/openapi/__init__.py
so X-Frame-Options + frame-ancestors CSP cover the canonical paths too.

Plan: docs/superpowers/plans/2026-04-26-openapi-migration.md (in difyctl repo).
2026-04-27 00:00:24 -07:00

49 lines
1.6 KiB
Python

"""Legacy /v1/* mounts for SSO-branch device-flow endpoints. Canonical
handlers live in controllers/openapi/oauth_device/. This file just
re-registers them on the legacy blueprint until Phase F retires the
legacy paths entirely.
Note: /v1/device/sso-complete (no /oauth/ in the path) is the existing
ACS callback. Its canonical home is /openapi/v1/oauth/device/sso-complete.
IdP-side ACS callback URLs need re-registration before Phase F.
"""
from __future__ import annotations
from flask import Blueprint
from controllers.openapi.oauth_device.approval_context import approval_context
from controllers.openapi.oauth_device.approve_external import approve_external
from controllers.openapi.oauth_device.sso_complete import sso_complete
from controllers.openapi.oauth_device.sso_initiate import sso_initiate
from libs.device_flow_security import attach_anti_framing
bp = Blueprint("oauth_device_sso", __name__, url_prefix="/v1")
attach_anti_framing(bp)
# Legacy /v1/* mounts — handlers live in controllers/openapi/oauth_device/.
# Removed in Phase F.
bp.add_url_rule(
"/oauth/device/sso-initiate",
endpoint="sso_initiate",
view_func=sso_initiate,
methods=["GET"],
)
bp.add_url_rule(
"/device/sso-complete",
endpoint="sso_complete",
view_func=sso_complete,
methods=["GET"],
)
bp.add_url_rule(
"/oauth/device/approval-context",
endpoint="approval_context",
view_func=approval_context,
methods=["GET"],
)
bp.add_url_rule(
"/oauth/device/approve-external",
endpoint="approve_external",
view_func=approve_external,
methods=["POST"],
)