Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Enable auth using trusted header (#1128)
Browse files* Declare jwt-decode as dependency.
* Show email from JWT and hide signout
* Use special value for JWT user ID.
* fix user creation, fix linting
* formatting
* Update implem to use header instead of cookie
* create user id based on email
---------
Co-authored-by: Nathan Sarrazin <[email protected]>
- .env +2 -0
- README.md +15 -2
- src/app.d.ts +1 -1
- src/hooks.server.ts +21 -1
- src/lib/components/NavMenu.svelte +8 -6
- src/routes/+layout.server.ts +1 -0
.env
CHANGED
@@ -6,6 +6,8 @@ MONGODB_DB_NAME=chat-ui
|
|
6 |
MONGODB_DIRECT_CONNECTION=false
|
7 |
|
8 |
COOKIE_NAME=hf-chat
|
|
|
|
|
9 |
HF_TOKEN=#hf_<token> from https://huggingface.co/settings/token
|
10 |
HF_API_ROOT=https://api-inference.huggingface.co/models
|
11 |
|
|
|
6 |
MONGODB_DIRECT_CONNECTION=false
|
7 |
|
8 |
COOKIE_NAME=hf-chat
|
9 |
+
TRUSTED_EMAIL_HEADER= # only set this if you understand the implications
|
10 |
+
|
11 |
HF_TOKEN=#hf_<token> from https://huggingface.co/settings/token
|
12 |
HF_API_ROOT=https://api-inference.huggingface.co/models
|
13 |
|
README.md
CHANGED
@@ -147,6 +147,19 @@ OPENID_CONFIG=`{
|
|
147 |
|
148 |
These variables will enable the openID sign-in modal for users.
|
149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
### Theming
|
151 |
|
152 |
You can use a few environment variables to customize the look and feel of chat-ui. These are by default:
|
@@ -172,7 +185,7 @@ You can enable the web search through an API by adding `YDC_API_KEY` ([docs.you.
|
|
172 |
|
173 |
You can also simply enable the local google websearch by setting `USE_LOCAL_WEBSEARCH=true` in your `.env.local` or specify a SearXNG instance by adding the query URL to `SEARXNG_QUERY_URL`.
|
174 |
|
175 |
-
You can enable
|
176 |
|
177 |
### Custom models
|
178 |
|
@@ -232,7 +245,7 @@ The following is the default `chatPromptTemplate`, although newlines and indenti
|
|
232 |
|
233 |
#### Multi modal model
|
234 |
|
235 |
-
We currently support [IDEFICS](https://huggingface.co/blog/idefics) (hosted on TGI), OpenAI and Claude 3 as multimodal models. You can enable it by setting `multimodal: true` in your `MODELS` configuration. For IDEFICS, you must have a [PRO HF Api token](https://huggingface.co/settings/tokens). For OpenAI, see the [OpenAI section](#OpenAI). For Anthropic, see the [Anthropic section](#
|
236 |
|
237 |
```env
|
238 |
{
|
|
|
147 |
|
148 |
These variables will enable the openID sign-in modal for users.
|
149 |
|
150 |
+
### Trusted header authentication
|
151 |
+
|
152 |
+
You can set the env variable `TRUSTED_EMAIL_HEADER` to point to the header that contains the user's email address. This will allow you to authenticate users from the header. This setup is usually combined with a proxy that will be in front of chat-ui and will handle the auth and set the header.
|
153 |
+
|
154 |
+
> [!WARNING]
|
155 |
+
> Make sure to only allow requests to chat-ui through your proxy which handles authentication, otherwise users could authenticate as anyone by setting the header manually! Only set this up if you understand the implications and know how to do it correctly.
|
156 |
+
|
157 |
+
Here is a list of header names for common auth providers:
|
158 |
+
|
159 |
+
- Tailscale Serve: `Tailscale-User-Login`
|
160 |
+
- Cloudflare Access: `Cf-Access-Authenticated-User-Email`
|
161 |
+
- oauth2-proxy: `X-Forwarded-Email`
|
162 |
+
|
163 |
### Theming
|
164 |
|
165 |
You can use a few environment variables to customize the look and feel of chat-ui. These are by default:
|
|
|
185 |
|
186 |
You can also simply enable the local google websearch by setting `USE_LOCAL_WEBSEARCH=true` in your `.env.local` or specify a SearXNG instance by adding the query URL to `SEARXNG_QUERY_URL`.
|
187 |
|
188 |
+
You can enable javascript when parsing webpages to improve compatibility with `WEBSEARCH_JAVASCRIPT=true` at the cost of increased CPU usage. You'll want at least 4 cores when enabling.
|
189 |
|
190 |
### Custom models
|
191 |
|
|
|
245 |
|
246 |
#### Multi modal model
|
247 |
|
248 |
+
We currently support [IDEFICS](https://huggingface.co/blog/idefics) (hosted on TGI), OpenAI and Claude 3 as multimodal models. You can enable it by setting `multimodal: true` in your `MODELS` configuration. For IDEFICS, you must have a [PRO HF Api token](https://huggingface.co/settings/tokens). For OpenAI, see the [OpenAI section](#OpenAI). For Anthropic, see the [Anthropic section](#anthropic).
|
249 |
|
250 |
```env
|
251 |
{
|
src/app.d.ts
CHANGED
@@ -10,7 +10,7 @@ declare global {
|
|
10 |
// interface Error {}
|
11 |
interface Locals {
|
12 |
sessionId: string;
|
13 |
-
user?: User;
|
14 |
}
|
15 |
|
16 |
interface Error {
|
|
|
10 |
// interface Error {}
|
11 |
interface Locals {
|
12 |
sessionId: string;
|
13 |
+
user?: User & { logoutDisabled?: boolean };
|
14 |
}
|
15 |
|
16 |
interface Error {
|
src/hooks.server.ts
CHANGED
@@ -13,6 +13,7 @@ import { refreshAssistantsCounts } from "$lib/assistantStats/refresh-assistants-
|
|
13 |
import { logger } from "$lib/server/logger";
|
14 |
import { AbortedGenerations } from "$lib/server/abortedGenerations";
|
15 |
import { MetricsServer } from "$lib/server/metrics";
|
|
|
16 |
|
17 |
// TODO: move this code on a started server hook, instead of using a "building" flag
|
18 |
if (!building) {
|
@@ -96,10 +97,29 @@ export const handle: Handle = async ({ event, resolve }) => {
|
|
96 |
|
97 |
const token = event.cookies.get(env.COOKIE_NAME);
|
98 |
|
|
|
|
|
|
|
|
|
|
|
99 |
let secretSessionId: string;
|
100 |
let sessionId: string;
|
101 |
|
102 |
-
if (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
secretSessionId = token;
|
104 |
sessionId = await sha256(token);
|
105 |
|
|
|
13 |
import { logger } from "$lib/server/logger";
|
14 |
import { AbortedGenerations } from "$lib/server/abortedGenerations";
|
15 |
import { MetricsServer } from "$lib/server/metrics";
|
16 |
+
import { ObjectId } from "mongodb";
|
17 |
|
18 |
// TODO: move this code on a started server hook, instead of using a "building" flag
|
19 |
if (!building) {
|
|
|
97 |
|
98 |
const token = event.cookies.get(env.COOKIE_NAME);
|
99 |
|
100 |
+
// if the trusted email header is set we use it to get the user email
|
101 |
+
const email = env.TRUSTED_EMAIL_HEADER
|
102 |
+
? event.request.headers.get(env.TRUSTED_EMAIL_HEADER)
|
103 |
+
: null;
|
104 |
+
|
105 |
let secretSessionId: string;
|
106 |
let sessionId: string;
|
107 |
|
108 |
+
if (email) {
|
109 |
+
secretSessionId = sessionId = await sha256(email);
|
110 |
+
|
111 |
+
event.locals.user = {
|
112 |
+
// generate id based on email
|
113 |
+
_id: new ObjectId(sessionId.slice(0, 24)),
|
114 |
+
name: email,
|
115 |
+
email,
|
116 |
+
createdAt: new Date(),
|
117 |
+
updatedAt: new Date(),
|
118 |
+
hfUserId: email,
|
119 |
+
avatarUrl: "",
|
120 |
+
logoutDisabled: true,
|
121 |
+
};
|
122 |
+
} else if (token) {
|
123 |
secretSessionId = token;
|
124 |
sessionId = await sha256(token);
|
125 |
|
src/lib/components/NavMenu.svelte
CHANGED
@@ -89,12 +89,14 @@
|
|
89 |
class="flex h-9 flex-none shrink items-center gap-1.5 truncate pr-2 text-gray-500 dark:text-gray-400"
|
90 |
>{user?.username || user?.email}</span
|
91 |
>
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
|
|
98 |
</form>
|
99 |
{/if}
|
100 |
{#if canLogin}
|
|
|
89 |
class="flex h-9 flex-none shrink items-center gap-1.5 truncate pr-2 text-gray-500 dark:text-gray-400"
|
90 |
>{user?.username || user?.email}</span
|
91 |
>
|
92 |
+
{#if !user.logoutDisabled}
|
93 |
+
<button
|
94 |
+
type="submit"
|
95 |
+
class="ml-auto h-6 flex-none items-center gap-1.5 rounded-md border bg-white px-2 text-gray-700 shadow-sm group-hover:flex hover:shadow-none md:hidden dark:border-gray-600 dark:bg-gray-600 dark:text-gray-400 dark:hover:text-gray-300"
|
96 |
+
>
|
97 |
+
Sign Out
|
98 |
+
</button>
|
99 |
+
{/if}
|
100 |
</form>
|
101 |
{/if}
|
102 |
{#if canLogin}
|
src/routes/+layout.server.ts
CHANGED
@@ -192,6 +192,7 @@ export const load: LayoutServerLoad = async ({ locals, depends }) => {
|
|
192 |
username: locals.user.username,
|
193 |
avatarUrl: locals.user.avatarUrl,
|
194 |
email: locals.user.email,
|
|
|
195 |
},
|
196 |
assistant,
|
197 |
enableAssistants,
|
|
|
192 |
username: locals.user.username,
|
193 |
avatarUrl: locals.user.avatarUrl,
|
194 |
email: locals.user.email,
|
195 |
+
logoutDisabled: locals.user.logoutDisabled,
|
196 |
},
|
197 |
assistant,
|
198 |
enableAssistants,
|