lobehub / lobe-chat

🤯 Lobe Chat - an open-source, modern-design AI chat framework. Supports Multi AI Providers( OpenAI / Claude 3 / Gemini / Ollama / Azure / DeepSeek), Knowledge Base (file upload / knowledge management / RAG ), Multi-Modals (Vision/TTS) and plugin system. One-click FREE deployment of your private ChatGPT/ Claude application.
https://chat-preview.lobehub.com
Other
44.6k stars 10k forks source link

[Bug] github鉴权,无法将获取到的用户名和头像传入web前端并显示 #4163

Closed BiFangKNT closed 1 month ago

BiFangKNT commented 1 month ago

📦 部署环境

Docker

📌 软件版本

lobehub/lobe-chat-database:1.19.34

💻 系统环境

Other Linux

🌐 浏览器

Chrome

🐛 问题描述

github鉴权,无法将获取到的用户名和头像传入web前端,只能将获取到邮箱作为用户名,头像则为默认占位符。

我通过脚本确认了通过使用和项目本身给出的实现相同的接口获取方法,我的github api是能获取到用户名和头像的。既然接口获取方法没问题,我的api也没问题,那么应该是在把获取到的用户名和头像传递到web前端的相应绑定点中的这个过程里出现了问题吧

测试脚本如下:

import os
import requests
from flask import Flask, redirect, request, url_for

app = Flask(__name__)

# 配置你的 GitHub OAuth App 的 client_id 和 client_secret
CLIENT_ID = 'your_github_client_id'
CLIENT_SECRET = 'your_github_client_secret'
# 回调 URL,必须与 GitHub OAuth App 的设置一致
REDIRECT_URI = 'http://127.0.0.1:5000/callback'

# GitHub 授权 URL
AUTH_URL = f'https://github.com/login/oauth/authorize?client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&scope=read:user%20user:email'

# GitHub 获取访问令牌的 URL
TOKEN_URL = 'https://github.com/login/oauth/access_token'
# GitHub 用户信息 API
USER_API_URL = 'https://api.github.com/user'

# 第一步:重定向到 GitHub 授权页面
@app.route('/')
def index():
    return redirect(AUTH_URL)

# 第二步:处理 GitHub 的回调,接收授权码并用它换取访问令牌
@app.route('/callback')
def callback():
    code = request.args.get('code')  # GitHub 返回的授权码

    if not code:
        return "Error: No code provided"

    # 第三步:使用授权码请求 GitHub 的访问令牌
    token_response = requests.post(TOKEN_URL, headers={'Accept': 'application/json'}, data={
        'client_id': CLIENT_ID,
        'client_secret': CLIENT_SECRET,
        'code': code,
        'redirect_uri': REDIRECT_URI,
    })

    if token_response.status_code != 200:
        return f"Error getting token: {token_response.text}"

    # 从响应中提取访问令牌
    token_json = token_response.json()
    access_token = token_json.get('access_token')

    if not access_token:
        return "Error: No access token found"

    # 第四步:使用访问令牌请求 GitHub 用户信息
    user_response = requests.get(USER_API_URL, headers={
        'Authorization': f'token {access_token}',
        'Accept': 'application/json',
    })

    if user_response.status_code != 200:
        return f"Error fetching user info: {user_response.text}"

    # 返回用户信息
    user_info = user_response.json()
    return f"User Info: {user_info}"

if __name__ == '__main__':
    # 在本地运行应用
    app.run(debug=True)

相关讨论: #4116

📷 复现步骤

数据库版,使用github鉴权,登录。

🚦 期望结果

web前端正常显示对应github账户的用户名和头像

📝 补充信息

github app只开放了邮箱权限,用户名和头像是公开访问的,不用额外授权。

lobehubbot commented 1 month ago

👀 @BiFangKNT

Thank you for raising an issue. We will investigate into the matter and get back to you as soon as possible. Please make sure you have given us as much context as possible.\ 非常感谢您提交 issue。我们会尽快调查此事,并尽快回复您。 请确保您已经提供了尽可能多的背景信息。

dosubot[bot] commented 1 month ago

I found a similar unsolved discussion regarding GitHub login and retrieving the username and avatar: 希望github登录能获取到用户名和头像 [1].

To resolve the issue where GitHub authentication fails to pass the retrieved username and avatar to the web frontend, ensure that the username prop is correctly passed to the GitHubAvatar component. Here is the GitHubAvatar component for reference:

import { Avatar, type AvatarProps } from '@lobehub/ui';
import qs from 'query-string';
import { memo } from 'react';
import urlJoin from 'url-join';

interface GitHubAvatarProps extends Omit<AvatarProps, 'avatar'> {
  username: string;
}

const GitHubAvatar = memo<GitHubAvatarProps>(({ username, size = 24 }) => {
  const url = qs.stringifyUrl({
    query: { size: size * 2 },
    url: urlJoin('https://github.com', `${username}.png`),
  });

  return <Avatar alt={username} avatar={url} size={size} />;
});

export default GitHubAvatar;

Ensure that when you use the GitHubAvatar component, you are passing the correct username prop. For example:

<GitHubAvatar username={retrievedUsername} size={48} />

