chainlit身份验证方案oauth2.0及常用社交应用账户集成

chainlit身份验证方案oauth2.0及常用社交应用账户集成

阅读原文

建议阅读原文,始终查看最新文档版本,获得最佳阅读体验:《chainlit身份验证方案oauth2.0及常用社交应用账户集成》

本文摘要

本文详细说明了如何将chainlit与Microsoft AD(LDAP)集成,以便于企业用户通过域账号登录到chainlit,另外,还简要介绍了两个功能类似的开源项目lobechat和librechat。

chainlit简介

官网:Overview - Chainlit

github网址:Chainlit/chainlit: Build Conversational AI in minutes ⚡️

chainlit是一个用于快速构建AI对话式聊天机器人的开源python库,其最大的特点是,可以很方便的构建类似于chatGPT那样的前端页面

请至钉钉文档查看附件《chainlit演示视频.mp4》

类似的开源项目

Lobe Chat

lobe-chat/README.zh-CN.md at main · lobehub/lobe-chat

LobeHub - LobeChat:个人 LLM 效能工具,超越 ChatGPT / OLLaMA 使用体验

lobechat是现代化设计的开源 ChatGPT/LLMs 聊天应用与开发框架支持语音合成、多模态、可扩展的(function call)插件系统,一键免费拥有你自己的 ChatGPT/Gemini/Claude/Ollama 应用

lobechat也是支持OAuth2.0的

lobechat的github stars数远高于librechat和chainlit,高达6万多。

请至钉钉文档查看附件《lobechat演示视频.webm》

LibreChat

librechat.ai/docs        danny-avila/LibreChat: Enhanced ChatGPT Clone: Features Agents, DeepSeek, Anthropic, AWS, OpenAI, Assistants API, Azure, Groq, o1, GPT-4o, Mistral, OpenRouter, Vertex AI, Gemini, Artifacts, AI model switching, message search, Code Interpreter, langchain, DALL-E-3, OpenAPI Actions, Functions, Secure Multi-User Auth, Presets, open-source for self-hosting. Active project.

官方介绍视频:https://youtu.be/ilfwGQtJNlI

LibreChat 是一款面向所有人工智能对话的终极开源应用程序,它完全可定制且兼容任何AI服务提供商——所有这些功能都集成在一个时尚流畅的界面中

LibreChat原生支持LDAP,同时也支持OAuth2.0

image.png

chainlit支持的身份验证提供商

参考资料:Overview - Chainlit

chainlit支持这三种身份认证方式:

image.png

其中OAuth又包括了以下几种,可以看到,支持的OAuth providers是非常多的,几乎包含了所有的社交账号,而keycloak本身也支持很多平台。

image.png

安装chainlit

参考资料:Installation - Chainlit

Linux系统

首先要安装python和pip,此过程省略

注意,下面几行命令是在ubuntu desktop 24.04系统上运行的,Windows系统命令有所区别

#创建虚拟环境
python3 -m venv chainlit
#激活虚拟环境
source ./chainlit/bin/activate
#用pip安装chainlit包
pip install --upgrade chainlit

image.png

image.png

Windows系统,trae(vs code)

先通过trae(用vs code或cursor也是可以的)创建一个空的app.py文件,然后通过命令面板创建虚拟环境

image.png

成功创建虚拟环境后,就可以在资源管理中看到自动生成了.env文件夹

image.png

激活虚拟环境

.venv\Scripts\activate

image.png

检查当前python解释器是不是虚拟环境中的解释器,如果不是,务必选择虚拟环境中的解释器

image.png

用pip安装chainlit包,时间会比较长,因为国内下载包会比较慢

pip install --upgrade chainlit

用github验证身份

创建一个github app

参考资料:OAuth - Chainlit

注册 GitHub 应用 - GitHub 文档

点击此链接,然后创建一个github app

下图是我已经创建好的一个github app

关键是callback url、client secret(可以直接生成)

Request user authorization (OAuth) during installation这个一定要勾选。

webhook不用勾选

private key也是必须的,直接生成即可,网页会提示的

image.png

安装github app

注册好github app后,还要安装此github app,很简单,点击install app,然后右侧会显示待安装和已安装的github app,下图是我已经安装的github app

image.png

验证

启动chainlit app

chainlit run .\text_to_SQL.py -d -w

text_to_SQL.py代码如下:

import os
from openai import AsyncOpenAI
from chainlit.oauth_providers import OAuthProvider
import chainlit as cl

import httpx
from fastapi import HTTPException
from chainlit.user import User

import json
cl.instrument_openai()

""" import os

# 手动加载.env文件
from dotenv import load_dotenv
load_dotenv() """

# 打印环境变量
""" print(os.getenv("OAUTH_KEYCLOAK_BASE_URL"))
print(os.getenv("OAUTH_KEYCLOAK_REALM"))
print(os.getenv("OAUTH_KEYCLOAK_CLIENT_ID"))
print(os.getenv("OAUTH_KEYCLOAK_CLIENT_SECRET"))
print(os.getenv("OAUTH_KEYCLOAK_NAME")) """

#user_env = cl.user_session.get("env") #从.env文件中获取环境变量
# 从环境变量中获取API KEY
api_key = os.getenv("OPENAI_API_KEY")
api_key = "<此处替换为你的api_key>"
print(os.getenv("OPENAI_API_KEY")) 

if api_key is None:
    raise ValueError("OPENAI_API_KEY environment variable is not set.")

client = AsyncOpenAI(
    api_key=api_key,
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)


# 优化后的模板,让指令更清晰
template = """SQL tables (and columns):
* Customers(customer_id, signup_date)
* Streaming(customer_id, video_id, watch_date, watch_minutes)

Generate a well - written SQL query to {input} and return the query wrapped in triple backticks (```):
```"""


settings = {
   
   
    "model": "qwen-plus",
    "temperature": 0,
    "max_tokens": 500,
    "top_p": 1,
    "frequency_penalty": 0,
    "presence_penalty": 0,
    # 可以尝试去掉 stop 参数
    # "stop": ["```"],
}



@cl.set_starters
async def starters():
    return [
       cl.Starter(
           label=">50 minutes watched",
           message="Compute the number of customers who watched more than 50 minutes of video this month."
       )
    ]

@cl.on_message
async def main(message: cl.Message):
    try:
        stream = await client.chat.completions.create(
            messages=[
                {
   
   
                    "role": "user",
                    "content": template.format(input=message.content),
                }
            ], stream=True, **settings
        )

        msg = await cl.Message(content="", language="sql").send()

        async for part in stream:
            if token := part.choices[0].delta.content or "":
                await msg.stream_token(token)

        await msg.update()
    except Exception as e:
        # 打印详细的错误信息
        print(f"Error occurred: {
     
     e}")
        error_msg = await cl.Message(content=f"An error occurred: {
     
     e}").send()


from typing import Dict, Optional



@cl.oauth_callback
def oauth_callback(
  provider_id: str,
  token: str,
  raw_user_data: Dict[str, str],
  default_user: cl.User,
) -> Optional[cl.User]:
  return default_user

.env文件如下

image.png

DASHSCOPE_API_KEY=<此处替换为你的api_key>
OPENAI_API_KEY=<此处替换为你的api_key>
#下面的环境变量值,可以在github app中查到
OAUTH_GITHUB_CLIENT_ID=<此处替换为你的GITHUB_CLIENT_ID>
OAUTH_GITHUB_CLIENT_SECRET=<此处替换为你的GITHUB_CLIENT_SECRET>

会自动打开默认浏览器,自动打开网页,网址为http://localhost:8000

如下图,点击“继续使用github”,然后会跳转到github的登录界面,提示需要授权,完成授权后,网页会自动跳转回chainlit页面

image.png

可以看到,成功登录了

image.png

问聊天机器人,也输出了回答

image.png

下面是chainlit部分日志

