Add enterprise level LDAP authentication

This commit is contained in:
xxlaila 2025-03-11 14:51:22 +08:00
parent 785e83b221
commit d1ed6ddd9d
5 changed files with 17 additions and 15 deletions

View File

@ -38,7 +38,6 @@ def create_app() -> DifyApp:
def initialize_extensions(app: DifyApp): def initialize_extensions(app: DifyApp):
from extensions import ( from extensions import (
ext_ldap,
ext_app_metrics, ext_app_metrics,
ext_blueprints, ext_blueprints,
ext_celery, ext_celery,
@ -48,6 +47,7 @@ def initialize_extensions(app: DifyApp):
ext_database, ext_database,
ext_hosting_provider, ext_hosting_provider,
ext_import_modules, ext_import_modules,
ext_ldap,
ext_logging, ext_logging,
ext_login, ext_login,
ext_mail, ext_mail,

View File

@ -5,10 +5,10 @@ from pydantic.fields import FieldInfo
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict
from .deploy import DeploymentConfig from .deploy import DeploymentConfig
from .ldap import AuthenticationConfig
from .enterprise import EnterpriseFeatureConfig from .enterprise import EnterpriseFeatureConfig
from .extra import ExtraServiceConfig from .extra import ExtraServiceConfig
from .feature import FeatureConfig from .feature import FeatureConfig
from .ldap import AuthenticationConfig
from .middleware import MiddlewareConfig from .middleware import MiddlewareConfig
from .packaging import PackagingInfo from .packaging import PackagingInfo
from .remote_settings_sources import RemoteSettingsSource, RemoteSettingsSourceConfig, RemoteSettingsSourceName from .remote_settings_sources import RemoteSettingsSource, RemoteSettingsSourceConfig, RemoteSettingsSourceName

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
@File : __init__.py.py @File : __init__.py.py
@Time : 2025/3/6 {TIME} @Time : 2025/3/6 {TIME}
@ -8,6 +7,7 @@
from pydantic import Field from pydantic import Field
from pydantic_settings import BaseSettings from pydantic_settings import BaseSettings
class AuthenticationConfig(BaseSettings): class AuthenticationConfig(BaseSettings):
"""LDAP authentication related configuration""" """LDAP authentication related configuration"""
# LDAP Authentication # LDAP Authentication

View File

@ -1,17 +1,19 @@
# -*- coding: utf-8 -*-
""" """
@File : ext_ldap.py @File : ext_ldap.py
@Time : 2025/3/5 {TIME} @Time : 2025/3/5 {TIME}
@Author : xxlaila @Author : xxlaila
@Software: dify @Software: dify
""" """
from flask_ldap3_login import LDAP3LoginManager
from configs import dify_config
from dify_app import DifyApp
import json import json
import logging import logging
from queue import Queue from queue import Queue
from ldap3 import Server, Connection, ALL
from flask_ldap3_login import LDAP3LoginManager
from ldap3 import ALL, Connection, Server
from configs import dify_config
from dify_app import DifyApp
def is_enabled(): def is_enabled():
return getattr(dify_config, 'LDAP_ENABLED', False) return getattr(dify_config, 'LDAP_ENABLED', False)
@ -54,7 +56,7 @@ def get_ldap_connection():
return new_conn return new_conn
raise Exception("LDAP connection reconstruction failed") raise Exception("LDAP connection reconstruction failed")
except Exception as e: except Exception as e:
logging.error(f"LDAP connection recovery failed: {str(e)}") logging.exception(f"LDAP connection recovery failed: {e}")
raise raise
return conn return conn
@ -67,7 +69,7 @@ def release_ldap_connection(conn):
conn.open() # Reopen connection without binding conn.open() # Reopen connection without binding
LDAP_POOL.put(conn) LDAP_POOL.put(conn)
except Exception as e: except Exception as e:
logging.error(f"Failed to recycle LDAP connection: {str(e)}") logging.exception(f"Failed to recycle LDAP connection: {str(e)}")
conn.unbind() conn.unbind()
def init_app(app: DifyApp): def init_app(app: DifyApp):

View File

@ -8,6 +8,8 @@ from datetime import UTC, datetime, timedelta
from hashlib import sha256 from hashlib import sha256
from typing import Any, Optional, cast from typing import Any, Optional, cast
from flask import current_app as app
from ldap3 import Connection, Server
from pydantic import BaseModel from pydantic import BaseModel
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@ -17,6 +19,7 @@ from configs import dify_config
from constants.languages import language_timezone_mapping, languages from constants.languages import language_timezone_mapping, languages
from events.tenant_event import tenant_was_created from events.tenant_event import tenant_was_created
from extensions.ext_database import db from extensions.ext_database import db
from extensions.ext_ldap import get_ldap_connection, release_ldap_connection
from extensions.ext_redis import redis_client from extensions.ext_redis import redis_client
from libs.helper import RateLimiter, TokenManager from libs.helper import RateLimiter, TokenManager
from libs.passport import PassportService from libs.passport import PassportService
@ -57,10 +60,7 @@ from tasks.mail_account_deletion_task import send_account_deletion_verification_
from tasks.mail_email_code_login import send_email_code_login_mail_task from tasks.mail_email_code_login import send_email_code_login_mail_task
from tasks.mail_invite_member_task import send_invite_member_mail_task from tasks.mail_invite_member_task import send_invite_member_mail_task
from tasks.mail_reset_password_task import send_reset_password_mail_task from tasks.mail_reset_password_task import send_reset_password_mail_task
from extensions.ext_ldap import get_ldap_connection, release_ldap_connection
from ldap3 import Server, Connection, ALL
from flask import current_app as app
class TokenPair(BaseModel): class TokenPair(BaseModel):
access_token: str access_token: str
@ -217,7 +217,7 @@ class AccountService:
finally: finally:
release_ldap_connection(conn) release_ldap_connection(conn)
except Exception as e: except Exception as e:
logging.error(f"LDAP authentication error: {str(e)}") logging.exception(f"LDAP authentication error: {str(e)}")
# Perform local authentication only if LDAP authentication explicitly fails # Perform local authentication only if LDAP authentication explicitly fails
if not is_ldap_success: if not is_ldap_success:
@ -303,7 +303,7 @@ class AccountService:
except Exception as e: except Exception as e:
db.session.rollback() # Transaction rollback to prevent database pollution db.session.rollback() # Transaction rollback to prevent database pollution
logging.error(f"Failed to create LDAP user or add to tenant: {str(e)}") logging.exception(f"Failed to create LDAP user or add to tenant: {str(e)}")
raise AccountRegisterError("Failed to create LDAP user.") raise AccountRegisterError("Failed to create LDAP user.")
@staticmethod @staticmethod