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
40.96k stars 9.34k forks source link

[Bug] [TRPCError]: UNAUTHORIZED - docker + auth0/github App + 腾讯 COS #4023

Open eachann1024 opened 2 days ago

eachann1024 commented 2 days ago

📦 Environment

Docker

📌 Version

latest

💻 Operating System

macOS, Ubuntu

🌐 Browser

Chrome, Other

🐛 Bug Description

| 基于 docker + postgres + lobechat 部署

CleanShot 2024-09-19 at 17 27 00@2x

一开始使用的是 github app , 后来出现 [TRPCError]: UNAUTHORIZED 错误之后, 更换 auth0,跟着文档来配置,也是不行


I started using the github app, but after getting a [TRPCError]: UNAUTHORIZED error, I replaced auth0 and followed the docs, but it didn't work either.

CleanShot 2024-09-19 at 17 28 05@2x

version: '3.8'

services:
  postgres:
    image: pgvector/pgvector:pg16
    container_name: Postgres
    restart: always
    ports:
      - '5432:5432' 
    volumes:
      - /postgres/data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: admin # 设置 Postgres 的用户名
      POSTGRES_PASSWORD: 123456 # 设置 Postgres 的密码
      POSTGRES_DB: lobechat # 设置默认数据库名称
      POSTGRES_HOST_AUTH_METHOD: trust
    command:
      - 'postgres'
      - '-c'
      - 'listen_addresses=*'

  # LobeChat 应用服务
  lobechat:
    image: lobehub/lobe-chat-database:latest
    container_name: LobeChatDB
    restart: always
    ports:
      - '3210:3210'
    depends_on:
      - postgres
    environment:
      APP_URL: 'https://chat.xxxx'
      DATABASE_URL: postgres://admin:123456@postgres/lobechat
      KEY_VAULTS_SECRET: 'xxx'
      # 腾讯 COS 配置
      # S3_ACCESS_KEY_ID: 'xxx'
      # S3_SECRET_ACCESS_KEY: 'xxx'
      # S3_BUCKET: 'xxx'
      # S3_REGION: 'ap-guangzhou'
      # S3_ENDPOINT: 'https://cos.ap-guangzhou.myqcloud.com'
      # S3_PUBLIC_DOMAIN: 'xxx'
      # Auth0配置
      NEXT_AUTH_SSO_PROVIDERS: 'auth0'
      AUTH_AUTH0_ID: 'xxx'
      AUTH_AUTH0_SECRET: 'xxx'
      AUTH_AUTH0_ISSUER: 'https://chat.xxxx/api/auth/callback/auth0'
      ACCESS_CODE: 'xxx'
    volumes:
      - /LobeChatDB/app/data:/app/data

# 定义内部网络(可选)
networks:
  default:
    driver: bridge

📷 Recurrence Steps

No response

🚦 Expected Behavior

No response

📝 Additional Information

No response

lobehubbot commented 2 days ago

👀 @eachann1024

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。我们会尽快调查此事,并尽快回复您。 请确保您已经提供了尽可能多的背景信息。

lobehubbot commented 2 days ago

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


📦 Environment

Docker

📌 Version

latest

💻 Operating System

macOS, Ubuntu

🌐 Browser

Chrome, Other

🐛 Bug Description

| Deployed based on docker + postgres + lobechat

CleanShot 2024-09-19 at 17 27 00@2x

I used github app at the beginning. Later, after the [TRPCError]: UNAUTHORIZED error occurred, I changed auth0 and followed the documentation to configure it, but it didn't work either.


I started using the github app, but after getting a [TRPCError]: UNAUTHORIZED error, I replaced auth0 and followed the docs, but it didn't work either.

CleanShot 2024-09-19 at 17 28 05@2x

version: '3.8'

services:
  postgres:
    image: pgvector/pgvector:pg16
    container_name: Postgres
    restart: always
    ports:
      - '5432:5432'
    volumes:
      -/postgres/data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: admin #Set Postgres username
      POSTGRES_PASSWORD: 123456 #Set the password for Postgres
      POSTGRES_DB: lobechat #Set the default database name
      POSTGRES_HOST_AUTH_METHOD: trust
    command:
      - 'postgres'
      - '-c'
      - 'listen_addresses=*'

  #LobeChat App Service
  lobechat:
    image: lobehub/lobe-chat-database:latest
    container_name: LobeChatDB
    restart: always
    ports:
      - '3210:3210'
    depends_on:
      -postgres
    environment:
      APP_URL: 'https://chat.xxxx'
      DATABASE_URL: postgres://admin:123456@postgres/lobechat
      KEY_VAULTS_SECRET: 'xxx'
      # Tencent COS configuration
      # S3_ACCESS_KEY_ID: 'xxx'
      # S3_SECRET_ACCESS_KEY: 'xxx'
      # S3_BUCKET: 'xxx'
      # S3_REGION: 'ap-guangzhou'
      # S3_ENDPOINT: 'https://cos.ap-guangzhou.myqcloud.com'
      # S3_PUBLIC_DOMAIN: 'xxx'
      # Auth0 configuration
      NEXT_AUTH_SSO_PROVIDERS: 'auth0'
      AUTH_AUTH0_ID: 'xxx'
      AUTH_AUTH0_SECRET: 'xxx'
      AUTH_AUTH0_ISSUER: 'https://chat.xxxx/api/auth/callback/auth0'
      ACCESS_CODE: 'xxx'
    volumes:
      - /LobeChatDB/app/data:/app/data

