Fix version check endpoint authentication
Changed version check endpoints to use X-API-Key authentication instead of Bearer token authentication. This makes them consistent with all other license server endpoints. Changes: - Updated /api/version/check to use validate_api_key dependency - Updated /api/version/latest to use validate_api_key dependency - Both endpoints now expect X-API-Key header instead of Authorization Bearer - Fixes HTTP 403 errors reported by client applications This resolves the issue where session heartbeat worked but version check failed with 403 Forbidden. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Dieser Commit ist enthalten in:
117
test_client_version_check.py
Normale Datei
117
test_client_version_check.py
Normale Datei
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test version check as a real client would do it
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
# API configuration
|
||||
API_URL = "https://api-software-undso.intelsight.de"
|
||||
API_KEY = "AF-2025-8E57CA6A97E257C5FA3E7778B8B44413"
|
||||
|
||||
def test_client_workflow():
|
||||
"""Test the complete client workflow: heartbeat + version check"""
|
||||
|
||||
print("=" * 60)
|
||||
print("Client Version Check Workflow Test")
|
||||
print("=" * 60)
|
||||
|
||||
# Simulate a real license key (you'll need to provide a real one for full testing)
|
||||
license_key = "DEMO-2025-ABCD-EFGH-IJKL"
|
||||
session_token = "test-session-123"
|
||||
|
||||
# 1. Test session heartbeat (simulating what works)
|
||||
print(f"\n[{datetime.now()}] 1. Testing session heartbeat...")
|
||||
|
||||
headers = {
|
||||
"X-API-Key": API_KEY,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
heartbeat_data = {
|
||||
"session_token": session_token
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{API_URL}/api/license/session/heartbeat",
|
||||
headers=headers,
|
||||
json=heartbeat_data,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
print(f"Heartbeat Status: {response.status_code}")
|
||||
if response.status_code == 200:
|
||||
print("SUCCESS: Heartbeat works")
|
||||
else:
|
||||
print(f"Response: {response.text}")
|
||||
except Exception as e:
|
||||
print(f"ERROR: {str(e)}")
|
||||
|
||||
# 2. Test version check (what was failing before)
|
||||
print(f"\n[{datetime.now()}] 2. Testing version check...")
|
||||
|
||||
version_data = {
|
||||
"license_key": license_key,
|
||||
"current_version": "1.0.0"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{API_URL}/api/version/check",
|
||||
headers=headers,
|
||||
json=version_data,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
print(f"Version Check Status: {response.status_code}")
|
||||
if response.status_code == 200:
|
||||
print("SUCCESS: Version check now works with same authentication!")
|
||||
result = response.json()
|
||||
print(f"Update Available: {result.get('update_available', False)}")
|
||||
print(f"Current Version: {result.get('current_version')}")
|
||||
print(f"Latest Version: {result.get('latest_version')}")
|
||||
if result.get('update_available'):
|
||||
print(f"Download URL: {result.get('download_url')}")
|
||||
print(f"Release Notes: {result.get('release_notes')}")
|
||||
else:
|
||||
print(f"Response: {response.text}")
|
||||
except Exception as e:
|
||||
print(f"ERROR: {str(e)}")
|
||||
|
||||
# 3. Test with different versions to check update detection
|
||||
print(f"\n[{datetime.now()}] 3. Testing with older version...")
|
||||
|
||||
old_version_data = {
|
||||
"license_key": license_key,
|
||||
"current_version": "0.9.0"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{API_URL}/api/version/check",
|
||||
headers=headers,
|
||||
json=old_version_data,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
print(f"Old Version Check Status: {response.status_code}")
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print(f"Update Available: {result.get('update_available', False)}")
|
||||
print(f"Is Mandatory: {result.get('is_mandatory', False)}")
|
||||
print(f"Current: {result.get('current_version')} -> Latest: {result.get('latest_version')}")
|
||||
else:
|
||||
print(f"Response: {response.text}")
|
||||
except Exception as e:
|
||||
print(f"ERROR: {str(e)}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Summary: Version check endpoint now uses X-API-Key authentication")
|
||||
print(" and is consistent with other license endpoints!")
|
||||
print("=" * 60)
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_client_workflow()
|
||||
115
test_version_endpoint.py
Normale Datei
115
test_version_endpoint.py
Normale Datei
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test the version check endpoint with X-API-Key authentication
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
# API configuration
|
||||
API_URL = "https://api-software-undso.intelsight.de"
|
||||
API_KEY = "AF-2025-8E57CA6A97E257C5FA3E7778B8B44413" # System API key
|
||||
|
||||
def test_version_check():
|
||||
"""Test the /api/version/check endpoint"""
|
||||
|
||||
print(f"\n[{datetime.now()}] Testing version check endpoint...")
|
||||
|
||||
# Test data
|
||||
test_data = {
|
||||
"license_key": "TEST-LICENSE-KEY",
|
||||
"current_version": "1.0.0"
|
||||
}
|
||||
|
||||
# Test with X-API-Key header (should work now)
|
||||
headers = {
|
||||
"X-API-Key": API_KEY,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{API_URL}/api/version/check",
|
||||
headers=headers,
|
||||
json=test_data,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
print(f"Status Code: {response.status_code}")
|
||||
print(f"Headers: {dict(response.headers)}")
|
||||
|
||||
if response.status_code == 200:
|
||||
print("SUCCESS: Version check now works with X-API-Key!")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}")
|
||||
else:
|
||||
print(f"FAILED: Status {response.status_code}")
|
||||
print(f"Response: {response.text}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"ERROR: {str(e)}")
|
||||
|
||||
# Also test with Authorization Bearer (should fail now)
|
||||
print(f"\n[{datetime.now()}] Testing with old Authorization Bearer (should fail)...")
|
||||
|
||||
headers_bearer = {
|
||||
"Authorization": f"Bearer {API_KEY}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{API_URL}/api/version/check",
|
||||
headers=headers_bearer,
|
||||
json=test_data,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
print(f"Status Code: {response.status_code}")
|
||||
if response.status_code == 401:
|
||||
print("EXPECTED: Bearer authentication correctly rejected")
|
||||
else:
|
||||
print(f"UNEXPECTED: Got status {response.status_code}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"ERROR: {str(e)}")
|
||||
|
||||
def test_latest_version():
|
||||
"""Test the /api/version/latest endpoint"""
|
||||
|
||||
print(f"\n[{datetime.now()}] Testing latest version endpoint...")
|
||||
|
||||
headers = {
|
||||
"X-API-Key": API_KEY
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{API_URL}/api/version/latest",
|
||||
headers=headers,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
print(f"Status Code: {response.status_code}")
|
||||
|
||||
if response.status_code == 200:
|
||||
print("SUCCESS: Latest version endpoint works!")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}")
|
||||
else:
|
||||
print(f"FAILED: Status {response.status_code}")
|
||||
print(f"Response: {response.text}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"ERROR: {str(e)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("Version Endpoint Authentication Test")
|
||||
print("=" * 60)
|
||||
|
||||
test_version_check()
|
||||
test_latest_version()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Test completed")
|
||||
print("=" * 60)
|
||||
@@ -5,7 +5,7 @@ from packaging import version
|
||||
from app.db.database import get_db
|
||||
from app.models.models import Version, License
|
||||
from app.schemas.license import VersionCheckRequest, VersionCheckResponse
|
||||
from app.core.security import get_api_key
|
||||
from app.core.api_key_auth import validate_api_key
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -13,7 +13,7 @@ router = APIRouter()
|
||||
async def check_version(
|
||||
request: VersionCheckRequest,
|
||||
db: Session = Depends(get_db),
|
||||
api_key = Depends(get_api_key)
|
||||
api_key: str = Depends(validate_api_key)
|
||||
):
|
||||
license = db.query(License).filter(
|
||||
License.license_key == request.license_key,
|
||||
@@ -63,7 +63,7 @@ async def check_version(
|
||||
@router.get("/latest")
|
||||
async def get_latest_version(
|
||||
db: Session = Depends(get_db),
|
||||
api_key = Depends(get_api_key)
|
||||
api_key: str = Depends(validate_api_key)
|
||||
):
|
||||
latest_version = db.query(Version).order_by(Version.release_date.desc()).first()
|
||||
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren