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"]