Fix UDM-SE authentication error by skipping meta.rc check for auth endpoint
The authentication endpoint /api/auth/login returns HTTP 200 with a different JSON response format than data endpoints. UDM-SE (UniFi OS) does not include the meta.rc field in authentication responses, causing false authentication failures. Changes: - Added skip_meta_check parameter to _request_json() method - Updated _login() to skip meta.rc validation for auth endpoint - Added debug logging to show actual API responses for troubleshooting Fixes authentication error: "UniFi API error: Unknown error" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
d42fd83d5d
commit
c157595ee3
@ -47,24 +47,25 @@ class UnifiClient:
|
|||||||
# Login to get session token
|
# Login to get session token
|
||||||
self._login()
|
self._login()
|
||||||
|
|
||||||
def _request_json(self, endpoint: str, method: str = 'GET',
|
def _request_json(self, endpoint: str, method: str = 'GET',
|
||||||
data: Optional[dict] = None) -> dict:
|
data: Optional[dict] = None, skip_meta_check: bool = False) -> dict:
|
||||||
"""
|
"""
|
||||||
Make a request to the UniFi API and return JSON response.
|
Make a request to the UniFi API and return JSON response.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
endpoint: API endpoint path
|
endpoint: API endpoint path
|
||||||
method: HTTP method (GET, POST, etc.)
|
method: HTTP method (GET, POST, etc.)
|
||||||
data: Optional data for POST requests
|
data: Optional data for POST requests
|
||||||
|
skip_meta_check: Skip meta.rc validation (for auth endpoints)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict: JSON response
|
dict: JSON response
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
UniFiDataError: If request fails or returns invalid data
|
UniFiDataError: If request fails or returns invalid data
|
||||||
"""
|
"""
|
||||||
url = f"{self.base_url}{endpoint}"
|
url = f"{self.base_url}{endpoint}"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if method == 'GET':
|
if method == 'GET':
|
||||||
response = self.session.get(url, verify=self.verify_ssl, timeout=30)
|
response = self.session.get(url, verify=self.verify_ssl, timeout=30)
|
||||||
@ -72,22 +73,25 @@ class UnifiClient:
|
|||||||
response = self.session.post(url, json=data, verify=self.verify_ssl, timeout=30)
|
response = self.session.post(url, json=data, verify=self.verify_ssl, timeout=30)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported HTTP method: {method}")
|
raise ValueError(f"Unsupported HTTP method: {method}")
|
||||||
|
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
json_response = response.json()
|
json_response = response.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise UniFiDataError(f"Invalid JSON response from {endpoint}")
|
raise UniFiDataError(f"Invalid JSON response from {endpoint}")
|
||||||
|
|
||||||
# Check for UniFi API error response
|
self.logger.debug(f"Response from {endpoint}: {json_response}")
|
||||||
if isinstance(json_response, dict):
|
|
||||||
|
# Check for UniFi API error response (skip for authentication endpoints)
|
||||||
|
if not skip_meta_check and isinstance(json_response, dict):
|
||||||
if json_response.get('meta', {}).get('rc') != 'ok':
|
if json_response.get('meta', {}).get('rc') != 'ok':
|
||||||
error_msg = json_response.get('meta', {}).get('msg', 'Unknown error')
|
error_msg = json_response.get('meta', {}).get('msg', 'Unknown error')
|
||||||
|
self.logger.debug(f"Meta check failed. Response: {json_response}")
|
||||||
raise UniFiDataError(f"UniFi API error: {error_msg}")
|
raise UniFiDataError(f"UniFi API error: {error_msg}")
|
||||||
|
|
||||||
return json_response
|
return json_response
|
||||||
|
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
self.logger.error(f"Request to {endpoint} failed: {e}")
|
self.logger.error(f"Request to {endpoint} failed: {e}")
|
||||||
raise UniFiDataError(f"Request failed: {e}")
|
raise UniFiDataError(f"Request failed: {e}")
|
||||||
@ -95,7 +99,7 @@ class UnifiClient:
|
|||||||
def _login(self):
|
def _login(self):
|
||||||
"""
|
"""
|
||||||
Authenticate with the UniFi controller.
|
Authenticate with the UniFi controller.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
AuthenticationError: If authentication fails
|
AuthenticationError: If authentication fails
|
||||||
"""
|
"""
|
||||||
@ -103,11 +107,14 @@ class UnifiClient:
|
|||||||
'username': self.username,
|
'username': self.username,
|
||||||
'password': self.password
|
'password': self.password
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = self._request_json('/api/auth/login', method='POST', data=login_data)
|
# Skip meta.rc check for auth endpoint - UDM-SE uses different response format
|
||||||
self.logger.debug("Successfully authenticated with UniFi controller")
|
response = self._request_json('/api/auth/login', method='POST',
|
||||||
|
data=login_data, skip_meta_check=True)
|
||||||
|
self.logger.debug(f"Successfully authenticated with UniFi controller")
|
||||||
|
self.logger.debug(f"Authentication response: {response}")
|
||||||
|
|
||||||
except UniFiDataError as e:
|
except UniFiDataError as e:
|
||||||
self.logger.error(f"Authentication failed: {e}")
|
self.logger.error(f"Authentication failed: {e}")
|
||||||
raise AuthenticationError(f"Failed to authenticate: {e}")
|
raise AuthenticationError(f"Failed to authenticate: {e}")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user