Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@ Set env `AUTH_PROXY_ENABLED=true` can enable auth proxy mode.

After activating this feature, it is necessary to ensure that chatgpt-web can only be accessed through a reverse proxy.

Authentication is carried out by the reverse proxy, which then forwards the request with the `X-Email` header to identify the user identity.
Authentication is carried out by the reverse proxy, which then forwards the request with the header to identify the user identity.
Default header name is `X-Email`, can custom config use set env `AUTH_PROXY_HEADER_NAME`.

Recommended for current IdP to use LDAP protocol, using [authelia](https://www.authelia.com)

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,8 @@ pnpm build

在开启该功能后 需确保 chatgpt-web 只能通过反向代理访问

由反向代理进行进行身份验证 并再转发请求时携带请求头`X-Email`标识用户身份
由反向代理进行进行身份验证 并再转发请求时携带请求头标识用户身份
默认请求头为 `X-Email` 并可以通过设置环境变量 `AUTH_PROXY_HEADER_NAME` 自定义配置

推荐当前 Idp 使用 LDAP 协议的 可以选择使用 [authelia](https://www.authelia.com)

Expand Down
14 changes: 9 additions & 5 deletions service/src/middleware/auth.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import jwt from 'jsonwebtoken'
import type { Request } from 'express'
import { getCacheConfig } from '../storage/config'
import { authProxyHeaderName, getCacheConfig } from '../storage/config'
import { createUser, getUser, getUserById } from '../storage/mongo'
import { Status, UserRole } from '../storage/model'
import type { AuthJwtPayload } from '../types'
Expand All @@ -10,17 +10,17 @@ async function auth(req, res, next) {

if (config.siteConfig.authProxyEnabled) {
try {
const username = req.header('X-Email')
const username = req.header(authProxyHeaderName)
if (!username) {
res.send({ status: 'Unauthorized', message: 'Please config auth proxy (usually is nginx) add set proxy header X-Email.', data: null })
res.send({ status: 'Unauthorized', message: `Please config auth proxy (usually is nginx) add set proxy header ${authProxyHeaderName}.`, data: null })
return
}
const user = await getUser(username)
req.headers.userId = user._id.toString()
next()
}
catch (error) {
res.send({ status: 'Unauthorized', message: error.message ?? 'Please config auth proxy (usually is nginx) add set proxy header X-Email.', data: null })
res.send({ status: 'Unauthorized', message: error.message ?? `Please config auth proxy (usually is nginx) add set proxy header ${authProxyHeaderName}.`, data: null })
}
return
}
Expand Down Expand Up @@ -52,7 +52,11 @@ async function getUserId(req: Request): Promise<string | undefined> {
try {
const config = await getCacheConfig()
if (config.siteConfig.authProxyEnabled) {
const username = req.header('X-Email')
const username = req.header(authProxyHeaderName)
if (!username) {
globalThis.console.error(`Please config auth proxy (usually is nginx) add set proxy header ${authProxyHeaderName}.`)
return null
}
let user = await getUser(username)
if (user == null) {
const isRoot = username.toLowerCase() === process.env.ROOT_USER
Expand Down
6 changes: 3 additions & 3 deletions service/src/middleware/rootAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import jwt from 'jsonwebtoken'
import * as dotenv from 'dotenv'
import { Status, UserRole } from '../storage/model'
import { getUser, getUserById } from '../storage/mongo'
import { getCacheConfig } from '../storage/config'
import { authProxyHeaderName, getCacheConfig } from '../storage/config'
import type { AuthJwtPayload } from '../types'

dotenv.config()
Expand All @@ -12,7 +12,7 @@ async function rootAuth(req, res, next) {

if (config.siteConfig.authProxyEnabled) {
try {
const username = req.header('X-Email')
const username = req.header(authProxyHeaderName)
const user = await getUser(username)
req.headers.userId = user._id
if (user == null || user.status !== Status.Normal || !user.roles.includes(UserRole.Admin))
Expand All @@ -21,7 +21,7 @@ async function rootAuth(req, res, next) {
next()
}
catch (error) {
res.send({ status: 'Unauthorized', message: error.message ?? 'Please config auth proxy (usually is nginx) add set proxy header X-Email.', data: null })
res.send({ status: 'Unauthorized', message: error.message ?? `Please config auth proxy (usually is nginx) add set proxy header ${authProxyHeaderName}.`, data: null })
}
return
}
Expand Down
2 changes: 2 additions & 0 deletions service/src/storage/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,5 @@ export async function getApiKeys() {
})
return result
}

export const authProxyHeaderName = process.env.AUTH_PROXY_HEADER_NAME ?? 'X-Email'