v0.1.0
Changes: - added rabbitmq hearbeat, consumer and publisher - fixed vqe to run with rabbitmq - added frontend via fasthtml - added proper .env configuration
This commit is contained in:
86
Dockerfile_build/source/connections/keycloak.py
Normal file
86
Dockerfile_build/source/connections/keycloak.py
Normal file
@@ -0,0 +1,86 @@
|
||||
import os
|
||||
from datetime import timedelta
|
||||
|
||||
from connections.local_files import (
|
||||
delete_client_info,
|
||||
delete_token,
|
||||
delete_verifier,
|
||||
load_token,
|
||||
save_token,
|
||||
)
|
||||
from fastcore.xtras import datetime
|
||||
|
||||
from keycloak import KeycloakOpenID
|
||||
|
||||
KEYCLOAK_CONFIG = {
|
||||
"server_url": os.environ["KEYCLOAK_URL"],
|
||||
"realm_name": os.environ["KEYCLOAK_REALM_NAME"],
|
||||
"client_id": os.environ["KEACLOAK_CLIENT_ID"],
|
||||
}
|
||||
|
||||
# Инициализация клиента Keycloak
|
||||
keycloak_openid = KeycloakOpenID(
|
||||
server_url=KEYCLOAK_CONFIG["server_url"],
|
||||
realm_name=KEYCLOAK_CONFIG["realm_name"],
|
||||
client_id=KEYCLOAK_CONFIG["client_id"],
|
||||
)
|
||||
|
||||
|
||||
def refresh_access_token() -> dict | None:
|
||||
"""Refresh the access token using refresh token"""
|
||||
token_data = load_token()
|
||||
if not token_data or not token_data.get("refresh_token"):
|
||||
return None
|
||||
|
||||
try:
|
||||
# Use Keycloak's refresh token endpoint
|
||||
refresh_token = token_data["refresh_token"]
|
||||
|
||||
# Get new token pair using refresh token
|
||||
new_tokens = keycloak_openid.refresh_token(refresh_token)
|
||||
|
||||
# Calculate new expiration time
|
||||
expires_in = new_tokens.get("expires_in", 3600)
|
||||
expires_at = datetime.now() + timedelta(seconds=expires_in)
|
||||
|
||||
# Update token data
|
||||
updated_token_data = {
|
||||
"access_token": new_tokens["access_token"],
|
||||
"refresh_token": new_tokens.get(
|
||||
"refresh_token", refresh_token
|
||||
), # Some providers return new refresh token
|
||||
"expires_at": expires_at.isoformat(),
|
||||
"id_token": new_tokens.get("id_token", token_data.get("id_token")),
|
||||
"user_info": token_data.get("user_info"), # Preserve user info
|
||||
}
|
||||
|
||||
# Save updated tokens
|
||||
save_token(updated_token_data)
|
||||
|
||||
return updated_token_data
|
||||
|
||||
except Exception as e:
|
||||
# If refresh fails, clear all tokens and force re-login
|
||||
delete_token()
|
||||
delete_client_info()
|
||||
delete_verifier()
|
||||
return None
|
||||
|
||||
|
||||
def get_valid_access_token() -> str | None:
|
||||
"""Get a valid access token, refreshing if necessary"""
|
||||
token_data = load_token()
|
||||
|
||||
if not token_data or not token_data.get("expires_at"):
|
||||
return None
|
||||
|
||||
# Check if token is expired or about to expire (within 60 seconds)
|
||||
expires_at = datetime.fromisoformat(str(token_data.get("expires_at")))
|
||||
if expires_at <= datetime.now() + timedelta(seconds=60):
|
||||
# Token is expired or about to expire, try to refresh
|
||||
new_token_data = refresh_access_token()
|
||||
if new_token_data:
|
||||
return new_token_data["access_token"]
|
||||
return None
|
||||
|
||||
return token_data["access_token"]
|
||||
Reference in New Issue
Block a user