#!/usr/bin/env python3 """Read-only native authorize checks; print no state, cookies or auth tokens.""" import base64 import hashlib import json import secrets from urllib.error import HTTPError from urllib.parse import urlencode, urlsplit from urllib.request import HTTPRedirectHandler, build_opener class NoRedirect(HTTPRedirectHandler): def redirect_request(self, req, fp, code, msg, headers, newurl): return None def verify(): opener = build_opener(NoRedirect) base = { "client_id": "user-engine-portal", "response_type": "code", "redirect_uri": "https://users.92-205-62-239.nip.io/oidc/callback", "scope": "openid profile email groups", "state": secrets.token_urlsafe(24), "code_challenge": base64.urlsafe_b64encode( hashlib.sha256(secrets.token_bytes(32)).digest() ).rstrip(b"=").decode(), "code_challenge_method": "S256", } results = [] for name in ("valid", "wrong_callback", "missing_pkce"): params = dict(base) if name == "wrong_callback": params["redirect_uri"] = "https://invalid.example/oidc/callback" if name == "missing_pkce": params.pop("code_challenge") params.pop("code_challenge_method") try: response = opener.open("https://kc.coulomb.social/authorize?" + urlencode(params), timeout=20) except HTTPError as error: response = error with response: row = {"check": name, "status": response.code} if name == "valid": location = urlsplit(response.headers.get("Location", "")) row["redirect_origin"] = location.scheme + "://" + location.netloc row["passed"] = response.code == 302 and row["redirect_origin"] == "https://auth.coulomb.social" else: body = json.loads(response.read(4096)) row.update(error=body.get("error"), feature=body.get("feature")) expected = "redirect_uri" if name == "wrong_callback" else "missing_pkce" row["passed"] = response.code == 400 and row["error"] == "invalid_profile_usage" and row["feature"] == expected results.append(row) print(json.dumps(results, indent=2)) return all(row["passed"] for row in results) if __name__ == "__main__": raise SystemExit(0 if verify() else 1)