2025-06-11 11:13:30 - HTTP Request: GET https://api.github.com/user "HTTP/1.1 200 OK"
2025-06-11 11:13:31 - HTTP Request: GET https://api.github.com/user/emails "HTTP/1.1 200 OK"
INFO:     127.0.0.1:60250 - "GET /auth/oauth/github/callback?code=c57134e83b9aa8f9411b&state=im0fiESYJ7wlUrS%24%2FpJ%40t%40%3ER03DsRQRG HTTP/1.1" 302 Found
INFO:     127.0.0.1:60250 - "GET /login/callback?success=True HTTP/1.1" 200 OK
INFO:     127.0.0.1:60250 - "GET /auth/config HTTP/1.1" 200 OK
INFO:     127.0.0.1:60249 - "GET /user HTTP/1.1" 200 OK
INFO:     127.0.0.1:60252 - "GET /project/translations?language=zh-CN& HTTP/1.1" 200 OK
2025-06-11 11:13:31 - Translated markdown file for zh-CN not found. Defaulting to chainlit.md.
INFO:     127.0.0.1:60252 - "GET /project/settings?language=zh-CN& HTTP/1.1" 200 OK
INFO:     127.0.0.1:60252 - "POST /set-session-cookie HTTP/1.1" 200 OK
INFO:     127.0.0.1:60252 - "GET /ws/socket.io/?EIO=4&transport=polling&t=PTS-eSY HTTP/1.1" 200 OK
INFO:     127.0.0.1:60252 - "POST /ws/socket.io/?EIO=4&transport=polling&t=PTS-eSk&sid=BhVCTPSnvJ-ahsFyAAAE HTTP/1.1" 200 OK
INFO:     127.0.0.1:60249 - "GET /ws/socket.io/?EIO=4&transport=polling&t=PTS-eSl&sid=BhVCTPSnvJ-ahsFyAAAE HTTP/1.1" 200 OK
INFO:     127.0.0.1:60249 - "POST /ws/socket.io/?EIO=4&transport=polling&t=PTS-eTB&sid=BhVCTPSnvJ-ahsFyAAAE HTTP/1.1" 200 OK
INFO:     127.0.0.1:60252 - "GET /ws/socket.io/?EIO=4&transport=polling&t=PTS-eTA&sid=BhVCTPSnvJ-ahsFyAAAE HTTP/1.1" 200 OK
INFO:     127.0.0.1:60252 - "GET /ws/socket.io/?EIO=4&transport=polling&t=PTS-eTd&sid=BhVCTPSnvJ-ahsFyAAAE HTTP/1.1" 200 OK
INFO:     ('127.0.0.1', 60344) - "WebSocket /ws/socket.io/?EIO=4&transport=websocket&sid=BhVCTPSnvJ-ahsFyAAAE" [accepted]
INFO:     127.0.0.1:60252 - "GET /ws/socket.io/?EIO=4&transport=polling&t=PTS-eTm&sid=BhVCTPSnvJ-ahsFyAAAE HTTP/1.1" 200 OK
INFO:     127.0.0.1:60452 - "GET /user HTTP/1.1" 200 OK
INFO:     127.0.0.1:60453 - "GET /project/translations?language=zh-CN& HTTP/1.1" 200 OK
INFO:     127.0.0.1:60456 - "GET /user HTTP/1.1" 200 OK
INFO:     127.0.0.1:60456 - "GET /project/translations?language=zh-CN& HTTP/1.1" 200 OK
INFO:     127.0.0.1:60484 - "GET /user HTTP/1.1" 200 OK
INFO:     127.0.0.1:60484 - "GET /project/translations?language=zh-CN& HTTP/1.1" 200 OK
INFO:     127.0.0.1:60529 - "GET /user HTTP/1.1" 200 OK
INFO:     127.0.0.1:60529 - "GET /project/translations?language=zh-CN& HTTP/1.1" 200 OK
INFO:     127.0.0.1:60629 - "GET /user HTTP/1.1" 200 OK
INFO:     127.0.0.1:60630 - "GET /project/translations?language=zh-CN& HTTP/1.1" 200 OK
2025-06-11 11:14:44 - HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions "HTTP/1.1 200 OK"
INFO:     127.0.0.1:60630 - "GET /user HTTP/1.1" 200 OK

关于https的特别说明

github的安全策略要求生产环境下,callback url必须使用https

但是开发环境下,可以使用http,不过callback url中的ip地址必须是localhost或127.0.0.1

image.png

keycloak–LDAP

部署keycloak

最简单的方法是用docker部署

docker run -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin --dns=192.168.124.7 docker.1ms.run/keycloak/keycloak:26.2.5 start-dev

注意,这种方式,只适用于实验环境,生产环境尽量用helm部署,且必须用https

添加一个LDAP provider

访问keycloak,网址为:http://your_serverIP:8080

默认的用户名和密码都是admin

image.png

下面是一个示例:

screencapture-172-16-0-9-8080-admin-master-console-2025-03-13-10_51_31.png

验证ldap连接性

image.pngimage.png

创建一个新的client

image.pngimage.png

参考资料:OAuth - Chainlit

官方文档,对于redirect URLs的说明如下,其实关键是callback前的字符,这个是可以自定义的,我设置的是chainlit-keycloak

You have the option of changing the id of your Keycloak provider, which by default is keycloak. This is useful if you want to display a more appropriate name on your login page. Use the OAUTH_KEYCLOAK_NAME environment variable to set the name. Don’t choose an id that conflicts with any of the other Oauth providers.

The callback URL for your client should be: CHAINLIT_URL/auth/oauth/ O A U T H _ K E Y C L O A K _ N A M E / c a l l b a c k .   I f   y o u r   C h a i n l i t   a p p   i s   h o s t e d   a t   l o c a l h o s t : 8000 ,   y o u   s h o u l d   u s e [ h t t p : / / l o c a l h o s t : 8000 / a u t h / o a u t h / {OAUTH\_KEYCLOAK\_NAME}/callback. If your Chainlit app is hosted at localhost:8000, you should use[http://localhost:8000/auth/oauth/ OAUTH_K

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值