feat: add Feishu OAuth integration
Implement Feishu OAuth provider using standard client: - Set up Feishu-specific endpoints for authorization, token, and userinfo - Use user_id as sub claim for Feishu user identification - Extract correct user information from nested 'data' field in Feishu responses Configuration requirements: - Set FEISHU_CLIENT_ID and FEISHU_CLIENT_SECRET environment variables to enable Feishu OAuth - Set ENABLE_OAUTH_SIGNUP=true to allow automatic user creation after OAuth login - Set DEFAULT_USER_ROLE=user to grant immediate access after OAuth registration - Set OAUTH_MERGE_ACCOUNTS_BY_EMAIL=true to enable merging of existing user accounts with matching emails
This commit is contained in:
parent
4a76bea80c
commit
ee82439e67
|
@ -1,3 +1,3 @@
|
||||||
export CORS_ALLOW_ORIGIN="http://localhost:5173"
|
export CORS_ALLOW_ORIGIN="http://localhost:5173;http://localhost:8080"
|
||||||
PORT="${PORT:-8080}"
|
PORT="${PORT:-8080}"
|
||||||
uvicorn open_webui.main:app --port $PORT --host 0.0.0.0 --forwarded-allow-ips '*' --reload
|
uvicorn open_webui.main:app --port $PORT --host 0.0.0.0 --forwarded-allow-ips '*' --reload
|
||||||
|
|
|
@ -513,6 +513,30 @@ OAUTH_GROUPS_CLAIM = PersistentConfig(
|
||||||
os.environ.get("OAUTH_GROUPS_CLAIM", os.environ.get("OAUTH_GROUP_CLAIM", "groups")),
|
os.environ.get("OAUTH_GROUPS_CLAIM", os.environ.get("OAUTH_GROUP_CLAIM", "groups")),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
FEISHU_CLIENT_ID = PersistentConfig(
|
||||||
|
"FEISHU_CLIENT_ID",
|
||||||
|
"oauth.feishu.client_id",
|
||||||
|
os.environ.get("FEISHU_CLIENT_ID", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
FEISHU_CLIENT_SECRET = PersistentConfig(
|
||||||
|
"FEISHU_CLIENT_SECRET",
|
||||||
|
"oauth.feishu.client_secret",
|
||||||
|
os.environ.get("FEISHU_CLIENT_SECRET", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
FEISHU_OAUTH_SCOPE = PersistentConfig(
|
||||||
|
"FEISHU_OAUTH_SCOPE",
|
||||||
|
"oauth.feishu.scope",
|
||||||
|
os.environ.get("FEISHU_OAUTH_SCOPE", "contact:user.base:readonly"),
|
||||||
|
)
|
||||||
|
|
||||||
|
FEISHU_REDIRECT_URI = PersistentConfig(
|
||||||
|
"FEISHU_REDIRECT_URI",
|
||||||
|
"oauth.feishu.redirect_uri",
|
||||||
|
os.environ.get("FEISHU_REDIRECT_URI", ""),
|
||||||
|
)
|
||||||
|
|
||||||
ENABLE_OAUTH_ROLE_MANAGEMENT = PersistentConfig(
|
ENABLE_OAUTH_ROLE_MANAGEMENT = PersistentConfig(
|
||||||
"ENABLE_OAUTH_ROLE_MANAGEMENT",
|
"ENABLE_OAUTH_ROLE_MANAGEMENT",
|
||||||
"oauth.enable_role_mapping",
|
"oauth.enable_role_mapping",
|
||||||
|
@ -705,6 +729,32 @@ def load_oauth_providers():
|
||||||
"register": oidc_oauth_register,
|
"register": oidc_oauth_register,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if FEISHU_CLIENT_ID.value and FEISHU_CLIENT_SECRET.value:
|
||||||
|
def feishu_oauth_register(client: OAuth):
|
||||||
|
client.register(
|
||||||
|
name="feishu",
|
||||||
|
client_id=FEISHU_CLIENT_ID.value,
|
||||||
|
client_secret=FEISHU_CLIENT_SECRET.value,
|
||||||
|
access_token_url="https://open.feishu.cn/open-apis/authen/v2/oauth/token",
|
||||||
|
authorize_url="https://accounts.feishu.cn/open-apis/authen/v1/authorize",
|
||||||
|
api_base_url="https://open.feishu.cn/open-apis",
|
||||||
|
userinfo_endpoint="https://open.feishu.cn/open-apis/authen/v1/user_info",
|
||||||
|
client_kwargs={
|
||||||
|
"scope": FEISHU_OAUTH_SCOPE.value,
|
||||||
|
**(
|
||||||
|
{"timeout": int(OAUTH_TIMEOUT.value)}
|
||||||
|
if OAUTH_TIMEOUT.value
|
||||||
|
else {}
|
||||||
|
),
|
||||||
|
},
|
||||||
|
redirect_uri=FEISHU_REDIRECT_URI.value,
|
||||||
|
)
|
||||||
|
|
||||||
|
OAUTH_PROVIDERS["feishu"] = {
|
||||||
|
"register": feishu_oauth_register,
|
||||||
|
"sub_claim": "user_id",
|
||||||
|
}
|
||||||
|
|
||||||
configured_providers = []
|
configured_providers = []
|
||||||
if GOOGLE_CLIENT_ID.value:
|
if GOOGLE_CLIENT_ID.value:
|
||||||
configured_providers.append("Google")
|
configured_providers.append("Google")
|
||||||
|
@ -712,6 +762,8 @@ def load_oauth_providers():
|
||||||
configured_providers.append("Microsoft")
|
configured_providers.append("Microsoft")
|
||||||
if GITHUB_CLIENT_ID.value:
|
if GITHUB_CLIENT_ID.value:
|
||||||
configured_providers.append("GitHub")
|
configured_providers.append("GitHub")
|
||||||
|
if FEISHU_CLIENT_ID.value:
|
||||||
|
configured_providers.append("Feishu")
|
||||||
|
|
||||||
if configured_providers and not OPENID_PROVIDER_URL.value:
|
if configured_providers and not OPENID_PROVIDER_URL.value:
|
||||||
provider_list = ", ".join(configured_providers)
|
provider_list = ", ".join(configured_providers)
|
||||||
|
|
|
@ -602,6 +602,8 @@ class OAuthManager:
|
||||||
or (auth_manager_config.OAUTH_USERNAME_CLAIM not in user_data)
|
or (auth_manager_config.OAUTH_USERNAME_CLAIM not in user_data)
|
||||||
):
|
):
|
||||||
user_data: UserInfo = await client.userinfo(token=token)
|
user_data: UserInfo = await client.userinfo(token=token)
|
||||||
|
if provider == "feishu" and isinstance(user_data, dict) and "data" in user_data:
|
||||||
|
user_data = user_data["data"]
|
||||||
if not user_data:
|
if not user_data:
|
||||||
log.warning(f"OAuth callback failed, user data is missing: {token}")
|
log.warning(f"OAuth callback failed, user data is missing: {token}")
|
||||||
raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
|
raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
|
||||||
|
|
|
@ -523,6 +523,16 @@
|
||||||
>
|
>
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if $config?.oauth?.providers?.feishu}
|
||||||
|
<button
|
||||||
|
class="flex justify-center items-center bg-gray-700/5 hover:bg-gray-700/10 dark:bg-gray-100/5 dark:hover:bg-gray-100/10 dark:text-gray-300 dark:hover:text-white transition w-full rounded-full font-medium text-sm py-2.5"
|
||||||
|
on:click={() => {
|
||||||
|
window.location.href = `${WEBUI_BASE_URL}/oauth/feishu/login`;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{$i18n.t('Continue with {{provider}}', { provider: 'Feishu' })}</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue