Files
Brancheneinstufung2/docs/Zierl/Ziel_1.txt

109 lines
4.2 KiB
Plaintext

envelope = f"""<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<s:Header>
<ApplicationToken xmlns="http://www.superoffice.com/superid/partnersystemuser/0.1">{APPLICATION_TOKEN}</ApplicationToken>
<ContextIdentifier xmlns="http://www.superoffice.com/superid/partnersystemuser/0.1">{CONTEXT_IDENTIFIER}</ContextIdentifier>
</s:Header>
<s:Body>
<AuthenticationRequest xmlns="http://www.superoffice.com/superid/partnersystemuser/0.1">
<SignedSystemToken>{SIGNED_SYSTEM_TOKEN}</SignedSystemToken>
<ReturnTokenType>{RETURN_TOKEN_TYPE}</ReturnTokenType>
</AuthenticationRequest>
</s:Body>
</s:Envelope>
""".strip()
headers = {
"Content-Type": "text/xml; charset=utf-8",
"SOAPAction": "http://www.superoffice.com/superid/partnersystemuser/0.1/IPartnerSystemUserService/Authenticate",
}
resp = requests.post(
SOAP_URL, data=envelope.encode("utf-8"), headers=headers, timeout=30
)
print(resp)
# --- Useful diagnostics if server responds with HTML or error ---
ct = resp.headers.get("Content-Type", "")
if "xml" not in ct.lower():
print("Unexpected response (not XML). Status:", resp.status_code)
print("Content-Type:", ct)
print(resp.text[:1200])
raise SystemExit("Check URL, SOAPAction, or required SOAP headers/values.")
# --- Parse SOAP response per WSDL ---
root = ET.fromstring(resp.text)
ns = {
"s": "http://schemas.xmlsoap.org/soap/envelope/",
"tns": "http://www.superoffice.com/superid/partnersystemuser/0.1",
}
# Fault?
fault = root.find(".//s:Fault", ns)
if fault is not None:
print(resp.text)
raise SystemExit("SOAP Fault returned. See XML above.")
# Extract AuthenticationResponse
is_ok_el = root.find(".//tns:AuthenticationResponse/tns:IsSuccessful", ns)
token_el = root.find(".//tns:AuthenticationResponse/tns:Token", ns)
err_el = root.find(".//tns:AuthenticationResponse/tns:ErrorMessage", ns)
is_ok = is_ok_el is not None and (is_ok_el.text or "").strip().lower() == "true"
token = token_el.text.strip() if token_el is not None and token_el.text else None
error_msg = (err_el.text or "").strip() if err_el is not None else ""
if not is_ok:
print("Authenticate returned IsSuccessful = false")
print("ErrorMessage:", error_msg)
print(resp.text)
raise SystemExit("Authentication failed.")
print("Authenticate succeeded.")
print("Token (truncated):", (token[:50] + "...") if token else None)
# If ReturnTokenType=Jwt, you can inspect claims to find the SOTicket claim key
if RETURN_TOKEN_TYPE.lower() == "jwt" and token and "." in token:
def b64url_decode(seg: str) -> bytes:
seg += "=" * ((4 - len(seg) % 4) % 4)
return base64.urlsafe_b64decode(seg.encode("ascii"))
header_b64, payload_b64, sig_b64 = token.split(".", 2)
payload = json.loads(b64url_decode(payload_b64))
print("JWT payload keys:", list(payload.keys()))
# Try to locate a ticket-like claim (key name may vary by env)
ticket = None
for k, v in payload.items():
if isinstance(v, str) and (
"ticket" in k.lower() or v.startswith(("7T:", "8A:", "8C:"))
):
ticket = v
break
if ticket:
print("Extracted system-user ticket:", ticket)
# Example REST call using SOTicket + SO-AppToken headers:
TENANT_BASE = (
"https://online.superoffice.com/Cust26703" # use your actual sodN host!
)
rest_headers = {
"Authorization": f"SOTicket {ticket}",
"SO-AppToken": APPLICATION_TOKEN, # same value as ApplicationToken
"Accept": "application/json",
}
test = requests.get(
f"{TENANT_BASE}/api/v1/contact/1", headers=rest_headers, timeout=30
)
print("REST test:", test.status_code, test.text)
else:
print(
"No obvious 'ticket' claim found in JWT. Inspect payload above and pick the correct claim manually."
)
else:
print(
"Returned token is not a JWT (or you requested SAML). Use the token as intended by your flow."
)