Fix auth to use form data instead of JSON

L2 server now uses HTML form endpoints for login/register.
Updated client to:
- Send form data instead of JSON
- Extract token from cookie response
- Decode JWT to get username and expiry
- Handle HTML success/error responses

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-11 15:36:59 +00:00
parent 2b1e699ab0
commit e642ffe301

View File

@@ -102,17 +102,48 @@ def cli(ctx, server, l2):
def login(username, password):
"""Login to get access token."""
try:
# Server expects form data, not JSON
resp = requests.post(
f"{get_l2_server()}/auth/login",
json={"username": username, "password": password}
data={"username": username, "password": password}
)
if resp.status_code == 200:
token_data = resp.json()
# Check if we got a token back in a cookie
if "auth_token" in resp.cookies:
token = resp.cookies["auth_token"]
# Decode token to get username and expiry
import base64
try:
# JWT format: header.payload.signature
payload = token.split(".")[1]
# Add padding if needed
payload += "=" * (4 - len(payload) % 4)
decoded = json.loads(base64.urlsafe_b64decode(payload))
token_data = {
"access_token": token,
"username": decoded.get("username", username),
"expires_at": decoded.get("exp", "")
}
save_token(token_data)
click.echo(f"Logged in as {token_data['username']}")
if token_data.get("expires_at"):
click.echo(f"Token expires: {token_data['expires_at']}")
except Exception:
# If we can't decode, just save the token
save_token({"access_token": token, "username": username})
click.echo(f"Logged in as {username}")
else:
click.echo(f"Login failed: {resp.json().get('detail', 'Unknown error')}", err=True)
# HTML response - check for success/error
if "successful" in resp.text.lower():
click.echo(f"Login successful but no token received. Try logging in via web browser.")
elif "invalid" in resp.text.lower():
click.echo(f"Login failed: Invalid username or password", err=True)
sys.exit(1)
else:
click.echo(f"Login failed: {resp.text}", err=True)
sys.exit(1)
else:
click.echo(f"Login failed: {resp.text}", err=True)
sys.exit(1)
except requests.RequestException as e:
click.echo(f"Login failed: {e}", err=True)
@@ -126,16 +157,51 @@ def login(username, password):
def register(username, password, email):
"""Register a new account."""
try:
# Server expects form data, not JSON
form_data = {
"username": username,
"password": password,
"password2": password,
}
if email:
form_data["email"] = email
resp = requests.post(
f"{get_l2_server()}/auth/register",
json={"username": username, "password": password, "email": email}
data=form_data
)
if resp.status_code == 200:
token_data = resp.json()
# Check if we got a token back in a cookie
if "auth_token" in resp.cookies:
token = resp.cookies["auth_token"]
# Decode token to get username and expiry
import base64
try:
# JWT format: header.payload.signature
payload = token.split(".")[1]
# Add padding if needed
payload += "=" * (4 - len(payload) % 4)
decoded = json.loads(base64.urlsafe_b64decode(payload))
token_data = {
"access_token": token,
"username": decoded.get("username", username),
"expires_at": decoded.get("exp", "")
}
save_token(token_data)
click.echo(f"Registered and logged in as {token_data['username']}")
except Exception:
# If we can't decode, just save the token
save_token({"access_token": token, "username": username})
click.echo(f"Registered and logged in as {username}")
else:
click.echo(f"Registration failed: {resp.json().get('detail', 'Unknown error')}", err=True)
# HTML response - registration successful
if "successful" in resp.text.lower():
click.echo(f"Registered as {username}. Please login to get a token.")
else:
click.echo(f"Registration failed: {resp.text}", err=True)
sys.exit(1)
else:
click.echo(f"Registration failed: {resp.text}", err=True)
sys.exit(1)
except requests.RequestException as e:
click.echo(f"Registration failed: {e}", err=True)