# Define internal network (optional)
networks:
  default:
    driver:bridge

📷 Recurrence Steps

No response

🚦 Expected Behavior

No response

📝 Additional Information

No response

eachann1024 commented 2 days ago

论坛找了好几次, 没看到合适的解决方案 I've searched the forums a few times, but haven't seen a suitable solution.

dosubot[bot] commented 2 days ago

@eachann1024 你好! 我是Dosu,我是一个能够帮助您解决bug,回答问题并成为贡献者的机器人。我会在等待人类维护者的过程中为您提供帮助。

I found a similar solved discussion that might help you with your issue: [HELP] Deploying Lobe-Chat with Server-Side Persistence and SSO | 部署带服务器端持久化和SSO的Lobe-Chat. This discussion addresses deployment issues and provides a detailed tutorial for setting up the environment [1].

To resolve the [TRPCError]: UNAUTHORIZED error in your Next.js application when using Docker with Auth0/GitHub App and Tencent COS, you need to ensure that the ctx.userId is correctly set in your context. The error occurs because ctx.userId is null or undefined.

Here is the relevant code snippet from src/libs/trpc/middleware/userAuth.ts:

import { TRPCError } from '@trpc/server';

import { enableClerk } from '@/const/auth';

import { trpc } from '../init';

export const userAuth = trpc.middleware(async (opts) => {
  const { ctx } = opts;
  // `ctx.user` is nullable
  if (!ctx.userId) {
    if (enableClerk) {
      console.log('clerk auth:', ctx.clerkAuth);
    } else {
      console.log('next auth:', ctx.nextAuth);
    }
    throw new TRPCError({ code: 'UNAUTHORIZED' });
  }

  return opts.next({
    ctx: {
      // ✅ user value is known to be non-null now
      userId: ctx.userId,
    },
  });
});

To fix this issue, you need to ensure that the authentication middleware correctly sets ctx.userId. This typically involves verifying the authentication token and extracting the user ID from it. Here are some steps you can follow:

  1. Verify Authentication Token: Ensure that the authentication token from Auth0/GitHub App is being correctly verified.
  2. Extract User ID: Extract the user ID from the verified token and set it in the context (ctx.userId).

Here is an example of how you might modify the middleware to include token verification and user ID extraction, using the getJWTPayload utility function:

import { TRPCError } from '@trpc/server';
import { getJWTPayload } from '@/app/api/middleware/auth/utils'; // Adjust the import path as necessary

import { enableClerk } from '@/const/auth';
import { trpc } from '../init';

export const userAuth = trpc.middleware(async (opts) => {
  const { ctx } = opts;
  const authHeader = ctx.req.headers.authorization;

  if (!authHeader) {
    throw new TRPCError({ code: 'UNAUTHORIZED' });
  }

  try {
    const jwtPayload = await getJWTPayload(authHeader);
    ctx.userId = jwtPayload.sub; // Assuming the user ID is in the 'sub' field
  } catch (error) {
    throw new TRPCError({ code: 'UNAUTHORIZED', message: (error as Error).message });
  }

  if (!ctx.userId) {
    if (enableClerk) {
      console.log('clerk auth:', ctx.clerkAuth);
    } else {
      console.log('next auth:', ctx.nextAuth);
    }
    throw new TRPCError({ code: 'UNAUTHORIZED' });
  }

  return opts.next({
    ctx: {
      userId: ctx.userId,
    },
  });
});

Additionally, you can refer to the jwtPayloadChecker middleware from src/libs/trpc/middleware/jwtPayload.ts for another example of handling authentication:

import { TRPCError } from '@trpc/server';

import { getJWTPayload } from '@/app/api/middleware/auth/utils';
import { trpc } from '@/libs/trpc/init';

export const jwtPayloadChecker = trpc.middleware(async (opts) => {
  const { ctx } = opts;

  if (!ctx.authorizationHeader) throw new TRPCError({ code: 'UNAUTHORIZED' });

  const jwtPayload = await getJWTPayload(ctx.authorizationHeader);

  return opts.next({ ctx: { jwtPayload } });
});