If retrievedUsername is not correctly set, the avatar URL will not be correctly constructed, leading to the default placeholder being displayed. Similarly, ensure that the retrievedUsername is correctly fetched and stored in your application state before being passed to the GitHubAvatar component [2].

Additionally, verify that the GitHub provider configuration in your authentication setup is correctly mapping the profile fields. Here is an example configuration using next-auth:

import GitHub from 'next-auth/providers/github';

import { authEnv } from '@/config/auth';

import { CommonProviderConfig } from './sso.config';

const provider = {
  id: 'github',
  provider: GitHub({
    ...CommonProviderConfig,
    authorization: { params: { scope: 'read:user user:email' } },
    clientId: authEnv.GITHUB_CLIENT_ID ?? process.env.AUTH_GITHUB_ID,
    clientSecret: authEnv.GITHUB_CLIENT_SECRET ?? process.env.AUTH_GITHUB_SECRET,
    profile: (profile) => {
      return {
        email: profile.email,
        id: profile.id.toString(),
        image: profile.avatar_url,
        name: profile.name,
        providerAccountId: profile.id.toString(),
      };
    },
  }),
};

export default provider;

Ensure that the profile function correctly maps the name and image fields from the GitHub profile to the corresponding fields in your application. This will ensure that the username and avatar are correctly retrieved and passed to the frontend [3].

There are also middleware or hooks in place that modify or handle the user data retrieved from GitHub before it reaches the frontend. Specifically, the jwt and session callbacks in Auth.js are used to process and customize the user information:

callbacks: {
  async jwt({ token, account, profile }) {
    if (account) {
      token.userId = account.providerAccountId;
    }
    return token;
  },
  async session({ session, token }) {
    if (session.user) {
      session.user.id = token.userId ?? session.user.id;
    }
    return session;
  },
}

Additionally, the profile function in the GitHub provider configuration shapes the user profile data retrieved from GitHub [4].

For error handling and logging, the AuthErrorPage.tsx file logs errors related to authentication using console.log:

console.log('[NextAuth] Error:', props.error);

This logging can provide insights into why the username and avatar are not being passed correctly to the frontend by capturing and displaying relevant error information [5].

To continue talking to Dosu, mention @dosu.

cy948 commented 1 month ago

有尝试过使用一个空的数据库去复现这个bug吗?

lobehubbot commented 1 month ago

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Have you tried using an empty database to reproduce this bug?

BiFangKNT commented 1 month ago

有尝试过使用一个空的数据库去复现这个bug吗?

试过了,发现是Cloudflare Zero Trust的问题,空数据库首先使用github原生鉴权的话没问题。请问前者该怎么设置才能显示连接的github账户的用户名和头像?

lobehubbot commented 1 month ago

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Have you tried using an empty database to reproduce this bug?

I tried it and found that it was a problem with Cloudflare Zero Trust. If the empty database first uses github native authentication, there will be no problem. How can I set the former to display the username and avatar of the connected github account?

cy948 commented 1 month ago

试过了,发现是Cloudflare Zero Trust的问题,空数据库首先使用github原生鉴权的话没问题。请问前者该怎么设置才能显示连接的github账户的用户名和头像?

@hezhijie0327 大佬可以帮忙看看这个问题嘛?

lobehubbot commented 1 month ago

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


I tried it and found that it is a problem with Cloudflare Zero Trust. If the empty database first uses github native authentication, there will be no problem. How can I set the former to display the username and avatar of the connected github account?

@hezhijie0327 Can you guys help me figure this out?

hezhijie0327 commented 1 month ago

Cloudflare Zero Trust 不支持返回头像参数,这个问题我印象里在哪个 PR 也提到过 现在数据库好像存在键值的话后续就不更新了

https://github.com/lobehub/lobe-chat/pull/3647#issuecomment-2314571062

lobehubbot commented 1 month ago

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Cloudflare Zero Trust does not support returning avatar parameters. I remember this problem was mentioned in a PR. Now it seems that if the key value exists in the database, it will not be updated in the future.

BiFangKNT commented 1 month ago

Cloudflare Zero Trust 不支持返回头像参数,这个问题我印象里在哪个 PR 也提到过 现在数据库好像存在键值的话后续就不更新了

啊这,看来只能先用github原生注册了。现在lobe不支持导出聊天记录,也懒得进数据库里改,看来只能慢慢等了

lobehubbot commented 1 month ago

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Cloudflare Zero Trust does not support returning avatar parameters. I remember this problem was mentioned in a PR. Now it seems that if the database has a key value, it will not be updated later.

Ah, it seems that I can only register natively with github first. Now Lobe does not support exporting chat records, and I am too lazy to change it in the database. It seems that I can only wait slowly.

cy948 commented 1 month ago
lobehubbot commented 1 month ago

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


  • Data migration when sso is replaced: When sso is replaced, it will first check whether there are users with the same email address and link the new sso account to the existing users.
  • Webhook synchronization of avatar, email and other information: Currently, the webhooks of casdoor and logto are supported. When the user information is updated in the administrator panel of the above two providers, the user information in the lobe database will be updated simultaneously.