-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Login as iOS bodyweight app #2
Labels
documentation
Improvements or additions to documentation
Comments
To make the code above working again, the User Agent must be updated to The complete code now is: import base64
import hashlib
import hmac
from datetime import datetime, timezone
from typing import Dict
import httpx
MAC_KEY = b'2f8562ec236faf401289537f8a8d53921f3aaab8b56533b5ba2c9006c41e48ea316b65212d59b12e3338c090d2a1f19645a11a2be931bf013188f2da47caecec'
MSG_PREFIX = b"e@*GE(eHj(!+XHlUShWpCDxct0}c=4"
LOGIN_URL = "https://api.freeletics.com/user/v2/password/authentication"
LOGOUT_URL = "https://api.freeletics.com/user/v1/auth/logout"
USER_AGENT = "bodyweight-ios-23491000 (iPhone; iOS 17.2.1; Freeletics 23.49.1; com.Freeletics.Freeletics-Lite; de_DE; MESZ; release)"
def timestamp_ms_now() -> int:
return int(datetime.now(tz=timezone.utc).timestamp() * 1000)
class MessageSigner:
def __init__(self) -> None:
self._signer = hmac.new(MAC_KEY, msg=MSG_PREFIX, digestmod=hashlib.sha256)
def sign(self, data: bytes, timestamp: int) -> bytes:
signer = self._signer.copy()
encoded_timestamp = str(timestamp).encode()
encoded_data = base64.b64encode(data)
signer.update(encoded_data)
signer.update(encoded_timestamp)
msg_digest = signer.digest()
return base64.b64encode(msg_digest)
def get_request_headers(self, data: bytes, timestamp: int) -> Dict[str, str]:
signature = self.sign(data, timestamp)
return {
"X-Authorization-Timestamp": str(timestamp),
"X-Authorization": signature.decode()
}
class LoginAuthorizer(httpx.Auth):
"""Login request authenticator for the httpx package."""
requires_request_body = True
signer = MessageSigner()
def auth_flow(self, request: httpx.Request):
timestamp = timestamp_ms_now()
headers = self.signer.get_request_headers(request.content, timestamp)
request.headers.update(headers)
yield request
login_authorizer = LoginAuthorizer()
async def login(username: str, password: str):
async with httpx.AsyncClient(auth=login_authorizer) as client:
body = {"authentication": {"email": username, "password": password}}
headers = {"User-Agent": USER_AGENT}
resp = await client.post(LOGIN_URL, json=body, headers=headers)
if resp.status_code != 201:
raise Exception()
return resp.json()
if __name__ == "__main__":
import asyncio
user = "USERMAIL"
pw = "USERPASS"
login_response = asyncio.run(login(user, pw))
print(login_response) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Login to Freeletics bodyweight app requires a
X-Authorization
andX-Authorization-Timestamp
header. To prevent these, I used the User-Agent from the Nutrion app in the past, which don’t require these.Now I have found out how to create these required headers.
The text was updated successfully, but these errors were encountered: