[GH-ISSUE #3058] Feat: Guest Mode #116422

Closed
opened 2026-05-20 18:09:20 -05:00 by GiteaMirror · 8 comments
Owner

Originally created by @MarlNox on GitHub (Jun 12, 2024).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/3058

Problem:
When users are not logged in, there's currently no option for them to engage in conversations through the chat in the open web UI without their interactions being put in history, like in the Single User mode where all history is still recorded so it can't be used simultaneously by many users.

Solution:
Introduce a "Guest Mode" within the open web UI, where users can access chat functionality without the need to create personal accounts. Upon choosing the "No Login" option, users are automatically provided with predefined login credentials (e.g., username and password) generated by the system. In this Guest Mode, the sidebar displaying chat history is hidden, ensuring that no conversation records are stored. The guest mode should be in addition to the multi-user sign in rather than an either-or scenario.
Alternatives:
Consider allowing users to access limited chat functionality without logging in, with the option to create an account for accessing more features and retaining chat history.

Originally created by @MarlNox on GitHub (Jun 12, 2024). Original GitHub issue: https://github.com/open-webui/open-webui/issues/3058 **Problem:** When users are not logged in, there's currently no option for them to engage in conversations through the chat in the open web UI without their interactions being put in history, like in the Single User mode where all history is still recorded so it can't be used simultaneously by many users. **Solution:** Introduce a "Guest Mode" within the open web UI, where users can access chat functionality without the need to create personal accounts. Upon choosing the "No Login" option, users are automatically provided with predefined login credentials (e.g., username and password) generated by the system. In this Guest Mode, the sidebar displaying chat history is hidden, ensuring that no conversation records are stored. The guest mode should be in addition to the multi-user sign in rather than an either-or scenario. **Alternatives:** Consider allowing users to access limited chat functionality without logging in, with the option to create an account for accessing more features and retaining chat history.
Author
Owner

@MarlNox commented on GitHub (Jun 13, 2024):

FIX i implemented locally - potentially useful input for the maintainers/devs of OpenWebui:

  1. Create an iframe html in static folder, and connect it with the src/routes/auth/+page.svelte, as well as setting the safe origin for requests.
  2. Create a Guest user with some credentials whatever (guestuser@guest.com, root password)
  3. Create a redirect button with JS to do the following: authenticate the user with the hardcoded sigin details.
  4. Fetch Token, insert it via iframe into the origin of the openwebui (cross-origin set LocalStorage token key)
  5. if logged in user is Guest, then hide the content of the sidebar. As well as other buttons which give access to chat history, or account settings.

Additional stuff:
a) create a new chat before redirecting to that specific chat.

TO DO from my side:

a) Generate the response to that new chat's query using the selected Pipeline.

 - From what im seeing there's no API endpoint for generation given a modelname, chatid, and userid. 
<!-- gh-comment-id:2165780166 --> @MarlNox commented on GitHub (Jun 13, 2024): **FIX i implemented locally - potentially useful input for the maintainers/devs of OpenWebui:** 1. Create an iframe html in static folder, and connect it with the src/routes/auth/+page.svelte, as well as setting the safe origin for requests. 2. Create a Guest user with some credentials whatever (guestuser@guest.com, root password) 3. Create a redirect button with JS to do the following: authenticate the user with the hardcoded sigin details. 4. Fetch Token, insert it via iframe into the origin of the openwebui (cross-origin set LocalStorage token key) 5. if logged in user is Guest, then hide the content of the sidebar. As well as other buttons which give access to chat history, or account settings. ___ Additional stuff: a) create a new chat before redirecting to that specific chat. ## TO DO from my side: a) Generate the response to that new chat's query using the selected Pipeline. - From what im seeing there's no API endpoint for generation given a modelname, chatid, and userid.
Author
Owner

@gaby commented on GitHub (Oct 4, 2024):

This is basically similar to https://chat.openai.com where you can use ChatGPT without login and history is gone once you refresh or close browser

<!-- gh-comment-id:2393596636 --> @gaby commented on GitHub (Oct 4, 2024): This is basically similar to https://chat.openai.com where you can use ChatGPT without login and history is gone once you refresh or close browser
Author
Owner

@stuartofmine commented on GitHub (Dec 17, 2024):

maybe more like https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web , guest user auto signup and can login by cookie

<!-- gh-comment-id:2547403744 --> @stuartofmine commented on GitHub (Dec 17, 2024): maybe more like https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web , guest user auto signup and can login by cookie
Author
Owner

@stuartofmine commented on GitHub (Dec 18, 2024):

OK. I have finished it by trusted header.

  1. In your docker-compose.yaml:
environment:
  - WEBUI_AUTH=True
  - ENABLE_SIGNUP=true
  - ENABLE_AUTO_AUTH=true
  - AUTH_TRUSTED_EMAIL_HEADER=true
  - WEBUI_AUTH_TRUSTED_EMAIL_HEADER=X-User-Email
  - WEBUI_AUTH_TRUSTED_NAME_HEADER=X-User-Name
  1. In backend/open_webui/apps/webui/models/auths.py
import logging
import uuid
import jwt
from datetime import UTC, datetime, timedelta
from typing import Optional, Union, List, Dict
from fastapi import Request, HTTPException, status

from open_webui.utils.misc import parse_duration
from open_webui.apps.webui.internal.db import Base, get_db
from open_webui.apps.webui.models.users import UserModel, Users
from open_webui.env import SRC_LOG_LEVELS,ENABLE_AUTO_AUTH,WEBUI_SECRET_KEY
from pydantic import BaseModel
from sqlalchemy import Boolean, Column, String, Text
from open_webui.utils.utils import verify_password

SESSION_SECRET = WEBUI_SECRET_KEY
ALGORITHM = "HS256"

log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])

    # Other Code
    def auto_auth(self, request: Request):
        log.debug("Starting auto auth process")
        
        random_id = str(uuid.uuid4())[:8]
        auto_email = f"auto_user_{random_id}@auto.local"
        auto_name = f"Auto User {random_id}"
        auto_password = str(uuid.uuid4())

        try:
            log.info(f"Creating auto user with email: {auto_email}")
            
            user = self.insert_new_auth(
                email=auto_email,
                password=auto_password,
                name=auto_name,
                role="user",
            )

            if not user:
                log.error("Failed to create auto user")
                raise HTTPException(
                    status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    detail="Failed to create auto user",
                )

            log.info(f"Successfully created auto user with ID: {user.id}")
            
            def create_token(data: dict, expires_delta: Union[timedelta, None] = None) -> str:
                payload = data.copy()

                if expires_delta:
                    expire = datetime.now(UTC) + expires_delta
                    payload.update({"exp": expire})

                encoded_jwt = jwt.encode(payload, SESSION_SECRET, algorithm=ALGORITHM)
                return encoded_jwt
            token = create_token(
                data={"id": user.id},
                expires_delta=parse_duration("-1"),
            )

            return {
                "status": True,
                "token": token,
                "user": {
                    "id": user.id,
                    "name": user.name,
                    "email": user.email,
                    "role": user.role,
                },
            }
        except Exception as e:
            log.exception(f"Auto auth failed: {str(e)}")
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"Auto auth failed: {str(e)}",
            )

    def authenticate_user_by_trusted_header(self, request: Request) -> Optional[UserModel]:
        # log.info(f"authenticate_user_by_trusted_header: {email}")
        # try:
        #     with get_db() as db:
        #         auth = db.query(Auth).filter_by(email=email, active=True).first()
        #         if auth:
        #             user = Users.get_user_by_id(auth.id)
        #             return user
        # except Exception:
        #     return None
        if ENABLE_AUTO_AUTH:
            log.info("Auto auth enabled, creating new user")
            auth_result = self.auto_auth(request)
            if auth_result and auth_result["status"]:
                user = Users.get_user_by_id(auth_result["user"]["id"])
                log.info(f"Created new auto user: {user.id}")
                return user        
        return None    
  1. Because I have change functionauthenticate_user_by_trusted_header, So
    In backend/open_webui/apps/webui/routers/auths.py
    change function signin statement judge:
@router.post("/signin", response_model=SessionUserResponse)
async def signin(request: Request, response: Response, form_data: SigninForm):
    if ENABLE_AUTO_AUTH == True and (WEBUI_AUTH_TRUSTED_EMAIL_HEADER in request.headers):

