Skip to content

Commit db7fde8

Browse files
author
Hans Zandbelt
committed
support passing browser cookies to OP/AS backchannel calls
1 parent 9953160 commit db7fde8

File tree

9 files changed

+109
-26
lines changed

9 files changed

+109
-26
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
12/12/2014
2+
- support passing cookies specified in OIDCPassCookies from browser on to OP/AS calls (for loadbalancing purposes)
3+
14
12/10/2014
25
- reconnect to the Redis server after I/O failure as raised in #43
36
- bump to 1.7.1rc4

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
AC_INIT([mod_auth_openidc],[1.7.1rc4],[[email protected]])
1+
AC_INIT([mod_auth_openidc],[1.7.1rc5],[[email protected]])
22

33
AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION())
44

src/config.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,16 @@ static const char * oidc_set_pass_idtoken_as(cmd_parms *cmd, void *dummy,
542542
return NULL;
543543
}
544544

545+
/*
546+
* specify cookies to pass on to the OP/AS
547+
*/
548+
static const char * oidc_set_pass_cookies(cmd_parms *cmd, void *m,
549+
const char *arg) {
550+
oidc_dir_cfg *dir_cfg = (oidc_dir_cfg *) m;
551+
*(const char**) apr_array_push(dir_cfg->pass_cookies) = arg;
552+
return NULL;
553+
}
554+
545555
/*
546556
* create a new server config record with defaults
547557
*/
@@ -902,6 +912,7 @@ void *oidc_create_dir_config(apr_pool_t *pool, char *path) {
902912
c->cookie_path = OIDC_DEFAULT_COOKIE_PATH;
903913
c->authn_header = OIDC_DEFAULT_AUTHN_HEADER;
904914
c->return401 = FALSE;
915+
c->pass_cookies = apr_array_make(pool, 0, sizeof(const char *));
905916
return (c);
906917
}
907918

@@ -921,9 +932,10 @@ void *oidc_merge_dir_config(apr_pool_t *pool, void *BASE, void *ADD) {
921932
c->authn_header = (
922933
add->authn_header != OIDC_DEFAULT_AUTHN_HEADER ?
923934
add->authn_header : base->authn_header);
924-
c->return401 = (
925-
add->return401 != FALSE ?
926-
add->return401 : base->return401);
935+
c->return401 = (add->return401 != FALSE ? add->return401 : base->return401);
936+
c->pass_cookies = (
937+
apr_is_empty_array(add->pass_cookies) != 0 ?
938+
add->pass_cookies : base->pass_cookies);
927939
return (c);
928940
}
929941

@@ -1594,6 +1606,11 @@ const command_rec oidc_config_cmds[] = {
15941606
(void*)APR_OFFSETOF(oidc_cfg, cache_redis_server),
15951607
RSRC_CONF,
15961608
"Redis server used for caching (<hostname>[:<port>])"),
1609+
AP_INIT_ITERATE("OIDCPassCookies",
1610+
oidc_set_pass_cookies,
1611+
(void *) APR_OFFSETOF(oidc_dir_cfg, pass_cookies),
1612+
RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
1613+
"Specify cookies that need to be passed from the browser on to the backend to the OP/AS."),
15971614

15981615
{ NULL }
15991616
};

src/metadata.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,10 @@ static apr_byte_t oidc_metadata_file_write(request_rec *r, const char *path,
561561
static apr_byte_t oidc_metadata_client_register(request_rec *r, oidc_cfg *cfg,
562562
oidc_provider_t *provider, json_t **j_client, const char **response) {
563563

564+
/* get a handle to the directory config */
565+
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
566+
&auth_openidc_module);
567+
564568
/* assemble the JSON registration request */
565569
json_t *data = json_object();
566570
json_object_set_new(data, "client_name",
@@ -655,7 +659,8 @@ static apr_byte_t oidc_metadata_client_register(request_rec *r, oidc_cfg *cfg,
655659
/* dynamically register the client with the specified parameters */
656660
if (oidc_util_http_post_json(r, provider->registration_endpoint_url, data,
657661
NULL, provider->registration_token, provider->ssl_validate_server, response,
658-
cfg->http_timeout_short, cfg->outgoing_proxy) == FALSE) {
662+
cfg->http_timeout_short, cfg->outgoing_proxy,
663+
dir_cfg->pass_cookies) == FALSE) {
659664
json_decref(data);
660665
return FALSE;
661666
}
@@ -673,10 +678,14 @@ static apr_byte_t oidc_metadata_jwks_retrieve_and_cache(request_rec *r,
673678

674679
const char *response = NULL;
675680

681+
/* get a handle to the directory config */
682+
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
683+
&auth_openidc_module);
684+
676685
/* no valid provider metadata, get it at the specified URL with the specified parameters */
677686
if (oidc_util_http_get(r, provider->jwks_uri, NULL, NULL,
678687
NULL, provider->ssl_validate_server, &response, cfg->http_timeout_long,
679-
cfg->outgoing_proxy) == FALSE)
688+
cfg->outgoing_proxy, dir_cfg->pass_cookies) == FALSE)
680689
return FALSE;
681690

682691
/* decode and see if it is not an error response somehow */
@@ -738,10 +747,15 @@ apr_byte_t oidc_metadata_provider_retrieve(request_rec *r, oidc_cfg *cfg,
738747
const char *issuer, const char *url, json_t **j_metadata,
739748
const char **response) {
740749

750+
/* get a handle to the directory config */
751+
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
752+
&auth_openidc_module);
753+
741754
/* get provider metadata from the specified URL with the specified parameters */
742755
if (oidc_util_http_get(r, url, NULL, NULL, NULL,
743756
cfg->provider.ssl_validate_server, response,
744-
cfg->http_timeout_short, cfg->outgoing_proxy) == FALSE)
757+
cfg->http_timeout_short, cfg->outgoing_proxy,
758+
dir_cfg->pass_cookies) == FALSE)
745759
return FALSE;
746760

747761
/* decode and see if it is not an error response somehow */

src/mod_auth_openidc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ static int oidc_handle_existing_session(request_rec *r,
677677

678678
oidc_debug(r, "enter");
679679

680-
/* get a handle to the director config */
680+
/* get a handle to the directory config */
681681
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
682682
&auth_openidc_module);
683683

src/mod_auth_openidc.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ typedef struct oidc_dir_cfg {
287287
char *cookie;
288288
char *authn_header;
289289
int return401;
290+
apr_array_header_t *pass_cookies;
290291
} oidc_dir_cfg;
291292

292293
int oidc_check_user_id(request_rec *r);
@@ -359,9 +360,9 @@ char *oidc_normalize_header_name(const request_rec *r, const char *str);
359360

360361
void oidc_util_set_cookie(request_rec *r, const char *cookieName, const char *cookieValue, apr_time_t expires);
361362
char *oidc_util_get_cookie(request_rec *r, const char *cookieName);
362-
apr_byte_t oidc_util_http_get(request_rec *r, const char *url, const apr_table_t *params, const char *basic_auth, const char *bearer_token, int ssl_validate_server, const char **response, int timeout, const char *outgoing_proxy);
363-
apr_byte_t oidc_util_http_post_form(request_rec *r, const char *url, const apr_table_t *params, const char *basic_auth, const char *bearer_token, int ssl_validate_server, const char **response, int timeout, const char *outgoing_proxy);
364-
apr_byte_t oidc_util_http_post_json(request_rec *r, const char *url, const json_t *data, const char *basic_auth, const char *bearer_token, int ssl_validate_server, const char **response, int timeout, const char *outgoing_proxy);
363+
apr_byte_t oidc_util_http_get(request_rec *r, const char *url, const apr_table_t *params, const char *basic_auth, const char *bearer_token, int ssl_validate_server, const char **response, int timeout, const char *outgoing_proxy, apr_array_header_t *pass_cookies);
364+
apr_byte_t oidc_util_http_post_form(request_rec *r, const char *url, const apr_table_t *params, const char *basic_auth, const char *bearer_token, int ssl_validate_server, const char **response, int timeout, const char *outgoing_proxy, apr_array_header_t *pass_cookies);
365+
apr_byte_t oidc_util_http_post_json(request_rec *r, const char *url, const json_t *data, const char *basic_auth, const char *bearer_token, int ssl_validate_server, const char **response, int timeout, const char *outgoing_proxy, apr_array_header_t *pass_cookies);
365366
apr_byte_t oidc_util_request_matches_url(request_rec *r, const char *url);
366367
apr_byte_t oidc_util_request_has_parameter(request_rec *r, const char* param);
367368
apr_byte_t oidc_util_get_request_parameter(request_rec *r, char *name, char **value);

src/oauth.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,16 @@ extern module AP_MODULE_DECLARE_DATA auth_openidc_module;
6565
static int oidc_oauth_validate_access_token(request_rec *r, oidc_cfg *c,
6666
const char *token, const char **response) {
6767

68+
/* get a handle to the directory config */
69+
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
70+
&auth_openidc_module);
71+
6872
/* assemble parameters to call the token endpoint for validation */
6973
apr_table_t *params = apr_table_make(r->pool, 4);
7074

7175
/* add any configured extra static parameters to the introspection endpoint */
72-
oidc_util_table_add_query_encoded_params(r->pool, params, c->oauth.introspection_endpoint_params);
76+
oidc_util_table_add_query_encoded_params(r->pool, params,
77+
c->oauth.introspection_endpoint_params);
7378

