Skip to content

Commit f68f618

Browse files
committed
test: add more unit tests to test/test_proto.c
Signed-off-by: Hans Zandbelt <[email protected]>
1 parent b2864d2 commit f68f618

1 file changed

Lines changed: 167 additions & 0 deletions

File tree

test/test_proto.c

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,166 @@ START_TEST(test_proto_validate_jwt) {
270270
}
271271
END_TEST
272272

273+
START_TEST(test_proto_nonce_and_jti) {
274+
request_rec *r = oidc_test_request_get();
275+
char *nonce = NULL;
276+
ck_assert_int_eq(oidc_proto_nonce_gen(r, &nonce), TRUE);
277+
ck_assert_ptr_nonnull(nonce);
278+
279+
char *jti = oidc_proto_jti_gen(r);
280+
ck_assert_ptr_nonnull(jti);
281+
/* jti should be a non-empty string */
282+
ck_assert_int_ne(_oidc_strlen(jti), 0);
283+
}
284+
END_TEST
285+
286+
START_TEST(test_proto_supported_flows_and_check) {
287+
apr_pool_t *pool = oidc_test_pool_get();
288+
apr_array_header_t *flows = oidc_proto_supported_flows(pool);
289+
ck_assert_ptr_nonnull(flows);
290+
ck_assert_int_eq(flows->nelts, 6);
291+
292+
/* known supported flows */
293+
ck_assert_int_eq(oidc_proto_flow_is_supported(pool, "code"), TRUE);
294+
ck_assert_int_eq(oidc_proto_flow_is_supported(pool, "id_token token"), TRUE);
295+
ck_assert_int_eq(oidc_proto_flow_is_supported(pool, "unrecognized flow"), FALSE);
296+
}
297+
END_TEST
298+
299+
START_TEST(test_proto_state_getters_setters_and_string) {
300+
request_rec *r = oidc_test_request_get();
301+
oidc_proto_state_t *ps = oidc_proto_state_new();
302+
ck_assert_ptr_nonnull(ps);
303+
304+
oidc_proto_state_set_issuer(ps, "https://example.org");
305+
oidc_proto_state_set_nonce(ps, "mynonce");
306+
oidc_proto_state_set_original_url(ps, "https://example.org/orig");
307+
oidc_proto_state_set_original_method(ps, "POST");
308+
oidc_proto_state_set_response_mode(ps, "fragment");
309+
oidc_proto_state_set_response_type(ps, "id_token token");
310+
oidc_proto_state_set_state(ps, "12345");
311+
oidc_proto_state_set_prompt(ps, "none");
312+
oidc_proto_state_set_pkce_state(ps, "pkce123");
313+
oidc_proto_state_set_timestamp_now(ps);
314+
315+
ck_assert_str_eq(oidc_proto_state_get_issuer(ps), "https://example.org");
316+
ck_assert_str_eq(oidc_proto_state_get_nonce(ps), "mynonce");
317+
ck_assert_str_eq(oidc_proto_state_get_original_url(ps), "https://example.org/orig");
318+
ck_assert_str_eq(oidc_proto_state_get_original_method(ps), "POST");
319+
ck_assert_str_eq(oidc_proto_state_get_response_mode(ps), "fragment");
320+
ck_assert_str_eq(oidc_proto_state_get_response_type(ps), "id_token token");
321+
ck_assert_str_eq(oidc_proto_state_get_state(ps), "12345");
322+
ck_assert_str_eq(oidc_proto_state_get_prompt(ps), "none");
323+
ck_assert_str_eq(oidc_proto_state_get_pkce_state(ps), "pkce123");
324+
ck_assert(oidc_proto_state_get_timestamp(ps) > 0);
325+
326+
char *s = oidc_proto_state_to_string(r, ps);
327+
ck_assert_ptr_nonnull(s);
328+
/* basic sanity: string contains issuer and nonce */
329+
ck_assert_ptr_nonnull(_oidc_strstr(s, "https://example.org"));
330+
ck_assert_ptr_nonnull(_oidc_strstr(s, "mynonce"));
331+
332+
oidc_proto_state_destroy(ps);
333+
}
334+
END_TEST
335+
336+
START_TEST(test_proto_state_cookie_roundtrip) {
337+
request_rec *r = oidc_test_request_get();
338+
oidc_cfg_t *c = oidc_test_cfg_get();
339+
340+
oidc_proto_state_t *ps = oidc_proto_state_new();
341+
oidc_proto_state_set_nonce(ps, "rndnonce");
342+
oidc_proto_state_set_state(ps, "s1");
343+
oidc_proto_state_set_issuer(ps, "https://idp.example.com");
344+
oidc_proto_state_set_timestamp_now(ps);
345+
346+
char *cookie = oidc_proto_state_to_cookie(r, c, ps);
347+
ck_assert_ptr_nonnull(cookie);
348+
349+
oidc_proto_state_t *parsed = oidc_proto_state_from_cookie(r, c, cookie);
350+
ck_assert_ptr_nonnull(parsed);
351+
ck_assert_str_eq(oidc_proto_state_get_nonce(parsed), "rndnonce");
352+
ck_assert_str_eq(oidc_proto_state_get_state(parsed), "s1");
353+
ck_assert_str_eq(oidc_proto_state_get_issuer(parsed), "https://idp.example.com");
354+
355+
oidc_proto_state_destroy(ps);
356+
oidc_proto_state_destroy(parsed);
357+
}
358+
END_TEST
359+
360+
START_TEST(test_proto_pkce_plain_and_s256) {
361+
request_rec *r = oidc_test_request_get();
362+
char *state_plain = NULL;
363+
char *challenge_plain = NULL;
364+
char *verifier_plain = NULL;
365+
366+
/* plain */
367+
ck_assert_int_eq(oidc_pkce_plain.state(r, &state_plain), TRUE);
368+
ck_assert_ptr_nonnull(state_plain);
369+
ck_assert_int_eq(oidc_pkce_plain.challenge(r, state_plain, &challenge_plain), TRUE);
370+
ck_assert_ptr_nonnull(challenge_plain);
371+
ck_assert_str_eq(challenge_plain, state_plain);
372+
ck_assert_int_eq(oidc_pkce_plain.verifier(r, state_plain, &verifier_plain), TRUE);
373+
ck_assert_ptr_nonnull(verifier_plain);
374+
ck_assert_str_eq(verifier_plain, state_plain);
375+
376+
/* s256 */
377+
char *state_s256 = NULL;
378+
char *challenge_s256 = NULL;
379+
char *verifier_s256 = NULL;
380+
ck_assert_int_eq(oidc_pkce_s256.state(r, &state_s256), TRUE);
381+
ck_assert_ptr_nonnull(state_s256);
382+
ck_assert_int_eq(oidc_pkce_s256.challenge(r, state_s256, &challenge_s256), TRUE);
383+
ck_assert_ptr_nonnull(challenge_s256);
384+
ck_assert_int_ne(_oidc_strlen(challenge_s256), 0);
385+
/* s256 challenge should not equal raw state */
386+
ck_assert_int_ne(_oidc_strcmp(challenge_s256, state_s256), 0);
387+
ck_assert_int_eq(oidc_pkce_s256.verifier(r, state_s256, &verifier_s256), TRUE);
388+
ck_assert_ptr_nonnull(verifier_s256);
389+
ck_assert_str_eq(verifier_s256, state_s256);
390+
}
391+
END_TEST
392+
393+
START_TEST(test_proto_profile_helpers) {
394+
apr_pool_t *pool = oidc_test_pool_get();
395+
oidc_provider_t *provider = oidc_cfg_provider_create(pool);
396+
397+
/* default profile: token_endpoint_auth_aud returns token endpoint */
398+
oidc_cfg_provider_token_endpoint_url_set(pool, provider, "https://idp.example.com/token");
399+
ck_assert_str_eq(oidc_proto_profile_token_endpoint_auth_aud(provider), "https://idp.example.com/token");
400+
401+
/* revocation: when val=="token" should return token endpoint */
402+
oidc_cfg_provider_revocation_endpoint_url_set(pool, provider, "https://idp.example.com/rev");
403+
ck_assert_str_eq(oidc_proto_profile_revocation_endpoint_auth_aud(provider, "token"),
404+
"https://idp.example.com/token");
405+
406+
/* if profile is FAPI20 behavior changes */
407+
/* set profile to FAPI20 */
408+
oidc_cfg_provider_profile_int_set(provider, OIDC_PROFILE_FAPI20);
409+
/* token endpoint aud should now be issuer */
410+
oidc_cfg_provider_issuer_set(pool, provider, "https://idp.example.com");
411+
ck_assert_str_eq(oidc_proto_profile_token_endpoint_auth_aud(provider), "https://idp.example.com");
412+
/* pkce should be forced to S256 */
413+
ck_assert_ptr_eq(oidc_proto_profile_pkce_get(provider), &oidc_pkce_s256);
414+
/* DPoP should be required */
415+
ck_assert_int_eq(oidc_proto_profile_dpop_mode_get(provider), OIDC_DPOP_MODE_REQUIRED);
416+
/* response require iss should be true */
417+
ck_assert_int_eq(oidc_proto_profile_response_require_iss_get(provider), 1);
418+
}
419+
END_TEST
420+
421+
START_TEST(test_proto_return_www_authenticate_header) {
422+
request_rec *r = oidc_test_request_get();
423+
/* ensure no auth_name in stub (stub returns NULL) */
424+
int rc = oidc_proto_return_www_authenticate(r, "invalid_token", "bad token");
425+
ck_assert_int_eq(rc, HTTP_UNAUTHORIZED);
426+
const char *hdr = apr_table_get(r->err_headers_out, "WWW-Authenticate");
427+
ck_assert_ptr_nonnull(hdr);
428+
ck_assert_ptr_nonnull(_oidc_strstr(hdr, "invalid_token"));
429+
ck_assert_ptr_nonnull(_oidc_strstr(hdr, "bad token"));
430+
}
431+
END_TEST
432+
273433
int main(void) {
274434
TCase *core = tcase_create("core");
275435
tcase_add_checked_fixture(core, oidc_test_setup, oidc_test_teardown);
@@ -280,6 +440,13 @@ int main(void) {
280440
tcase_add_test(core, test_logout_request);
281441
tcase_add_test(core, test_proto_validate_nonce);
282442
tcase_add_test(core, test_proto_validate_jwt);
443+
tcase_add_test(core, test_proto_nonce_and_jti);
444+
tcase_add_test(core, test_proto_supported_flows_and_check);
445+
tcase_add_test(core, test_proto_state_getters_setters_and_string);
446+
tcase_add_test(core, test_proto_state_cookie_roundtrip);
447+
tcase_add_test(core, test_proto_pkce_plain_and_s256);
448+
tcase_add_test(core, test_proto_profile_helpers);
449+
tcase_add_test(core, test_proto_return_www_authenticate_header);
283450

284451
Suite *s = suite_create("proto");
285452
suite_add_tcase(s, core);

0 commit comments

Comments
 (0)