Skip to content

Commit fed0f2f

Browse files
committed
fix requests to the info hook with extend_session=false; see #1279
- properly reflect the (unmodified) inactivity timeout in the response ("timeout") - avoid refreshing an access token (since the session is not saved) - avoid refreshing claims from the user info endpoint, and possibly refreshing the access token thanks @fnieri-cdp Signed-off-by: Hans Zandbelt <[email protected]>
1 parent bddff12 commit fed0f2f

File tree

5 files changed

+82
-62
lines changed

5 files changed

+82
-62
lines changed

ChangeLog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
11/07/2024
2+
- info: fix requests to the info hook with extend_session=false; see #1279; thanks @fnieri-cdp
3+
- properly reflect the (unmodified) inactivity timeout in the response ("timeout")
4+
- avoid refreshing an access token (since the session is not saved)
5+
- avoid refreshing claims from the user info endpoint, and possibly refreshing the access token
6+
17
10/23/2024
28
- metadata: allow plain HTTP URLs in metadata elements `jwks_uri` and `signed_jwks_uri`
39
to ensure backwards compatibility with <=2.4.15.7 and to support private/test deployments

src/handle/info.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
#include "util.h"
4646

4747
#define OIDC_INFO_PARAM_ACCESS_TOKEN_REFRESH_INTERVAL "access_token_refresh_interval"
48-
#define OIDC_INFO_PARAM_EXTEND_SESSION "extend_session"
4948

5049
#define OIDC_HOOK_INFO_FORMAT_JSON "json"
5150
#define OIDC_HOOK_INFO_FORMAT_HTML "html"
@@ -209,9 +208,8 @@ int oidc_info_request(request_rec *r, oidc_cfg_t *c, oidc_session_t *session, ap
209208
}
210209

211210
/* pass the tokens to the application and save the session, possibly updating the expiry */
212-
if (b_extend_session)
213-
if (oidc_session_pass_tokens(r, c, session, &needs_save) == FALSE)
214-
oidc_warn(r, "error passing tokens");
211+
if (oidc_session_pass_tokens(r, c, session, b_extend_session, &needs_save) == FALSE)
212+
oidc_warn(r, "error passing tokens");
215213

216214
/* check if something was updated in the session and we need to save it again */
217215
if (b_extend_session && needs_save) {

src/handle/refresh.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ int oidc_refresh_token_request(request_rec *r, oidc_cfg_t *c, oidc_session_t *se
363363
}
364364

365365
/* pass the tokens to the application, possibly updating the expiry */
366-
if (oidc_session_pass_tokens(r, c, session, &needs_save) == FALSE) {
366+
if (oidc_session_pass_tokens(r, c, session, TRUE, &needs_save) == FALSE) {
367367
error_code = "session_corruption";
368368
goto end;
369369
}

src/mod_auth_openidc.c

Lines changed: 69 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,8 @@ static void oidc_copy_tokens_to_request_state(request_rec *r, oidc_session_t *se
599599
/*
600600
* pass refresh_token, access_token and access_token_expires as headers/environment variables to the application
601601
*/
602-
apr_byte_t oidc_session_pass_tokens(request_rec *r, oidc_cfg_t *cfg, oidc_session_t *session, apr_byte_t *needs_save) {
602+
apr_byte_t oidc_session_pass_tokens(request_rec *r, oidc_cfg_t *cfg, oidc_session_t *session, apr_byte_t extend_session,
603+
apr_byte_t *needs_save) {
603604

604605
oidc_appinfo_pass_in_t pass_in = oidc_cfg_dir_pass_info_in_get(r);
605606
oidc_appinfo_encoding_t encoding = oidc_cfg_dir_pass_info_encoding_get(r);
@@ -636,27 +637,29 @@ apr_byte_t oidc_session_pass_tokens(request_rec *r, oidc_cfg_t *cfg, oidc_sessio
636637
OIDC_DEFAULT_HEADER_PREFIX, pass_in, encoding);
637638
}
638639

639-
/*
640-
* reset the session inactivity timer
641-
* but only do this once per 10% of the inactivity timeout interval (with a max to 60 seconds)
642-
* for performance reasons
643-
*
644-
* now there's a small chance that the session ends 10% (or a minute) earlier than configured/expected
645-
* cq. when there's a request after a recent save (so no update) and then no activity happens until
646-
* a request comes in just before the session should expire
647-
* ("recent" and "just before" refer to 10%-with-a-max-of-60-seconds of the inactivity interval after
648-
* the start/last-update and before the expiry of the session respectively)
649-
*
650-
* this is be deemed acceptable here because of performance gain
651-
*/
652-
apr_time_t interval = apr_time_from_sec(oidc_cfg_session_inactivity_timeout_get(cfg));
653-
apr_time_t now = apr_time_now();
654-
apr_time_t slack = interval / 10;
655-
if (slack > apr_time_from_sec(60))
656-
slack = apr_time_from_sec(60);
657-
if (session->expiry - now < interval - slack) {
658-
session->expiry = now + interval;
659-
*needs_save = TRUE;
640+
if (extend_session) {
641+
/*
642+
* reset the session inactivity timer
643+
* but only do this once per 10% of the inactivity timeout interval (with a max to 60 seconds)
644+
* for performance reasons
645+
*
646+
* now there's a small chance that the session ends 10% (or a minute) earlier than configured/expected
647+
* cq. when there's a request after a recent save (so no update) and then no activity happens until
648+
* a request comes in just before the session should expire
649+
* ("recent" and "just before" refer to 10%-with-a-max-of-60-seconds of the inactivity interval after
650+
* the start/last-update and before the expiry of the session respectively)
651+
*
652+
* this is be deemed acceptable here because of performance gain
653+
*/
654+
apr_time_t interval = apr_time_from_sec(oidc_cfg_session_inactivity_timeout_get(cfg));
655+
apr_time_t now = apr_time_now();
656+
apr_time_t slack = interval / 10;
657+
if (slack > apr_time_from_sec(60))
658+
slack = apr_time_from_sec(60);
659+
if (session->expiry - now < interval - slack) {
660+
session->expiry = now + interval;
661+
*needs_save = TRUE;
662+
}
660663
}
661664

662665
/* log message about session expiry */
@@ -669,7 +672,7 @@ apr_byte_t oidc_session_pass_tokens(request_rec *r, oidc_cfg_t *cfg, oidc_sessio
669672
* handle the case where we have identified an existing authentication session for a user
670673
*/
671674
static int oidc_handle_existing_session(request_rec *r, oidc_cfg_t *cfg, oidc_session_t *session,
672-
apr_byte_t *needs_save) {
675+
apr_byte_t extend_session, apr_byte_t *needs_save) {
673676

674677
apr_byte_t rv = FALSE;
675678
int rc = OK;
@@ -710,39 +713,44 @@ static int oidc_handle_existing_session(request_rec *r, oidc_cfg_t *cfg, oidc_se
710713
return rc;
711714
}
712715

713-
/* if needed, refresh the access token */
714-
rv = oidc_refresh_access_token_before_expiry(
715-
r, cfg, session, oidc_cfg_dir_refresh_access_token_before_expiry_get(r), needs_save);
716-
if (rv == FALSE) {
717-
*needs_save = FALSE;
718-
oidc_debug(r, "dir_action_on_error_refresh: %d", oidc_cfg_dir_action_on_error_refresh_get(r));
719-
OIDC_METRICS_COUNTER_INC(r, cfg, OM_SESSION_ERROR_REFRESH_ACCESS_TOKEN);
720-
if (oidc_cfg_dir_action_on_error_refresh_get(r) == OIDC_ON_ERROR_LOGOUT) {
721-
return oidc_logout_request(
722-
r, cfg, session, oidc_util_absolute_url(r, cfg, oidc_cfg_default_slo_url_get(cfg)), FALSE);
723-
}
724-
if (oidc_cfg_dir_action_on_error_refresh_get(r) == OIDC_ON_ERROR_AUTH) {
725-
oidc_session_kill(r, session);
726-
return oidc_handle_unauthenticated_user(r, cfg);
727-
}
728-
return HTTP_BAD_GATEWAY;
729-
}
716+
if (extend_session) {
730717

731-
/* if needed, refresh claims from the user info endpoint */
732-
rv = oidc_userinfo_refresh_claims(r, cfg, session, needs_save);
733-
if (rv == FALSE) {
734-
*needs_save = FALSE;
735-
oidc_debug(r, "action_on_userinfo_error: %d", oidc_cfg_action_on_userinfo_error_get(cfg));
736-
OIDC_METRICS_COUNTER_INC(r, cfg, OM_SESSION_ERROR_REFRESH_USERINFO);
737-
if (oidc_cfg_action_on_userinfo_error_get(cfg) == OIDC_ON_ERROR_LOGOUT) {
738-
return oidc_logout_request(
739-
r, cfg, session, oidc_util_absolute_url(r, cfg, oidc_cfg_default_slo_url_get(cfg)), FALSE);
718+
/* if needed, refresh the access token */
719+
rv = oidc_refresh_access_token_before_expiry(
720+
r, cfg, session, oidc_cfg_dir_refresh_access_token_before_expiry_get(r), needs_save);
721+
if (rv == FALSE) {
722+
*needs_save = FALSE;
723+
oidc_debug(r, "dir_action_on_error_refresh: %d", oidc_cfg_dir_action_on_error_refresh_get(r));
724+
OIDC_METRICS_COUNTER_INC(r, cfg, OM_SESSION_ERROR_REFRESH_ACCESS_TOKEN);
725+
if (oidc_cfg_dir_action_on_error_refresh_get(r) == OIDC_ON_ERROR_LOGOUT) {
726+
return oidc_logout_request(
727+
r, cfg, session, oidc_util_absolute_url(r, cfg, oidc_cfg_default_slo_url_get(cfg)),
728+
FALSE);
729+
}
730+
if (oidc_cfg_dir_action_on_error_refresh_get(r) == OIDC_ON_ERROR_AUTH) {
731+
oidc_session_kill(r, session);
732+
return oidc_handle_unauthenticated_user(r, cfg);
733+
}
734+
return HTTP_BAD_GATEWAY;
740735
}
741-
if (oidc_cfg_action_on_userinfo_error_get(cfg) == OIDC_ON_ERROR_AUTH) {
742-
oidc_session_kill(r, session);
743-
return oidc_handle_unauthenticated_user(r, cfg);
736+
737+
/* if needed, refresh claims from the user info endpoint */
738+
rv = oidc_userinfo_refresh_claims(r, cfg, session, needs_save);
739+
if (rv == FALSE) {
740+
*needs_save = FALSE;
741+
oidc_debug(r, "action_on_userinfo_error: %d", oidc_cfg_action_on_userinfo_error_get(cfg));
742+
OIDC_METRICS_COUNTER_INC(r, cfg, OM_SESSION_ERROR_REFRESH_USERINFO);
743+
if (oidc_cfg_action_on_userinfo_error_get(cfg) == OIDC_ON_ERROR_LOGOUT) {
744+
return oidc_logout_request(
745+
r, cfg, session, oidc_util_absolute_url(r, cfg, oidc_cfg_default_slo_url_get(cfg)),
746+
FALSE);
747+
}
748+
if (oidc_cfg_action_on_userinfo_error_get(cfg) == OIDC_ON_ERROR_AUTH) {
749+
oidc_session_kill(r, session);
750+
return oidc_handle_unauthenticated_user(r, cfg);
751+
}
752+
return HTTP_BAD_GATEWAY;
744753
}
745-
return HTTP_BAD_GATEWAY;
746754
}
747755

748756
/* set the user authentication HTTP header if set and required */
@@ -777,7 +785,7 @@ static int oidc_handle_existing_session(request_rec *r, oidc_cfg_t *cfg, oidc_se
777785
}
778786

779787
/* pass the at, rt and at expiry to the application, possibly update the session expiry */
780-
if (oidc_session_pass_tokens(r, cfg, session, needs_save) == FALSE)
788+
if (oidc_session_pass_tokens(r, cfg, session, extend_session, needs_save) == FALSE)
781789
return HTTP_INTERNAL_SERVER_ERROR;
782790

783791
oidc_userinfo_pass_as(r, cfg, session, s_claims, pass_in, encoding);
@@ -971,6 +979,7 @@ static int oidc_javascript_implicit(request_rec *r, oidc_cfg_t *c) {
971979
int oidc_handle_redirect_uri_request(request_rec *r, oidc_cfg_t *c, oidc_session_t *session) {
972980

973981
apr_byte_t needs_save = FALSE;
982+
char *s_extend_session = NULL;
974983
int rc = OK;
975984

976985
OIDC_METRICS_TIMING_START(r, c);
@@ -1098,8 +1107,12 @@ int oidc_handle_redirect_uri_request(request_rec *r, oidc_cfg_t *c, oidc_session
10981107

10991108
OIDC_METRICS_COUNTER_INC(r, c, OM_REDIRECT_URI_REQUEST_INFO);
11001109

1110+
oidc_util_request_parameter_get(r, OIDC_INFO_PARAM_EXTEND_SESSION, &s_extend_session);
1111+
11011112
// need to establish user/claims for authorization purposes
1102-
rc = oidc_handle_existing_session(r, c, session, &needs_save);
1113+
rc = oidc_handle_existing_session(
1114+
r, c, session, (s_extend_session == NULL) || (_oidc_strcmp(s_extend_session, "false") != 0),
1115+
&needs_save);
11031116

11041117
// retain this session across the authentication and content handler phases
11051118
// by storing it in the request state
@@ -1233,7 +1246,7 @@ static int oidc_check_userid_openidc(request_rec *r, oidc_cfg_t *c) {
12331246
} else if (session->remote_user != NULL) {
12341247

12351248
/* this is initial request and we already have a session */
1236-
rc = oidc_handle_existing_session(r, c, session, &needs_save);
1249+
rc = oidc_handle_existing_session(r, c, session, TRUE, &needs_save);
12371250
if (rc == OK) {
12381251

12391252
/* check if something was updated in the session and we need to save it again */

src/mod_auth_openidc.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@
9999
#define OIDC_REDIRECT_URI_REQUEST_SID "sid"
100100
#define OIDC_REDIRECT_URI_REQUEST_ISS "iss"
101101

102+
#define OIDC_INFO_PARAM_EXTEND_SESSION "extend_session"
103+
102104
#define OIDC_CLAIM_ISS "iss"
103105
#define OIDC_CLAIM_AUD "aud"
104106
#define OIDC_CLAIM_AZP "azp"
@@ -145,7 +147,8 @@ apr_byte_t oidc_get_remote_user(request_rec *r, const char *claim_name, const ch
145147
json_t *json, char **request_user);
146148
apr_byte_t oidc_get_provider_from_session(request_rec *r, oidc_cfg_t *c, oidc_session_t *session,
147149
oidc_provider_t **provider);
148-
apr_byte_t oidc_session_pass_tokens(request_rec *r, oidc_cfg_t *cfg, oidc_session_t *session, apr_byte_t *needs_save);
150+
apr_byte_t oidc_session_pass_tokens(request_rec *r, oidc_cfg_t *cfg, oidc_session_t *session, apr_byte_t extend_session,
151+
apr_byte_t *needs_save);
149152
void oidc_log_session_expires(request_rec *r, const char *msg, apr_time_t session_expires);
150153
apr_byte_t oidc_provider_static_config(request_rec *r, oidc_cfg_t *c, oidc_provider_t **provider);
151154
const char *oidc_original_request_method(request_rec *r, oidc_cfg_t *cfg, apr_byte_t handle_discovery_response);

0 commit comments

Comments
 (0)