Skip to content

Instantly share code, notes, and snippets.

@e1ectr0cut1e
Forked from ancientGlider/keenetic_auth.py
Last active March 25, 2026 13:08
Show Gist options
  • Select an option

  • Save e1ectr0cut1e/b6759331c1d3d152f5a8c2e1f68fe103 to your computer and use it in GitHub Desktop.

Select an option

Save e1ectr0cut1e/b6759331c1d3d152f5a8c2e1f68fe103 to your computer and use it in GitHub Desktop.
Keenetic REST API Class with automatic auth handling (Python)
import hashlib
import requests
class KeeneticRci:
def __init__(self, address, username, password):
self.address = address
self.username = username
self.password = password
self.session = requests.session()
self._auth()
pass
def _auth(self):
response = self.session.get(f"http://{self.address}/auth")
if response.status_code == 401:
stage1_token = ":".join([self.username, response.headers["X-NDM-Realm"], self.password])
stage1_hash = hashlib.md5(stage1_token.encode('utf-8'))
stage2_token = response.headers["X-NDM-Challenge"] + stage1_hash.hexdigest()
stage2_hash = hashlib.sha256(stage2_token.encode('utf-8'))
response = self.session.post(f"http://{self.address}/auth", json={
"login": self.username,
"password": stage2_hash.hexdigest()
})
if response.status_code == 200:
return True
elif response.status_code == 200:
return True
return False
def request(self, query, json=None, try_auth=True):
if json is not None:
response = self.session.post(f"http://{self.address}/rci/{query}", json=json)
else:
response = self.session.get(f"http://{self.address}/rci/{query}")
if response.status_code == 401 and try_auth:
if not self._auth():
raise Exception("Authentication failed")
return self.request(query, json=json, try_auth=False)
return response.json()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment