code wiki / (root) / nx_bearer_auth.nx

nx_bearer_auth.nx source

↩ module page · 133 lines · 4560 B

1// bearer_auth.nx -- extract Bearer tokens from Authorization header. 2// 3// RFC 6750. The modern HTTP auth scheme for OAuth 2.0, JWT, 4// API keys, and general \"the client holds a secret and presents 5// it\" flows. Trivial algorithmically but worth isolating behind 6// a helper so callers don't re-invent the case-insensitive prefix 7// parse + whitespace handling every time. 8// 9// Authorization: Bearer eyJhbGciOi... 10// ^^^^^^ ^^^^^^^^^^^^^ 11// scheme token (opaque to HTTP) 12// 13// The token format itself (JWT / opaque random / signed session) 14// is caller's concern -- we just peel the \"Bearer \" prefix. 15// 16// Invariants: 17// BA1 Scheme match is case-insensitive per RFC 7235 ยง2.1. 18// BA2 Token is returned as (offset, length) into the caller's 19// buffer -- zero-alloc. 20// BA3 Multiple whitespace tolerated between scheme and token 21// (RFC permits 1 or more SP between credentials parts). 22 23// nx_safety_envelope: 24// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 25// sil_target: SIL1 26// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 27// verdict: NOT_YET_EVALUATED 28 29import "nx_syscalls.nx" 30 31const BR_ERR_FORMAT: i64 = -1 32const BR_ERR_SHORT: i64 = -2 33 34// ASCII lowercase. 35func br_lower(b: i64) -> i64 { 36 if b >= 0x41 { 37 if b <= 0x5A { return b + 0x20 } 38 } 39 return b 40} 41 42// Match the literal \"bearer\" case-insensitively at offset. 43func br_is_bearer(buf: *u8, off: i64, n: i64) -> i64 { 44 if n < off + 6 { return 0 } 45 if br_lower(buf[off]) != 0x62 { return 0 } // 'b' 46 if br_lower(buf[off + 1]) != 0x65 { return 0 } // 'e' 47 if br_lower(buf[off + 2]) != 0x61 { return 0 } // 'a' 48 if br_lower(buf[off + 3]) != 0x72 { return 0 } // 'r' 49 if br_lower(buf[off + 4]) != 0x65 { return 0 } // 'e' 50 if br_lower(buf[off + 5]) != 0x72 { return 0 } // 'r' 51 return 1 52} 53 54// Extract the Bearer token from an Authorization header VALUE 55// (not the full header; caller strips \"Authorization: \" first). 56// Writes (offset, length) of the token into *tok_off and *tok_len. 57// Returns 0 on success, negative on failure. 58func bearer_auth_extract(hdr: *u8, n: i64, 59 tok_off: *i64, tok_len: *i64) -> i64 { 60 if n < 7 { return BR_ERR_SHORT } 61 if br_is_bearer(hdr, 0, n) != 1 { return BR_ERR_FORMAT } 62 // Must be followed by at least one space. 63 var i: i64 = 6 64 if hdr[i] != 0x20 { return BR_ERR_FORMAT } 65 // Skip run of spaces. 66 while i < n { 67 if hdr[i] != 0x20 { break } 68 i = i + 1 69 } 70 if i >= n { return BR_ERR_FORMAT } 71 72 // Token runs to end-of-input or first whitespace (RFC permits 73 // trailing whitespace / additional fields in some grammars 74 // but for Authorization they're not standard). 75 let start: i64 = i 76 while i < n { 77 if hdr[i] == 0x20 { break } 78 if hdr[i] == 0x09 { break } 79 if hdr[i] == 0x0D { break } 80 if hdr[i] == 0x0A { break } 81 i = i + 1 82 } 83 *tok_off = start 84 *tok_len = i - start 85 return 0 86} 87 88// Convenience: returns 1 if the header starts with \"Bearer\" 89// (case-insensitive) and has at least some token content. 90func bearer_auth_is_present(hdr: *u8, n: i64) -> i64 { 91 let off: *i64 = (sys_mmap(16)) as *i64 92 let len: *i64 = (sys_mmap(16)) as *i64 93 if bearer_auth_extract(hdr, n, off, len) != 0 { return 0 } 94 if *len == 0 { return 0 } 95 return 1 96} 97 98// Compile-only smoke. 99func main() -> i64 { 100 let off: *i64 = (sys_mmap(16)) as *i64 101 let len: *i64 = (sys_mmap(16)) as *i64 102 103 // Happy path. 104 let hdr: *u8 = "Bearer eyJhbGciOiJIUzI1NiJ9" 105 if bearer_auth_extract(hdr, 27, off, len) != 0 { return 1 } 106 if *off != 7 { return 2 } 107 if *len != 20 { return 3 } 108 if hdr[*off] != 0x65 { return 4 } // 'e' 109 110 // Lowercase scheme. 111 let hdr2: *u8 = "bearer abc" 112 if bearer_auth_extract(hdr2, 10, off, len) != 0 { return 5 } 113 if *off != 7 { return 6 } 114 if *len != 3 { return 7 } 115 116 // Multiple spaces between scheme and token. 117 let hdr3: *u8 = "Bearer xyz" 118 if bearer_auth_extract(hdr3, 12, off, len) != 0 { return 8 } 119 if *off != 9 { return 9 } 120 if *len != 3 { return 10 } 121 122 // Wrong scheme -> error. 123 let hdr4: *u8 = "Basic dXNlcjpwYXNz" 124 if bearer_auth_extract(hdr4, 18, off, len) != BR_ERR_FORMAT { 125 return 11 126 } 127 128 // Presence helper. 129 if bearer_auth_is_present(hdr, 27) != 1 { return 12 } 130 if bearer_auth_is_present(hdr4, 18) != 0 { return 13 } 131 132 return 0 133}