7479
/* add the access_token itself */
7580
apr_table_addn(params, "token", token);
@@ -87,9 +92,9 @@ static int oidc_oauth_validate_access_token(request_rec *r, oidc_cfg *c,
8792
}
8893

8994
/* call the endpoint with the constructed parameter set and return the resulting response */
90-
return oidc_util_http_post_form(r, c->oauth.introspection_endpoint_url, params,
91-
basic_auth, NULL, c->oauth.ssl_validate_server, response,
92-
c->http_timeout_long, c->outgoing_proxy);
95+
return oidc_util_http_post_form(r, c->oauth.introspection_endpoint_url,
96+
params, basic_auth, NULL, c->oauth.ssl_validate_server, response,
97+
c->http_timeout_long, c->outgoing_proxy, dir_cfg->pass_cookies);
9398
}
9499

95100
/*

src/proto.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,10 @@ static apr_byte_t oidc_proto_token_endpoint_request(request_rec *r,
779779
char **id_token, char **access_token, char **token_type,
780780
int *expires_in, char **refresh_token) {
781781

782+
/* get a handle to the directory config */
783+
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
784+
&auth_openidc_module);
785+
782786
const char *response = NULL;
783787

784788
/* see if we need to do basic auth or auth-through-post-params (both applied through the HTTP POST method though) */
@@ -800,7 +804,8 @@ static apr_byte_t oidc_proto_token_endpoint_request(request_rec *r,
800804
/* send the refresh request to the token endpoint */
801805
if (oidc_util_http_post_form(r, provider->token_endpoint_url, params,
802806
basic_auth, NULL, provider->ssl_validate_server, &response,
803-
cfg->http_timeout_long, cfg->outgoing_proxy) == FALSE) {
807+
cfg->http_timeout_long, cfg->outgoing_proxy,
808+
dir_cfg->pass_cookies) == FALSE) {
804809
oidc_warn(r, "error when calling the token endpoint (%s)",
805810
provider->token_endpoint_url);
806811
return FALSE;
@@ -889,13 +894,18 @@ apr_byte_t oidc_proto_resolve_userinfo(request_rec *r, oidc_cfg *cfg,
889894
oidc_provider_t *provider, const char *access_token,
890895
const char **response, json_t **claims) {
891896

897+
/* get a handle to the directory config */
898+
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
899+
&auth_openidc_module);
900+
892901
oidc_debug(r, "enter, endpoint=%s, access_token=%s",
893902
provider->userinfo_endpoint_url, access_token);
894903

895904
/* get the JSON response */
896905
if (oidc_util_http_get(r, provider->userinfo_endpoint_url,
897906
NULL, NULL, access_token, provider->ssl_validate_server, response,
898-
cfg->http_timeout_long, cfg->outgoing_proxy) == FALSE)
907+
cfg->http_timeout_long, cfg->outgoing_proxy,
908+
dir_cfg->pass_cookies) == FALSE)
899909
return FALSE;
900910

