Skip to content

Commit

Permalink
use ips directly
Browse files Browse the repository at this point in the history
  • Loading branch information
bjia56 committed May 18, 2023
1 parent 30f54c9 commit 0a020f2
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 9 deletions.
34 changes: 28 additions & 6 deletions plugins/arlo/src/arlo_plugin/arlo/arlo_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
# Import helper classes that are part of this library.

from .request import Request
from .host_picker import pick_host
from .mqtt_stream_async import MQTTStream
from .sse_stream_async import EventStream
from .logging import logger
Expand Down Expand Up @@ -79,8 +80,21 @@ def change_stream_class(s_class):
class Arlo(object):
BASE_URL = 'my.arlo.com'
AUTH_URL = 'ocapi-app.arlo.com'
AUTH_HOSTS = [
'NTIuMTYuMTM4LjI=',
'NjMuMzIuODEuMjE4',
'MzQuMjQ2LjIzOS4xNzk=',
'NTQuNzMuMjI5LjUz',
'MzQuMjUwLjE4MC4xOTA=',
'MzQuMjU0LjIxNS4xOTQ=',
'MzQuMjQzLjkwLjIwMA==',
'NTQuNzIuMjI0LjI0Mg==',
'MzQuMjUyLjIyMS40Ng==',
]
TRANSID_PREFIX = 'web'

random.shuffle(AUTH_HOSTS)

def __init__(self, username, password):
self.username = username
self.password = password
Expand Down Expand Up @@ -138,9 +152,14 @@ def UseExistingAuth(self, user_id, headers):
self.BASE_URL = 'myapi.arlo.com'

def LoginMFA(self):
self.request = Request()
self.request = Request(mode="ip")
device_id = str(uuid.uuid4())

auth_host = pick_host([
base64.b64decode(h.encode("utf-8")).decode("utf-8")
for h in self.AUTH_HOSTS
], self.AUTH_URL)

# Authenticate
headers = {
'DNT': '1',
Expand All @@ -155,10 +174,11 @@ def LoginMFA(self):
'x-user-device-id': device_id,
'x-user-device-automation-name': 'QlJPV1NFUg==',
'x-user-device-type': 'BROWSER',
'Host': self.AUTH_URL,
}
self.request.options(f'https://{self.AUTH_URL}/api/auth', headers=headers)
self.request.options(f'https://{auth_host}/api/auth', headers=headers)
auth_body = self.request.post(
f'https://{self.AUTH_URL}/api/auth',
f'https://{auth_host}/api/auth',
params={
'email': self.username,
'password': str(base64.b64encode(self.password.encode('utf-8')), 'utf-8'),
Expand All @@ -173,7 +193,7 @@ def LoginMFA(self):

# Retrieve MFA factor id
factors_body = self.request.get(
f'https://{self.AUTH_URL}/api/getFactors',
f'https://{auth_host}/api/getFactors',
params={'data': auth_body['data']['issued']},
headers=headers,
raw=True
Expand All @@ -186,7 +206,7 @@ def LoginMFA(self):

# Start factor auth
start_auth_body = self.request.post(
f'https://{self.AUTH_URL}/api/startAuth',
f'https://{auth_host}/api/startAuth',
params={'factorId': factor_id},
headers=headers,
raw=True
Expand All @@ -197,7 +217,7 @@ def complete_auth(code):
nonlocal self, factor_auth_code, headers

finish_auth_body = self.request.post(
f'https://{self.AUTH_URL}/api/finishAuth',
f'https://{auth_host}/api/finishAuth',
params={
'factorAuthCode': factor_auth_code,
'otp': code
Expand All @@ -206,6 +226,8 @@ def complete_auth(code):
raw=True
)

self.request = Request()

# Update Authorization code with new code
headers = {
'Auth-Version': '2',
Expand Down
18 changes: 18 additions & 0 deletions plugins/arlo/src/arlo_plugin/arlo/host_picker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import ssl
from socket import setdefaulttimeout
from cryptography import x509
from cryptography.x509.oid import ExtensionOID

setdefaulttimeout(5)

def pick_host(hosts, hostname_to_match):
for host in hosts:
try:
c = ssl.get_server_certificate((host, 443))
c = x509.load_pem_x509_certificate(c.encode("utf-8"))
if hostname_to_match in c.subject.rfc4514_string() or \
hostname_to_match in c.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value.get_values_for_type(x509.DNSName):
return host
except:
print(f"{host} is invalid")
raise Exception("no valid hosts found!")
11 changes: 8 additions & 3 deletions plugins/arlo/src/arlo_plugin/arlo/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import requests
from requests.exceptions import HTTPError
from requests_toolbelt.adapters import host_header_ssl
import cloudscraper
import time
import uuid
Expand All @@ -28,9 +29,13 @@
class Request(object):
"""HTTP helper class"""

def __init__(self, timeout=5):
from .arlo_async import USER_AGENTS
self.session = cloudscraper.CloudScraper(browser={"custom": USER_AGENTS["arlo"]})
def __init__(self, timeout=5, mode="cloudscraper"):
if mode == "cloudscraper":
from .arlo_async import USER_AGENTS
self.session = cloudscraper.CloudScraper(browser={"custom": USER_AGENTS["arlo"]})
elif mode == "ip":
self.session = requests.Session()
self.session.mount('https://', host_header_ssl.HostHeaderSSLAdapter())
self.timeout = timeout

def gen_event_id(self):
Expand Down
1 change: 1 addition & 0 deletions plugins/arlo/src/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ requests==2.28.2
cachetools==5.3.0
scrypted-arlo-go==0.0.1
cloudscraper==1.2.71
cryptography==38.0.4
--extra-index-url=https://www.piwheels.org/simple/
--extra-index-url=https://bjia56.github.io/scrypted-arlo-go/
--prefer-binary

0 comments on commit 0a020f2

Please sign in to comment.