This commit is contained in:
Timothy J. Baek 2024-10-15 02:48:41 -07:00
parent 2f4c04055c
commit 97bb9d41a6
3 changed files with 62 additions and 15 deletions

View File

@ -1,10 +1,13 @@
import re import re
import uuid import uuid
import time
import datetime
from open_webui.apps.webui.models.auths import ( from open_webui.apps.webui.models.auths import (
AddUserForm, AddUserForm,
ApiKey, ApiKey,
Auths, Auths,
Token,
SigninForm, SigninForm,
SigninResponse, SigninResponse,
SignupForm, SignupForm,
@ -34,6 +37,7 @@ from open_webui.utils.utils import (
get_password_hash, get_password_hash,
) )
from open_webui.utils.webhook import post_webhook from open_webui.utils.webhook import post_webhook
from typing import Optional
router = APIRouter() router = APIRouter()
@ -42,25 +46,42 @@ router = APIRouter()
############################ ############################
@router.get("/", response_model=UserResponse) class SessionUserResponse(Token, UserResponse):
expires_at: Optional[int] = None
@router.get("/", response_model=SessionUserResponse)
async def get_session_user( async def get_session_user(
request: Request, response: Response, user=Depends(get_current_user) request: Request, response: Response, user=Depends(get_current_user)
): ):
expires_delta = parse_duration(request.app.state.config.JWT_EXPIRES_IN)
expires_at = None
if expires_delta:
expires_at = int(time.time()) + int(expires_delta.total_seconds())
token = create_token( token = create_token(
data={"id": user.id}, data={"id": user.id},
expires_delta=parse_duration(request.app.state.config.JWT_EXPIRES_IN), expires_delta=expires_delta,
)
datetime_expires_at = datetime.datetime.fromtimestamp(
expires_at, datetime.timezone.utc
) )
# Set the cookie token # Set the cookie token
response.set_cookie( response.set_cookie(
key="token", key="token",
value=token, value=token,
expires=datetime_expires_at,
httponly=True, # Ensures the cookie is not accessible via JavaScript httponly=True, # Ensures the cookie is not accessible via JavaScript
samesite=WEBUI_SESSION_COOKIE_SAME_SITE, samesite=WEBUI_SESSION_COOKIE_SAME_SITE,
secure=WEBUI_SESSION_COOKIE_SECURE, secure=WEBUI_SESSION_COOKIE_SECURE,
) )
return { return {
"token": token,
"token_type": "Bearer",
"expires_at": expires_at,
"id": user.id, "id": user.id,
"email": user.email, "email": user.email,
"name": user.name, "name": user.name,
@ -119,7 +140,7 @@ async def update_password(
############################ ############################
@router.post("/signin", response_model=SigninResponse) @router.post("/signin", response_model=SessionUserResponse)
async def signin(request: Request, response: Response, form_data: SigninForm): async def signin(request: Request, response: Response, form_data: SigninForm):
if WEBUI_AUTH_TRUSTED_EMAIL_HEADER: if WEBUI_AUTH_TRUSTED_EMAIL_HEADER:
if WEBUI_AUTH_TRUSTED_EMAIL_HEADER not in request.headers: if WEBUI_AUTH_TRUSTED_EMAIL_HEADER not in request.headers:
@ -161,15 +182,26 @@ async def signin(request: Request, response: Response, form_data: SigninForm):
user = Auths.authenticate_user(form_data.email.lower(), form_data.password) user = Auths.authenticate_user(form_data.email.lower(), form_data.password)
if user: if user:
expires_delta = parse_duration(request.app.state.config.JWT_EXPIRES_IN)
expires_at = None
if expires_delta:
expires_at = int(time.time()) + int(expires_delta.total_seconds())
token = create_token( token = create_token(
data={"id": user.id}, data={"id": user.id},
expires_delta=parse_duration(request.app.state.config.JWT_EXPIRES_IN), expires_delta=expires_delta,
)
datetime_expires_at = datetime.datetime.fromtimestamp(
expires_at, datetime.timezone.utc
) )
# Set the cookie token # Set the cookie token
response.set_cookie( response.set_cookie(
key="token", key="token",
value=token, value=token,
expires=datetime_expires_at,
httponly=True, # Ensures the cookie is not accessible via JavaScript httponly=True, # Ensures the cookie is not accessible via JavaScript
samesite=WEBUI_SESSION_COOKIE_SAME_SITE, samesite=WEBUI_SESSION_COOKIE_SAME_SITE,
secure=WEBUI_SESSION_COOKIE_SECURE, secure=WEBUI_SESSION_COOKIE_SECURE,
@ -178,6 +210,7 @@ async def signin(request: Request, response: Response, form_data: SigninForm):
return { return {
"token": token, "token": token,
"token_type": "Bearer", "token_type": "Bearer",
"expires_at": expires_at,
"id": user.id, "id": user.id,
"email": user.email, "email": user.email,
"name": user.name, "name": user.name,
@ -193,7 +226,7 @@ async def signin(request: Request, response: Response, form_data: SigninForm):
############################ ############################
@router.post("/signup", response_model=SigninResponse) @router.post("/signup", response_model=SessionUserResponse)
async def signup(request: Request, response: Response, form_data: SignupForm): async def signup(request: Request, response: Response, form_data: SignupForm):
if WEBUI_AUTH: if WEBUI_AUTH:
if ( if (
@ -233,15 +266,25 @@ async def signup(request: Request, response: Response, form_data: SignupForm):
) )
if user: if user:
expires_delta = parse_duration(request.app.state.config.JWT_EXPIRES_IN)
expires_at = None
if expires_delta:
expires_at = int(time.time()) + int(expires_delta.total_seconds())
token = create_token( token = create_token(
data={"id": user.id}, data={"id": user.id},
expires_delta=parse_duration(request.app.state.config.JWT_EXPIRES_IN), expires_delta=expires_delta,
)
datetime_expires_at = datetime.datetime.fromtimestamp(
expires_at, datetime.timezone.utc
) )
# Set the cookie token # Set the cookie token
response.set_cookie( response.set_cookie(
key="token", key="token",
value=token, value=token,
expires=datetime_expires_at,
httponly=True, # Ensures the cookie is not accessible via JavaScript httponly=True, # Ensures the cookie is not accessible via JavaScript
samesite=WEBUI_SESSION_COOKIE_SAME_SITE, samesite=WEBUI_SESSION_COOKIE_SAME_SITE,
secure=WEBUI_SESSION_COOKIE_SECURE, secure=WEBUI_SESSION_COOKIE_SECURE,
@ -261,6 +304,7 @@ async def signup(request: Request, response: Response, form_data: SignupForm):
return { return {
"token": token, "token": token,
"token_type": "Bearer", "token_type": "Bearer",
"expires_at": expires_at,
"id": user.id, "id": user.id,
"email": user.email, "email": user.email,
"name": user.name, "name": user.name,

View File

@ -7,7 +7,7 @@ import jwt
from open_webui.apps.webui.models.users import Users from open_webui.apps.webui.models.users import Users
from open_webui.constants import ERROR_MESSAGES from open_webui.constants import ERROR_MESSAGES
from open_webui.env import WEBUI_SECRET_KEY from open_webui.env import WEBUI_SECRET_KEY
from fastapi import Depends, HTTPException, Request, status from fastapi import Depends, HTTPException, Request, Response, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from passlib.context import CryptContext from passlib.context import CryptContext
@ -73,6 +73,7 @@ def get_http_authorization_cred(auth_header: str):
def get_current_user( def get_current_user(
request: Request, request: Request,
response: Response,
auth_token: HTTPAuthorizationCredentials = Depends(bearer_security), auth_token: HTTPAuthorizationCredentials = Depends(bearer_security),
): ):
token = None token = None
@ -103,6 +104,8 @@ def get_current_user(
Users.update_user_last_active_by_id(user.id) Users.update_user_last_active_by_id(user.id)
return user return user
else: else:
response.delete_cookie("token")
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.UNAUTHORIZED, detail=ERROR_MESSAGES.UNAUTHORIZED,

View File

@ -675,7 +675,7 @@
</div> </div>
</div> </div>
<div class="px-2.5 pb-safe-bottom"> <div class="px-2 pb-safe-bottom">
<!-- <hr class=" border-gray-900 mb-1 w-full" /> --> <!-- <hr class=" border-gray-900 mb-1 w-full" /> -->
<div class="flex flex-col font-primary"> <div class="flex flex-col font-primary">
@ -689,7 +689,7 @@
}} }}
> >
<button <button
class=" flex rounded-xl py-3 px-3.5 w-full hover:bg-gray-100 dark:hover:bg-gray-900 transition" class=" flex items-center rounded-xl py-2.5 px-2.5 w-full hover:bg-gray-100 dark:hover:bg-gray-900 transition"
on:click={() => { on:click={() => {
showDropdown = !showDropdown; showDropdown = !showDropdown;
}} }}