code wiki / _hdl_build / nx_apistack_oidc_gate.nx

nx_apistack_oidc_gate.nx source

↩ module page · 54 lines · 3663 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_apistack_oidc_gate.nx -- hermetic gate for CAP-API-OIDC. Proves JWT structure validation, a base64url 4// encode/decode round-trip, and claim extraction from a real (self-built) JWT payload. expect_exit: 0 5import "nx_syscalls.nx" 6import "nx_apistack_oidc.nx" 7import "nx_gate_verdict.nx" 8 9func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 10" as *u8); return ok } 11func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func g_app(buf: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){buf[off+i]=s[i];i=i+1} return off+i } 13func g_eq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 } 14 15func main(argc: i64, argv: *i64) -> i64 { 16 gp("=== nx_apistack_oidc_gate (JWT parse + base64url + claim extract) ===\n" as *u8) 17 var pass: i64 = 0; var fail: i64 = 0 18 19 // T1/T2 structure 20 if oidc_valid_structure("h.p.s" as *u8, 5) == 1 { pass=pass+1; gp(" T1 3-part JWT -> valid structure PASS\n" as *u8) } else { fail=fail+1; gp(" T1 FAIL\n" as *u8) } 21 if oidc_valid_structure("h.p" as *u8, 3) == 0 { pass=pass+1; gp(" T2 2-part -> invalid structure PASS\n" as *u8) } else { fail=fail+1; gp(" T2 FAIL\n" as *u8) } 22 23 // T3 base64url encode/decode round-trip 24 let enc: *u8 = sys_mmap(256); let en: i64 = oidc_b64url_encode("hello" as *u8, 5, enc) 25 let dec: *u8 = sys_mmap(256); let dn: i64 = oidc_b64url_decode(enc, en, dec) 26 if dn == 5 { if g_eq(dec, "hello" as *u8, 5) == 1 { pass=pass+1; gp(" T3 b64url encode->decode round-trip PASS\n" as *u8) } else { fail=fail+1; gp(" T3 FAIL content\n" as *u8) } } else { fail=fail+1; gp(" T3 FAIL len=" as *u8); gn(dn); gp("\n" as *u8) } 27 28 // build a JWT with payload {"sub":"ops","level":"3"} 29 let pl: *u8 = "{\"sub\":\"ops\",\"level\":\"3\"}" as *u8; let pln: i64 = g_slen(pl) 30 let penc: *u8 = sys_mmap(512); let pen: i64 = oidc_b64url_encode(pl, pln, penc) 31 let jwt: *u8 = sys_mmap(1024); var jn: i64 = g_app(jwt, 0, "aGVhZGVy." as *u8) 32 var i: i64 = 0; while i < pen { jwt[jn] = penc[i]; jn = jn + 1; i = i + 1 } 33 jn = g_app(jwt, jn, ".c2ln" as *u8) 34 35 // T4 extract sub 36 let o1: *u8 = sys_mmap(128); let n1: i64 = oidc_extract_claim(jwt, jn, "sub" as *u8, 3, o1, 128) 37 gp(" claim sub='" as *u8); sys_write(1, o1, n1); gp("'\n" as *u8) 38 if g_eq(o1, "ops" as *u8, 3) == 1 { if n1 == 3 { pass=pass+1; gp(" T4 extract claim sub -> 'ops' PASS\n" as *u8) } else { fail=fail+1; gp(" T4 FAIL len\n" as *u8) } } else { fail=fail+1; gp(" T4 FAIL\n" as *u8) } 39 40 // T5 extract level 41 let o2: *u8 = sys_mmap(128); let n2: i64 = oidc_extract_claim(jwt, jn, "level" as *u8, 5, o2, 128) 42 if g_eq(o2, "3" as *u8, 1) == 1 { if n2 == 1 { pass=pass+1; gp(" T5 extract claim level -> '3' PASS\n" as *u8) } else { fail=fail+1; gp(" T5 FAIL len\n" as *u8) } } else { fail=fail+1; gp(" T5 FAIL\n" as *u8) } 43 44 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail) 45 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 46 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 47 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 48 let ctr__dry: *i64 = gv_ctr() 49 ctr__dry[0] = pass 50 ctr__dry[1] = pass + fail 51 let rc__dry: i64 = gv_verdict("APISTACK-OIDC-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 52 sys_exit(rc__dry) 53 return rc__dry 54}