diff --git a/ChangeLog b/ChangeLog index bdea7b27..e2a5e050 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,10 @@ - fix performance issue with latin1 encoding when using OIDCPassClaimsAs latin1 - add options for authentication to OIDCOutgoingProxy; thanks @drzraf see https://github.com/OpenIDC/mod_auth_openidc/discussions/1107 -- bump to 2.4.14.4rc2 +- add support for custom preserve/restore POST data templates with OIDCPreservePostTemplates + to be used when OIDCPreservePost is set to On; the hard-coded internal templates are added to + the test directory as an example; closes #195 (yeah...); thanks @kerrermanisNL and @spiazzi +- bump to 2.4.14.4rc3 09/14/2023 - fix `OIDCRefreshAccessTokenBeforeExpiry` when using it with `logout_on_error` or `authenticate_on_error` diff --git a/auth_openidc.conf b/auth_openidc.conf index 1ac728c6..4408ab9a 100644 --- a/auth_openidc.conf +++ b/auth_openidc.conf @@ -953,6 +953,14 @@ # The default is "Off" (for security reasons). Can be configured on a per Directory/Location basis. #OIDCPreservePost [On|Off] +# POST preserve and restore templates to be used with OIDCPreservePost +# template needs to contain two "%s" characters +# the first for the JSON formattted POST data, the second for the URL to redirect to after preserving +# template needs to contain one "%s" +# which contains the (original) URL to POST the restored data to +# The default is to use internal templates +#OIDCPreservePostTemplates + # Indicates whether the access token and access token expires will be passed to the application in a header/environment variable, according # to the OIDCPassClaimsAs directive. # Can be configured on a per Directory/Location basis. The default is "On". diff --git a/configure.ac b/configure.ac index 0a7ccc28..3da39ab4 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([mod_auth_openidc],[2.4.14.4rc2],[hans.zandbelt@openidc.com]) +AC_INIT([mod_auth_openidc],[2.4.14.4rc3],[hans.zandbelt@openidc.com]) AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION()) diff --git a/src/config.c b/src/config.c index c6c8233a..6a20365b 100644 --- a/src/config.c +++ b/src/config.c @@ -252,6 +252,7 @@ #define OIDCRedisCacheConnectTimeout "OIDCRedisCacheConnectTimeout" #define OIDCRedisCacheTimeout "OIDCRedisCacheTimeout" #define OIDCHTMLErrorTemplate "OIDCHTMLErrorTemplate" +#define OIDCPreservePostTemplates "OIDCPreservePostTemplates" #define OIDCDiscoverURL "OIDCDiscoverURL" #define OIDCPassCookies "OIDCPassCookies" #define OIDCStripCookies "OIDCStripCookies" @@ -1413,6 +1414,17 @@ static const char* oidc_set_signed_jwks_uri(cmd_parms *cmd, void *m, return NULL; } +static const char* oidc_set_post_preserve_templates(cmd_parms *cmd, void *m, + const char *arg1, const char *arg2) { + oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config, + &auth_openidc_module); + if (arg1) + cfg->post_preserve_template = apr_pstrdup(cmd->pool, arg1); + if (arg2) + cfg->post_restore_template = apr_pstrdup(cmd->pool, arg2); + return NULL; +} + static const char* oidc_set_token_revocation_endpoint(cmd_parms *cmd, void *struct_ptr, const char *args) { oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config, @@ -1823,6 +1835,8 @@ void* oidc_create_server_config(apr_pool_t *pool, server_rec *svr) { c->crypto_passphrase = NULL; c->error_template = NULL; + c->post_preserve_template = NULL; + c->post_restore_template = NULL; c->provider.userinfo_refresh_interval = OIDC_DEFAULT_USERINFO_REFRESH_INTERVAL; @@ -2141,6 +2155,12 @@ void* oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) { c->error_template = add->error_template != NULL ? add->error_template : base->error_template; + c->post_preserve_template = + add->post_preserve_template != NULL ? + add->post_preserve_template : base->post_preserve_template; + c->post_restore_template = + add->post_restore_template != NULL ? + add->post_restore_template : base->post_restore_template; c->provider_metadata_refresh_interval = add->provider_metadata_refresh_interval @@ -3625,6 +3645,14 @@ const command_rec oidc_config_cmds[] = { (void*)APR_OFFSETOF(oidc_cfg, error_template), RSRC_CONF, "Name of a HTML error template: needs to contain two \"%s\" characters, one for the error message, one for the description."), + AP_INIT_TAKE2(OIDCPreservePostTemplates, + oidc_set_post_preserve_templates, + NULL, + RSRC_CONF, + "Name of POST preserve and restore templates:" + "1) preserve: needs to contain two \"%s\" characters, the first for the JSON POST data, the second for the URL to redirect to." + "2) restore: needs to contain one \"%s\", which contains the (original) URL to POST the restored data to" + ), AP_INIT_TAKE1(OIDCDiscoverURL, oidc_set_relative_or_absolute_url_slot_dir_cfg, diff --git a/src/mod_auth_openidc.c b/src/mod_auth_openidc.c index a6621ef5..380889fa 100644 --- a/src/mod_auth_openidc.c +++ b/src/mod_auth_openidc.c @@ -418,6 +418,8 @@ static const char* oidc_original_request_method(request_rec *r, oidc_cfg *cfg, return method; } +static char *post_preserve_template_contents = NULL; + /* * send an OpenID Connect authorization request to the specified provider preserving POST parameters using HTML5 storage */ @@ -456,8 +458,33 @@ apr_byte_t oidc_post_preserve_javascript(request_rec *r, const char *location, } json = apr_psprintf(r->pool, "{ %s }", json); + const char *jscript = NULL; + char *template = NULL; + + if (cfg->post_preserve_template != NULL) { + if (post_preserve_template_contents == NULL) { + template = oidc_util_get_full_path(r->pool, + cfg->post_preserve_template); + if (oidc_util_file_read(r, template, r->server->process->pool, + &post_preserve_template_contents) == FALSE) { + oidc_error(r, "could not read POST template: %s", template); + post_preserve_template_contents = NULL; + } + } + if (post_preserve_template_contents != NULL) { + jscript = apr_psprintf(r->pool, post_preserve_template_contents, + json, + location ? + oidc_util_javascript_escape(r->pool, location) : + ""); + oidc_util_http_send(r, jscript, _oidc_strlen(jscript), + OIDC_CONTENT_TYPE_TEXT_HTML, OK); + return TRUE; + } + } + const char *jmethod = "preserveOnLoad"; - const char *jscript = + jscript = apr_psprintf(r->pool, " \n", jmethod, json, location ? apr_psprintf(r->pool, "window.location='%s';\n", - oidc_util_javascript_escape(r->pool, location)) : - ""); + oidc_util_javascript_escape(r->pool, + location)) : + ""); if (location == NULL) { if (javascript_method) *javascript_method = apr_pstrdup(r->pool, jmethod); @@ -2139,6 +2167,8 @@ static apr_byte_t oidc_handle_browser_back(request_rec *r, const char *r_state, return FALSE; } +static char *post_restore_template_contents = NULL; + /* * complete the handling of an authorization response by obtaining, parsing and verifying the * id_token and storing the authenticated user state in the session @@ -2291,6 +2321,29 @@ static int oidc_handle_authorization_response(request_rec *r, oidc_cfg *c, /* check whether form post data was preserved; if so restore it */ if (_oidc_strcmp(original_method, OIDC_METHOD_FORM_POST) == 0) { + char *template = NULL; + char *jscript = NULL; + if (c->post_restore_template != NULL) { + if (post_restore_template_contents == NULL) { + template = oidc_util_get_full_path(r->pool, + c->post_restore_template); + if (oidc_util_file_read(r, template, r->server->process->pool, + &post_restore_template_contents) == FALSE) { + oidc_error(r, "could not read POST template: %s", template); + post_restore_template_contents = NULL; + } + } + if (post_restore_template_contents != NULL) { + jscript = apr_psprintf(r->pool, post_restore_template_contents, + original_url ? + oidc_util_javascript_escape(r->pool, + original_url) : + ""); + oidc_util_http_send(r, jscript, _oidc_strlen(jscript), + OIDC_CONTENT_TYPE_TEXT_HTML, OK); + return TRUE; + } + } return oidc_request_post_preserved_restore(r, original_url); } diff --git a/src/mod_auth_openidc.h b/src/mod_auth_openidc.h index 468ff6f2..7d088e3c 100644 --- a/src/mod_auth_openidc.h +++ b/src/mod_auth_openidc.h @@ -400,6 +400,10 @@ typedef struct oidc_cfg { /* HTML to display error messages+description */ char *error_template; + /* Javascript template to preserve POST data */ + char *post_preserve_template; + /* Javascript template to restore POST data */ + char *post_restore_template; /* the redirect URI as configured with the OpenID Connect OP's that we talk to */ char *redirect_uri; diff --git a/test/post_preserve.template b/test/post_preserve.template new file mode 100644 index 00000000..0ae8e717 --- /dev/null +++ b/test/post_preserve.template @@ -0,0 +1,16 @@ + + + + + Preserving... + + + +

Preserving...

+ + diff --git a/test/post_restore.template b/test/post_restore.template new file mode 100644 index 00000000..e16a704c --- /dev/null +++ b/test/post_restore.template @@ -0,0 +1,34 @@ + + + + + Restoring... + + + +

Restoring...

+
+ +