Make sure to replace getJWTPayload and jwtPayload.sub with the appropriate methods and fields for your specific authentication provider (Auth0/GitHub App). This should help resolve the [TRPCError]: UNAUTHORIZED error by ensuring that ctx.userId is correctly set [2][3][4][5].

To continue talking to Dosu, mention @dosu.

dosubot[bot] commented 2 days ago

I found a similar solved discussion that might help you with your issue: [HELP] Deploying Lobe-Chat with Server-Side Persistence and SSO | 部署带服务器端持久化和SSO的Lobe-Chat. This discussion addresses deployment issues and provides a detailed tutorial for setting up the environment [1].

To resolve the [TRPCError]: UNAUTHORIZED error in your Next.js application when using Docker with Auth0/GitHub App and Tencent COS, you need to ensure that the ctx.userId is correctly set in your context. The error occurs because ctx.userId is null or undefined.

Here is the relevant code snippet from src/libs/trpc/middleware/userAuth.ts:

import { TRPCError } from '@trpc/server';

import { enableClerk } from '@/const/auth';

import { trpc } from '../init';

export const userAuth = trpc.middleware(async (opts) => {
  const { ctx } = opts;
  // `ctx.user` is nullable
  if (!ctx.userId) {
    if (enableClerk) {
      console.log('clerk auth:', ctx.clerkAuth);
    } else {
      console.log('next auth:', ctx.nextAuth);
    }
    throw new TRPCError({ code: 'UNAUTHORIZED' });
  }

  return opts.next({
    ctx: {
      // ✅ user value is known to be non-null now
      userId: ctx.userId,
    },
  });
});

To fix this issue, you need to ensure that the authentication middleware correctly sets ctx.userId. This typically involves verifying the authentication token and extracting the user ID from it. Here are some steps you can follow:

  1. Verify Authentication Token: Ensure that the authentication token from Auth0/GitHub App is being correctly verified.
  2. Extract User ID: Extract the user ID from the verified token and set it in the context (ctx.userId).

Here is an example of how you might modify the middleware to include token verification and user ID extraction, using the getJWTPayload utility function:

import { TRPCError } from '@trpc/server';
import { getJWTPayload } from '@/app/api/middleware/auth/utils'; // Adjust the import path as necessary

import { enableClerk } from '@/const/auth';
import { trpc } from '../init';

export const userAuth = trpc.middleware(async (opts) => {
  const { ctx } = opts;
  const authHeader = ctx.req.headers.authorization;

  if (!authHeader) {
    throw new TRPCError({ code: 'UNAUTHORIZED' });
  }

  try {
    const jwtPayload = await getJWTPayload(authHeader);
    ctx.userId = jwtPayload.sub; // Assuming the user ID is in the 'sub' field
  } catch (error) {
    throw new TRPCError({ code: 'UNAUTHORIZED', message: (error as Error).message });
  }

  if (!ctx.userId) {
    if (enableClerk) {
      console.log('clerk auth:', ctx.clerkAuth);
    } else {
      console.log('next auth:', ctx.nextAuth);
    }
    throw new TRPCError({ code: 'UNAUTHORIZED' });
  }

  return opts.next({
    ctx: {
      userId: ctx.userId,
    },
  });
});

Additionally, you can refer to the jwtPayloadChecker middleware from src/libs/trpc/middleware/jwtPayload.ts for another example of handling authentication:

import { TRPCError } from '@trpc/server';

import { getJWTPayload } from '@/app/api/middleware/auth/utils';
import { trpc } from '@/libs/trpc/init';

export const jwtPayloadChecker = trpc.middleware(async (opts) => {
  const { ctx } = opts;

  if (!ctx.authorizationHeader) throw new TRPCError({ code: 'UNAUTHORIZED' });

  const jwtPayload = await getJWTPayload(ctx.authorizationHeader);

  return opts.next({ ctx: { jwtPayload } });
});

Make sure to replace getJWTPayload and jwtPayload.sub with the appropriate methods and fields for your specific authentication provider (Auth0/GitHub App). This should help resolve the [TRPCError]: UNAUTHORIZED error by ensuring that ctx.userId is correctly set [2][3][4][5].

To continue talking to Dosu, mention @dosu.

SpeedupMaster commented 1 day ago

ACCESS_CODE: 'xxx' 这个不需要了 AUTH_AUTH0_ISSUER: 'https://chat.xxxx/api/auth/callback/auth0' 还有这个ISSUER应该是Auth0 应用程序的 Domain

lobehubbot commented 1 day ago

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


ACCESS_CODE: 'xxx' This is no longer needed AUTH_AUTH0_ISSUER: 'https://chat.xxxx/api/auth/callback/auth0' And this ISSUER should be the Domain of the Auth0 application