901911
/* decode and check for an "error" response */
@@ -908,6 +918,10 @@ apr_byte_t oidc_proto_resolve_userinfo(request_rec *r, oidc_cfg *cfg,
908918
apr_byte_t oidc_proto_account_based_discovery(request_rec *r, oidc_cfg *cfg,
909919
const char *acct, char **issuer) {
910920

921+
/* get a handle to the directory config */
922+
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
923+
&auth_openidc_module);
924+
911925
// TODO: maybe show intermediate/progress screen "discovering..."
912926

913927
oidc_debug(r, "enter, acct=%s", acct);
@@ -929,7 +943,8 @@ apr_byte_t oidc_proto_account_based_discovery(request_rec *r, oidc_cfg *cfg,
929943
const char *response = NULL;
930944
if (oidc_util_http_get(r, url, params, NULL, NULL,
931945
cfg->provider.ssl_validate_server, &response,
932-
cfg->http_timeout_short, cfg->outgoing_proxy) == FALSE) {
946+
cfg->http_timeout_short, cfg->outgoing_proxy,
947+
dir_cfg->pass_cookies) == FALSE) {
933948
/* errors will have been logged by now */
934949
return FALSE;
935950
}

src/util.c

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -413,11 +413,13 @@ static int oidc_http_add_form_url_encoded_param(void* rec, const char* key,
413413
static apr_byte_t oidc_util_http_call(request_rec *r, const char *url,
414414
const char *data, const char *content_type, const char *basic_auth,
415415
const char *bearer_token, int ssl_validate_server,
416-
const char **response, int timeout, const char *outgoing_proxy) {
416+
const char **response, int timeout, const char *outgoing_proxy,
417+
apr_array_header_t *pass_cookies) {
417418
char curlError[CURL_ERROR_SIZE];
418419
oidc_curl_buffer curlBuffer;
419420
CURL *curl;
420421
struct curl_slist *h_list = NULL;
422+
int i;
421423

422424
/* do some logging about the inputs */
423425
oidc_debug(r,
@@ -498,6 +500,28 @@ static apr_byte_t oidc_util_http_call(request_rec *r, const char *url,
498500
if (h_list != NULL)
499501
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, h_list);
500502

503+
/* gather cookies that we need to pass on from the incoming request */
504+
char *cookie_string = NULL;
505+
for (i = 0; i < pass_cookies->nelts; i++) {
506+
const char *cookie_name = ((const char**) pass_cookies->elts)[i];
507+
char *cookie_value = oidc_util_get_cookie(r, cookie_name);
508+
if (cookie_value != NULL) {
509+
cookie_string =
510+
(cookie_string == NULL) ?
511+
apr_psprintf(r->pool, "%s=%s", cookie_name,
512+
cookie_value) :
513+
apr_psprintf(r->pool, "%s; %s=%s", cookie_string,
514+
cookie_name, cookie_value);
515+
}
516+
}
517+
518+
/* see if we need to pass any cookies */
519+
if (cookie_string != NULL) {
520+
oidc_debug(r, "passing browser cookies on backend call: %s",
521+
cookie_string);
522+
curl_easy_setopt(curl, CURLOPT_COOKIE, cookie_string);
523+
}
524+
501525
/* set the target URL */
502526
curl_easy_setopt(curl, CURLOPT_URL, url);
503527

@@ -514,7 +538,7 @@ static apr_byte_t oidc_util_http_call(request_rec *r, const char *url,
514538
/* set and log the response */
515539
oidc_debug(r, "response=%s", *response);
516540

517-
out:
541+
out:
518542

519543
/* cleanup and return the result */
520544
if (h_list != NULL)
@@ -530,7 +554,8 @@ static apr_byte_t oidc_util_http_call(request_rec *r, const char *url,
530554
apr_byte_t oidc_util_http_get(request_rec *r, const char *url,
531555
const apr_table_t *params, const char *basic_auth,
532556
const char *bearer_token, int ssl_validate_server,
533-
const char **response, int timeout, const char *outgoing_proxy) {
557+
const char **response, int timeout, const char *outgoing_proxy,
558+
apr_array_header_t *pass_cookies) {
534559

535560
if ((params != NULL) && (apr_table_elts(params)->nelts > 0)) {
536561
oidc_http_encode_t data = { r, "" };
@@ -541,7 +566,8 @@ apr_byte_t oidc_util_http_get(request_rec *r, const char *url,
541566
}
542567

543568
return oidc_util_http_call(r, url, NULL, NULL, basic_auth, bearer_token,
544-
ssl_validate_server, response, timeout, outgoing_proxy);
569+
ssl_validate_server, response, timeout, outgoing_proxy,
570+
pass_cookies);
545571
}
546572

547573
/*
@@ -550,7 +576,8 @@ apr_byte_t oidc_util_http_get(request_rec *r, const char *url,
550576
apr_byte_t oidc_util_http_post_form(request_rec *r, const char *url,
551577
const apr_table_t *params, const char *basic_auth,
552578
const char *bearer_token, int ssl_validate_server,
553-
const char **response, int timeout, const char *outgoing_proxy) {
579+
const char **response, int timeout, const char *outgoing_proxy,
580+
apr_array_header_t *pass_cookies) {
554581

555582
const char *data = NULL;
556583
if ((params != NULL) && (apr_table_elts(params)->nelts > 0)) {
@@ -563,7 +590,8 @@ apr_byte_t oidc_util_http_post_form(request_rec *r, const char *url,
563590

564591
return oidc_util_http_call(r, url, data,
565592
"application/x-www-form-urlencoded", basic_auth, bearer_token,
566-
ssl_validate_server, response, timeout, outgoing_proxy);
593+
ssl_validate_server, response, timeout, outgoing_proxy,
594+
pass_cookies);
567595
}
568596

569597
/*
@@ -572,7 +600,7 @@ apr_byte_t oidc_util_http_post_form(request_rec *r, const char *url,
572600
apr_byte_t oidc_util_http_post_json(request_rec *r, const char *url,
573601
const json_t *json, const char *basic_auth, const char *bearer_token,
574602
int ssl_validate_server, const char **response, int timeout,
575-
const char *outgoing_proxy) {
603+
const char *outgoing_proxy, apr_array_header_t *pass_cookies) {
576604

577605
char *data = NULL;
578606
if (json != NULL) {
@@ -583,7 +611,7 @@ apr_byte_t oidc_util_http_post_json(request_rec *r, const char *url,
583611

584612
return oidc_util_http_call(r, url, data, "application/json", basic_auth,
585613
bearer_token, ssl_validate_server, response, timeout,
586-
outgoing_proxy);
614+
outgoing_proxy, pass_cookies);
587615
}
588616

589617
/*

0 commit comments

Comments
 (0)