mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 10:13:58 +00:00
- Copy pg-knoe-auth/ wholesale from upstream/knoe-db/20260523 (Task 1 of docs/plans/junie/upstream-knoe-db-20260523-integration.md). - Extension: PG18 OAUTHBEARER JWT validator using libcurl + OpenSSL RS256. - knoe-db/Dockerfile: add libcurl4-openssl-dev to dev deps; COPY src/ and build with make USE_PGXS=1 install after tds_fdw. - NOT enabled in the default database build (absent from 20_create_extensions.sh). To enable: CREATE EXTENSION pg_knoe_auth; (requires pg_hba.conf oauth_issuer). Closes Task 1 of upstream-knoe-db-20260523-integration.md.
67 lines
2.0 KiB
C
67 lines
2.0 KiB
C
/*
|
|
* test_alg_validation.c — unit tests for H1: JWT alg header validation.
|
|
*
|
|
* Tests that only RS256 is accepted; alg=none, alg=HS256, missing alg all fail.
|
|
* See docs/plans/junie/pg_knoe_auth-rename-harden-modularize.md §2.2.1
|
|
*/
|
|
#include "test_helpers.h"
|
|
|
|
/*
|
|
* Inline the alg-check logic from pg_knoe_auth.c so we can test it without
|
|
* linking against PostgreSQL. The logic is: extract "alg" from a JSON
|
|
* header string and reject anything that isn't "RS256".
|
|
*/
|
|
|
|
/* Minimal json_get_string (same logic as production code) */
|
|
static char *
|
|
json_get_string(const char *json, const char *key)
|
|
{
|
|
char search[256];
|
|
const char *p, *start, *end;
|
|
size_t len;
|
|
|
|
snprintf(search, sizeof(search), "\"%s\"", key);
|
|
p = strstr(json, search);
|
|
if (!p) return NULL;
|
|
p += strlen(search);
|
|
while (*p == ' ' || *p == '\t') p++;
|
|
if (*p != ':') return NULL;
|
|
p++;
|
|
while (*p == ' ' || *p == '\t') p++;
|
|
if (*p != '"') return NULL;
|
|
p++;
|
|
start = p;
|
|
while (*p && *p != '"') { if (*p == '\\') p++; if (*p) p++; }
|
|
end = p;
|
|
len = (size_t)(end - start);
|
|
return pnstrdup(start, len);
|
|
}
|
|
|
|
/* Returns true if alg is valid (RS256), false otherwise — mirrors H1 logic */
|
|
static bool
|
|
alg_is_valid(const char *header_json)
|
|
{
|
|
char *alg = json_get_string(header_json, "alg");
|
|
bool ok = alg && strcmp(alg, "RS256") == 0;
|
|
if (alg) pfree(alg);
|
|
return ok;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
ASSERT(!alg_is_valid("{\"alg\":\"none\",\"typ\":\"JWT\"}"),
|
|
"alg=none is rejected");
|
|
ASSERT(!alg_is_valid("{\"alg\":\"HS256\",\"typ\":\"JWT\"}"),
|
|
"alg=HS256 is rejected");
|
|
ASSERT(!alg_is_valid("{\"alg\":\"RS512\",\"typ\":\"JWT\"}"),
|
|
"alg=RS512 is rejected");
|
|
ASSERT(!alg_is_valid("{\"typ\":\"JWT\"}"),
|
|
"missing alg is rejected");
|
|
ASSERT( alg_is_valid("{\"alg\":\"RS256\",\"typ\":\"JWT\"}"),
|
|
"alg=RS256 is accepted");
|
|
ASSERT( alg_is_valid("{\"kid\":\"k1\",\"alg\":\"RS256\",\"typ\":\"JWT\"}"),
|
|
"alg=RS256 with kid is accepted");
|
|
|
|
TEST_SUMMARY();
|
|
}
|