and modify
user = Auths.authenticate_user_by_trusted_header(trusted_email)
to
user = Auths.authenticate_user_by_trusted_header(request)

  1. DO NOT FORGET config open_webui.env to get ENABLE_AUTO_AUTH.
####################################
# ENABLE_AUTO_AUTH (auto create user)
####################################

ENABLE_AUTO_AUTH = os.environ.get("ENABLE_AUTO_AUTH", "True").lower() == "true"
  1. Change +page.svelte, because enable TRUSTED_HEADER will let you can not log in your normal account.
    In line 159 to line 160 , change the auto redirect code to:
<div class="w-full sm:max-w-md px-10 min-h-screen flex flex-col text-center">
{#if window.location.port === YOUR GUEST MODE ENTRY PORT }
	<div class=" my-auto pb-10 w-full">
  1. At last, set header by nginx conf:
server {
    listen 12138;# YOUR GUEST MODE ENTRY

    location / {
        proxy_pass http://127.0.0.1:10086;# YOUR NORMAL MODE ENTRY
        proxy_set_header X-User-Email "user@local.host";
        proxy_set_header X-User-Name "user";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}


Now, you can login by YOUR NORMAL MODE ENTRY, and let guest auto-auth by YOUR GUEST MODE ENTRY

<!-- gh-comment-id:2550697331 --> @stuartofmine commented on GitHub (Dec 18, 2024): OK. I have finished it by trusted header. 1. In your docker-compose.yaml: > environment: > - WEBUI_AUTH=True > - ENABLE_SIGNUP=true > - ENABLE_AUTO_AUTH=true > - AUTH_TRUSTED_EMAIL_HEADER=true > - WEBUI_AUTH_TRUSTED_EMAIL_HEADER=X-User-Email > - WEBUI_AUTH_TRUSTED_NAME_HEADER=X-User-Name 2. In backend/open_webui/apps/webui/models/auths.py ``` import logging import uuid import jwt from datetime import UTC, datetime, timedelta from typing import Optional, Union, List, Dict from fastapi import Request, HTTPException, status from open_webui.utils.misc import parse_duration from open_webui.apps.webui.internal.db import Base, get_db from open_webui.apps.webui.models.users import UserModel, Users from open_webui.env import SRC_LOG_LEVELS,ENABLE_AUTO_AUTH,WEBUI_SECRET_KEY from pydantic import BaseModel from sqlalchemy import Boolean, Column, String, Text from open_webui.utils.utils import verify_password SESSION_SECRET = WEBUI_SECRET_KEY ALGORITHM = "HS256" log = logging.getLogger(__name__) log.setLevel(SRC_LOG_LEVELS["MODELS"]) # Other Code def auto_auth(self, request: Request): log.debug("Starting auto auth process") random_id = str(uuid.uuid4())[:8] auto_email = f"auto_user_{random_id}@auto.local" auto_name = f"Auto User {random_id}" auto_password = str(uuid.uuid4()) try: log.info(f"Creating auto user with email: {auto_email}") user = self.insert_new_auth( email=auto_email, password=auto_password, name=auto_name, role="user", ) if not user: log.error("Failed to create auto user") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to create auto user", ) log.info(f"Successfully created auto user with ID: {user.id}") def create_token(data: dict, expires_delta: Union[timedelta, None] = None) -> str: payload = data.copy() if expires_delta: expire = datetime.now(UTC) + expires_delta payload.update({"exp": expire}) encoded_jwt = jwt.encode(payload, SESSION_SECRET, algorithm=ALGORITHM) return encoded_jwt token = create_token( data={"id": user.id}, expires_delta=parse_duration("-1"), ) return { "status": True, "token": token, "user": { "id": user.id, "name": user.name, "email": user.email, "role": user.role, }, } except Exception as e: log.exception(f"Auto auth failed: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Auto auth failed: {str(e)}", ) def authenticate_user_by_trusted_header(self, request: Request) -> Optional[UserModel]: # log.info(f"authenticate_user_by_trusted_header: {email}") # try: # with get_db() as db: # auth = db.query(Auth).filter_by(email=email, active=True).first() # if auth: # user = Users.get_user_by_id(auth.id) # return user # except Exception: # return None if ENABLE_AUTO_AUTH: log.info("Auto auth enabled, creating new user") auth_result = self.auto_auth(request) if auth_result and auth_result["status"]: user = Users.get_user_by_id(auth_result["user"]["id"]) log.info(f"Created new auto user: {user.id}") return user return None ``` 3. Because I have change function`authenticate_user_by_trusted_header`, So In backend/open_webui/apps/webui/routers/auths.py change function `signin` statement judge: ``` @router.post("/signin", response_model=SessionUserResponse) async def signin(request: Request, response: Response, form_data: SigninForm): if ENABLE_AUTO_AUTH == True and (WEBUI_AUTH_TRUSTED_EMAIL_HEADER in request.headers): ``` and modify `user = Auths.authenticate_user_by_trusted_header(trusted_email)` to `user = Auths.authenticate_user_by_trusted_header(request)` 4. DO NOT FORGET config open_webui.env to get ENABLE_AUTO_AUTH. ``` #################################### # ENABLE_AUTO_AUTH (auto create user) #################################### ENABLE_AUTO_AUTH = os.environ.get("ENABLE_AUTO_AUTH", "True").lower() == "true" ``` 5. Change +page.svelte, because enable TRUSTED_HEADER will let you can not log in your normal account. In line 159 to line 160 , change the auto redirect code to: ``` <div class="w-full sm:max-w-md px-10 min-h-screen flex flex-col text-center"> {#if window.location.port === YOUR GUEST MODE ENTRY PORT } <div class=" my-auto pb-10 w-full"> ``` 8. At last, set header by nginx conf: ``` server { listen 12138;# YOUR GUEST MODE ENTRY location / { proxy_pass http://127.0.0.1:10086;# YOUR NORMAL MODE ENTRY proxy_set_header X-User-Email "user@local.host"; proxy_set_header X-User-Name "user"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } ``` Now, you can login by YOUR NORMAL MODE ENTRY, and let guest auto-auth by YOUR GUEST MODE ENTRY
Author
Owner

@DaniyalAhmadSE commented on GitHub (Feb 17, 2025):

Would really appreciate having this feature.

<!-- gh-comment-id:2663073529 --> @DaniyalAhmadSE commented on GitHub (Feb 17, 2025): Would really appreciate having this feature.
Author
Owner

@xxtg666 commented on GitHub (May 18, 2025):

Need this feature. It hasn't been forgotten, has it?

Suggested to combine with #2904 when this feature is implemented

<!-- gh-comment-id:2889045426 --> @xxtg666 commented on GitHub (May 18, 2025): Need this feature. It hasn't been forgotten, has it? Suggested to combine with #2904 when this feature is implemented
Author
Owner

@cfy-code commented on GitHub (Jul 15, 2025):

How exactly should the guest mode feature be implemented? Based on the latest version, I followed @stuartofmine @MarlNox method, but there are no corresponding folders and code in the new version.

<!-- gh-comment-id:3072914226 --> @cfy-code commented on GitHub (Jul 15, 2025): How exactly should the guest mode feature be implemented? Based on the latest version, I followed @stuartofmine @MarlNox method, but there are no corresponding folders and code in the new version.
Author
Owner

@silentoplayz commented on GitHub (Dec 18, 2025):

This functionality is somewhat effectively already present in Open WebUI via the "Enforce Temporary Chat" permission.

Admins can achieve a "Guest Mode"-like setup by:

  1. Creating a "Guest" Usergroup.
  2. Enabling "Allow Temporary Chat" and "Enforce Temporary Chat" in the group's Chat Permissions.
  3. Creating a generic "Guest" user account and assigning it to this group.

When users log in with this Guest account, their chats will be temporary by default (history not saved), which fulfills the requirement for a privacy-focused guest experience.

<!-- gh-comment-id:3669434699 --> @silentoplayz commented on GitHub (Dec 18, 2025): This functionality is somewhat effectively already present in Open WebUI via the **"Enforce Temporary Chat"** permission. Admins can achieve a "Guest Mode"-like setup by: 1. Creating a "Guest" Usergroup. 2. Enabling **"Allow Temporary Chat"** and **"Enforce Temporary Chat"** in the group's Chat Permissions. 3. Creating a generic "Guest" user account and assigning it to this group. When users log in with this Guest account, their chats will be temporary by default (history not saved), which fulfills the requirement for a privacy-focused guest experience.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#116422