[PR #31935] refactor: api/controllers/console/feature.py resolve compatibility issues #33475

Open
opened 2026-02-21 20:53:21 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/langgenius/dify/pull/31935

State: open
Merged: No


Important

  1. Make sure you have read our contribution guidelines
  2. Ensure there is an associated issue and you have been assigned to it
  3. Use the correct syntax to link this PR: Fixes #<issue number>.

Summary

Update load_user_from_request to support FastOpenAPI routes

Change unauthorized_handler to raise exception rather than return Response

Add integration tests to verify authentication flow

Fix return type incompatibility

@asukaminato0721

I have encountered the same issue reported in #31887 and have a proposed solution. I hope this helps.

Here is a detailed description of the problems:

Problem 1: request.blueprint dependency in Authentication Dify's authentication system (at ext_login.py:51) relies on request.blueprint to determine how to load the user. However, for routes registered via FastOpenAPI, request.blueprint is None. As a result, the authentication logic is completely bypassed, and current_user is not loaded.

Problem 2: Incompatible return types in error handling When login_required detects an unauthenticated user (api/libs/login.py:80), the unauthorized_handler (api/extensions/ext_login.py:117-123) returns a standard Flask Response object. Since FastOpenAPI uses orjson for serialization, it fails to serialize the Flask Response object, leading to a TypeError.

The following are the solutions:

Issue 1: Blueprint Registration Issue

In ext_login.py (lines 51-53), the PR adds a path check to support FastOpenAPI routes:

# Before
if request.blueprint in {"console", "inner_api"}:

# After
is_console_api = request.blueprint in {"console", "inner_api"} or request.path.startswith("/console/api/")
if is_console_api:

This ensures that even if request.blueprint is None (which is the case for FastOpenAPI routes), the authentication logic will still execute as long as the path starts with /console/api/.

Issue 2: Serialization Error Caused by Authentication Failure

In api/extensions/ext_login.py (lines 127-131), the unauthorized_handler now raises an exception for FastOpenAPI routes instead of returning a Response object:

# FastOpenAPI routes: Raise exception (serializable by orjson)
if request.blueprint is None and request.path.startswith("/console/api/"):
    raise Unauthorized("Unauthorized.")
# Blueprint routes: Return Response (retain original behavior)
return Response(...

The system-features endpoint is not decorated with @login_required, so it does not trigger the unauthorized_handler. It handles the authentication check via a try-catch block (lines 49-52). When current_user.is_authenticated raises Unauthorized, the exception is caught, and is_authenticated is set to False.

The workflow is as follows:

  • Request without token -> /console/api/system-features

  • The endpoint lacks the @login_required decorator, so execution enters the function body directly.

  • Accessing current_user.is_authenticated triggers load_user_from_request.

  • load_user_from_request raises Unauthorized due to the missing token.

  • The endpoint's try-catch block catches the exception and sets is_authenticated=False.

  • Returns a streamlined system configuration (excluding sensitive license information).

This aligns with the original design, allowing the frontend login page to successfully retrieve SSO/OAuth configurations.

Screenshots

Before After
... ...

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran make lint and make type-check (backend) and cd web && npx lint-staged (frontend) to appease the lint gods
**Original Pull Request:** https://github.com/langgenius/dify/pull/31935 **State:** open **Merged:** No --- > [!IMPORTANT] > > 1. Make sure you have read our [contribution guidelines](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) > 1. Ensure there is an associated issue and you have been assigned to it > 1. Use the correct syntax to link this PR: `Fixes #<issue number>`. ## Summary Update load_user_from_request to support FastOpenAPI routes Change unauthorized_handler to raise exception rather than return Response Add integration tests to verify authentication flow Fix return type incompatibility @asukaminato0721 I have encountered the same issue reported in #31887 and have a proposed solution. I hope this helps. Here is a detailed description of the problems: Problem 1: request.blueprint dependency in Authentication Dify's authentication system (at ext_login.py:51) relies on request.blueprint to determine how to load the user. However, for routes registered via FastOpenAPI, request.blueprint is None. As a result, the authentication logic is completely bypassed, and current_user is not loaded. Problem 2: Incompatible return types in error handling When login_required detects an unauthenticated user (api/libs/login.py:80), the unauthorized_handler (api/extensions/ext_login.py:117-123) returns a standard Flask Response object. Since FastOpenAPI uses orjson for serialization, it fails to serialize the Flask Response object, leading to a TypeError. The following are the solutions: Issue 1: Blueprint Registration Issue In ext_login.py (lines 51-53), the PR adds a path check to support FastOpenAPI routes: ```python # Before if request.blueprint in {"console", "inner_api"}: # After is_console_api = request.blueprint in {"console", "inner_api"} or request.path.startswith("/console/api/") if is_console_api: ``` This ensures that even if request.blueprint is None (which is the case for FastOpenAPI routes), the authentication logic will still execute as long as the path starts with /console/api/. Issue 2: Serialization Error Caused by Authentication Failure In api/extensions/ext_login.py (lines 127-131), the unauthorized_handler now raises an exception for FastOpenAPI routes instead of returning a Response object: ```python # FastOpenAPI routes: Raise exception (serializable by orjson) if request.blueprint is None and request.path.startswith("/console/api/"): raise Unauthorized("Unauthorized.") # Blueprint routes: Return Response (retain original behavior) return Response(... ``` The system-features endpoint is not decorated with @login_required, so it does not trigger the unauthorized_handler. It handles the authentication check via a try-catch block (lines 49-52). When current_user.is_authenticated raises Unauthorized, the exception is caught, and is_authenticated is set to False. The workflow is as follows: - Request without token -> /console/api/system-features - The endpoint lacks the @login_required decorator, so execution enters the function body directly. - Accessing current_user.is_authenticated triggers load_user_from_request. - load_user_from_request raises Unauthorized due to the missing token. - The endpoint's try-catch block catches the exception and sets is_authenticated=False. - Returns a streamlined system configuration (excluding sensitive license information). This aligns with the original design, allowing the frontend login page to successfully retrieve SSO/OAuth configurations. ## Screenshots | Before | After | |--------|-------| | ... | ... | ## Checklist - [ ] This change requires a documentation update, included: [Dify Document](https://github.com/langgenius/dify-docs) - [x] I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!) - [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change. - [x] I've updated the documentation accordingly. - [x] I ran `make lint` and `make type-check` (backend) and `cd web && npx lint-staged` (frontend) to appease the lint gods
yindo added the pull-request label 2026-02-21 20:53:21 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#33475