From ae2893d3ac1c1f6a55bc518ce021426ed6c5fae3 Mon Sep 17 00:00:00 2001 From: Hans Zandbelt Date: Thu, 14 Nov 2024 08:24:23 +0100 Subject: [PATCH] allow specific settings Strict|Lax|None|Disabled for OIDCCookieSameSite - fix: default behaviour Lax - fix: apply OIDCCookieSameSite Off/None properly to state cookies - re-introduce the option to configure a Strict SameSite session cookie - allows for a "Disabled" value that does not set any SameSite flag Signed-off-by: Hans Zandbelt --- ChangeLog | 10 ++++++++ auth_openidc.conf | 27 +++++++++++++++------ src/cfg/cfg.c | 28 +++++++++++++++++++-- src/cfg/cfg.h | 9 ++++++- src/cfg/cfg_int.h | 2 +- src/cfg/parse.c | 20 +++++++++++++-- src/cfg/parse.h | 2 ++ src/handle/discovery.c | 29 +++++++++++++++++----- src/handle/request.c | 20 ++++++++++++--- src/handle/response.c | 5 +++- src/http.h | 4 +++ src/mod_auth_openidc.c | 6 +++++ src/mod_auth_openidc.h | 4 --- src/session.c | 55 ++++++++++++++++++++++++++++++++++-------- src/session.h | 2 ++ src/state.c | 6 ++--- 16 files changed, 189 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index c207fab1..b0a84f37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +11/14/2024 +- allow specific settings Strict|Lax|None|Disabled for OIDCCookieSameSite in addition to On(=Lax)|Off(=None) + - fix: default behaviour Lax + - fix: apply OIDCCookieSameSite Off/None properly to state cookies instead of always setting Lax + - re-introduces the option to configure a Strict SameSite session cookie policy, which will turn the initial + Lax session cookie - set upon receving the response to the Redirect URI - into a Strict session cookie + immediately after the first application request + - allows for a "Disabled" value that does not set any SameSite flag on the cookies, in which case a browser + falls back to its default browser behaviour (which should be Lax by spec) + 11/07/2024 - info: fix requests to the info hook with extend_session=false; see #1279; thanks @fnieri-cdp - properly reflect the (unmodified) inactivity timeout in the response ("timeout") diff --git a/auth_openidc.conf b/auth_openidc.conf index f3fdca76..ec6620c5 100644 --- a/auth_openidc.conf +++ b/auth_openidc.conf @@ -555,18 +555,31 @@ # When not defined the default is On. #OIDCCookieHTTPOnly [On|Off] -# Defines whether the SameSite flag will be set on cookies. -# When On the following will apply: -# state cookie: Lax +# Defines the SameSite flag that will be set on cookies. +# +# When set to "On" (default) or "Lax" the following will apply: # session cookie: Lax -# x_csrf discovery: Strict: +# state cookie: Lax +# x_csrf discovery: Lax +# +# When set to "Strict" the following will apply: +# session cookie: Strict (first time: Lax) +# state cookie: Lax +# x_csrf discovery: Strict +# +# When set to "Off" or "None" the following will apply: +# session cookie: None +# state cookie: None +# x_csrf discovery: None # -# The default `SameSite=None` cookie appendix on `Set-Cookie` response headers can be +# When set to "Disabled" no SameSite flag will be appended. +# +# The configured SameSite cookie appendix on `Set-Cookie` response headers can be # conditionally overridden using an environment variable in the Apache config as in: # SetEnvIf User-Agent ".*IOS.*" OIDC_SET_COOKIE_APPEND=; # -# When not defined the default is On. -#OIDCCookieSameSite [On|Off] +# When not defined the default is On (Lax). +#OIDCCookieSameSite [ On | Off | Strict | Lax | None | Disabled ] # Specify the names of cookies to pickup from the browser and send along on backchannel # calls to the OP and AS endpoints. This can be used for load-balancing purposes. diff --git a/src/cfg/cfg.c b/src/cfg/cfg.c index 02288b14..237865c9 100644 --- a/src/cfg/cfg.c +++ b/src/cfg/cfg.c @@ -521,8 +521,32 @@ OIDC_CFG_MEMBER_FUNC_GET(metadata_dir, const char *) #define OIDC_DEFAULT_COOKIE_HTTPONLY 1 OIDC_CFG_MEMBER_FUNCS_BOOL(cookie_http_only, OIDC_DEFAULT_COOKIE_HTTPONLY) -#define OIDC_DEFAULT_COOKIE_SAME_SITE 1 -OIDC_CFG_MEMBER_FUNCS_BOOL(cookie_same_site, OIDC_DEFAULT_COOKIE_SAME_SITE) +#define OIDC_SAMESITE_COOKIE_OFF_STR "Off" +#define OIDC_SAMESITE_COOKIE_ON_STR "On" +#define OIDC_SAMESITE_COOKIE_DISABLED_STR "Disabled" +#define OIDC_SAMESITE_COOKIE_NONE_STR "None" +#define OIDC_SAMESITE_COOKIE_LAX_STR "Lax" +#define OIDC_SAMESITE_COOKIE_STRICT_STR "Strict" + +/* + * define which header we use for calculating the fingerprint of the state during authentication + */ +const char *oidc_cmd_cookie_same_site_set(cmd_parms *cmd, void *m, const char *arg) { + oidc_cfg_t *cfg = (oidc_cfg_t *)ap_get_module_config(cmd->server->module_config, &auth_openidc_module); + // NB: On is made equal to Lax here and Off is equal to None (backwards compatibility) + static const oidc_cfg_option_t options[] = {{OIDC_SAMESITE_COOKIE_NONE, OIDC_SAMESITE_COOKIE_OFF_STR}, + {OIDC_SAMESITE_COOKIE_LAX, OIDC_SAMESITE_COOKIE_ON_STR}, + {OIDC_SAMESITE_COOKIE_DISABLED, OIDC_SAMESITE_COOKIE_DISABLED_STR}, + {OIDC_SAMESITE_COOKIE_NONE, OIDC_SAMESITE_COOKIE_NONE_STR}, + {OIDC_SAMESITE_COOKIE_LAX, OIDC_SAMESITE_COOKIE_LAX_STR}, + {OIDC_SAMESITE_COOKIE_STRICT, OIDC_SAMESITE_COOKIE_STRICT_STR}}; + const char *rv = oidc_cfg_parse_option_ignore_case(cmd->pool, options, OIDC_CFG_OPTIONS_SIZE(options), arg, + (int *)&cfg->cookie_same_site); + return OIDC_CONFIG_DIR_RV(cmd, rv); +} + +#define OIDC_DEFAULT_COOKIE_SAME_SITE OIDC_SAMESITE_COOKIE_LAX +OIDC_CFG_MEMBER_FUNC_TYPE_GET(cookie_same_site, oidc_samesite_cookie_t, OIDC_DEFAULT_COOKIE_SAME_SITE) #define OIDC_DEFAULT_SESSION_FALLBACK_TO_COOKIE 0 OIDC_CFG_MEMBER_FUNCS_BOOL(session_cache_fallback_to_cookie, OIDC_DEFAULT_SESSION_FALLBACK_TO_COOKIE) diff --git a/src/cfg/cfg.h b/src/cfg/cfg.h index 776b3670..59ac919d 100644 --- a/src/cfg/cfg.h +++ b/src/cfg/cfg.h @@ -111,6 +111,13 @@ typedef enum { OIDC_TRACE_PARENT_GENERATE = 2 } oidc_trace_parent_t; +typedef enum { + OIDC_SAMESITE_COOKIE_DISABLED = 0, + OIDC_SAMESITE_COOKIE_NONE = 1, + OIDC_SAMESITE_COOKIE_LAX = 2, + OIDC_SAMESITE_COOKIE_STRICT = 3 +} oidc_samesite_cookie_t; + #define OIDC_ERROR_ENVVAR "OIDC_ERROR" #define OIDC_ERROR_DESC_ENVVAR "OIDC_ERROR_DESC" @@ -214,7 +221,7 @@ OIDC_CFG_MEMBER_FUNCS_DECL(default_sso_url, const char *) OIDC_CFG_MEMBER_FUNCS_DECL(default_slo_url, const char *) OIDC_CFG_MEMBER_FUNCS_DECL(cookie_domain, const char *) OIDC_CFG_MEMBER_FUNCS_DECL(cookie_http_only, int) -OIDC_CFG_MEMBER_FUNCS_DECL(cookie_same_site, int) +OIDC_CFG_MEMBER_FUNCS_DECL(cookie_same_site, oidc_samesite_cookie_t) OIDC_CFG_MEMBER_FUNCS_DECL(claim_delimiter, const char *) OIDC_CFG_MEMBER_FUNCS_DECL(claim_prefix, const char *) OIDC_CFG_MEMBER_FUNCS_DECL(state_timeout, int) diff --git a/src/cfg/cfg_int.h b/src/cfg/cfg_int.h index 2bf62d15..13e08ff9 100644 --- a/src/cfg/cfg_int.h +++ b/src/cfg/cfg_int.h @@ -150,7 +150,7 @@ struct oidc_cfg_t { int session_cookie_chunk_size; char *cookie_domain; int cookie_http_only; - int cookie_same_site; + oidc_samesite_cookie_t cookie_same_site; int state_timeout; int max_number_of_state_cookies; diff --git a/src/cfg/parse.c b/src/cfg/parse.c index b02f710c..8db66c53 100644 --- a/src/cfg/parse.c +++ b/src/cfg/parse.c @@ -106,9 +106,10 @@ char *oidc_cfg_parse_options_flatten(apr_pool_t *pool, const oidc_cfg_option_t o /* * parse an value provided as an option string into the corresponding integer/enum */ -char *oidc_cfg_parse_option(apr_pool_t *pool, const oidc_cfg_option_t options[], int n, const char *arg, int *v) { +static char *oidc_cfg_parse_option_impl(apr_pool_t *pool, const oidc_cfg_option_t options[], int n, const char *arg, + int *v, int (*fstrcmp)(const char *, const char *)) { int i = 0; - while ((i < n) && (_oidc_strcmp(arg, options[i].str) != 0)) + while ((i < n) && (fstrcmp(arg, options[i].str) != 0)) i++; if (i < n) { *v = options[i].val; @@ -118,6 +119,21 @@ char *oidc_cfg_parse_option(apr_pool_t *pool, const oidc_cfg_option_t options[], OIDC_LIST_OPTIONS_QUOTE, oidc_cfg_parse_options_flatten(pool, options, n)); } +/* + * parse an value provided as an option string into the corresponding integer/enum case sensitive + */ +char *oidc_cfg_parse_option(apr_pool_t *pool, const oidc_cfg_option_t options[], int n, const char *arg, int *v) { + return oidc_cfg_parse_option_impl(pool, options, n, arg, v, _oidc_strcmp); +} + +/* + * parse an value provided as an option string into the corresponding integer/enum case insensitive + */ +char *oidc_cfg_parse_option_ignore_case(apr_pool_t *pool, const oidc_cfg_option_t options[], int n, const char *arg, + int *v) { + return oidc_cfg_parse_option_impl(pool, options, n, arg, v, _oidc_strnatcasecmp); +} + /* * check if the provided integer value is between a specified minimum and maximum */ diff --git a/src/cfg/parse.h b/src/cfg/parse.h index aba0d2a2..0452ddcc 100644 --- a/src/cfg/parse.h +++ b/src/cfg/parse.h @@ -51,6 +51,8 @@ typedef struct oidc_cfg_option_t { } oidc_cfg_option_t; char *oidc_cfg_parse_option(apr_pool_t *pool, const oidc_cfg_option_t options[], int n, const char *arg, int *v); +char *oidc_cfg_parse_option_ignore_case(apr_pool_t *pool, const oidc_cfg_option_t options[], int n, const char *arg, + int *v); char *oidc_cfg_parse_options_flatten(apr_pool_t *pool, const oidc_cfg_option_t options[], int n); char *oidc_cfg_parse_flatten_options(apr_pool_t *pool, const char *options[]); diff --git a/src/handle/discovery.c b/src/handle/discovery.c index 83b26519..db0823b8 100644 --- a/src/handle/discovery.c +++ b/src/handle/discovery.c @@ -74,12 +74,29 @@ apr_byte_t oidc_is_discovery_response(request_rec *r, oidc_cfg_t *cfg) { oidc_util_request_has_parameter(r, OIDC_DISC_USER_PARAM); } +static const char *oidc_discovery_csrf_cookie_samesite(request_rec *r, oidc_cfg_t *c) { + const char *rv = NULL; + switch (oidc_cfg_cookie_same_site_get(c)) { + case OIDC_SAMESITE_COOKIE_STRICT: + rv = OIDC_HTTP_COOKIE_SAMESITE_STRICT; + break; + case OIDC_SAMESITE_COOKIE_LAX: + rv = OIDC_HTTP_COOKIE_SAMESITE_LAX; + break; + case OIDC_SAMESITE_COOKIE_NONE: + rv = OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r); + break; + case OIDC_SAMESITE_COOKIE_DISABLED: + break; + default: + break; + } + return rv; +} + /* define the name of the cookie/parameter for CSRF protection */ #define OIDC_CSRF_NAME "x_csrf" -#define OIDC_COOKIE_SAMESITE_STRICT(c, r) \ - oidc_cfg_cookie_same_site_get(c) ? OIDC_COOKIE_EXT_SAME_SITE_STRICT : OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r) - /* * present the user with an OP selection screen */ @@ -122,7 +139,7 @@ int oidc_discovery_request(request_rec *r, oidc_cfg_t *cfg) { oidc_debug(r, "redirecting to external discovery page: %s", url); /* set CSRF cookie */ - oidc_http_set_cookie(r, OIDC_CSRF_NAME, csrf, -1, OIDC_COOKIE_SAMESITE_STRICT(cfg, r)); + oidc_http_set_cookie(r, OIDC_CSRF_NAME, csrf, -1, oidc_discovery_csrf_cookie_samesite(r, cfg)); /* see if we need to preserve POST parameters through Javascript/HTML5 storage */ if (oidc_response_post_preserve_javascript(r, url, NULL, NULL) == TRUE) @@ -200,7 +217,7 @@ int oidc_discovery_request(request_rec *r, oidc_cfg_t *cfg) { s = apr_psprintf(r->pool, "%s

\n", s); s = apr_psprintf(r->pool, "%s\n", s); - oidc_http_set_cookie(r, OIDC_CSRF_NAME, csrf, -1, OIDC_COOKIE_SAMESITE_STRICT(cfg, r)); + oidc_http_set_cookie(r, OIDC_CSRF_NAME, csrf, -1, oidc_discovery_csrf_cookie_samesite(r, cfg)); char *javascript = NULL, *javascript_method = NULL; char *html_head = ""; @@ -307,7 +324,7 @@ int oidc_discovery_response(request_rec *r, oidc_cfg_t *c) { if (csrf_cookie) { /* clean CSRF cookie */ - oidc_http_set_cookie(r, OIDC_CSRF_NAME, "", 0, OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r)); + oidc_http_set_cookie(r, OIDC_CSRF_NAME, "", 0, OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r)); /* compare CSRF cookie value with query parameter value */ if ((csrf_query == NULL) || _oidc_strcmp(csrf_query, csrf_cookie) != 0) { diff --git a/src/handle/request.c b/src/handle/request.c index 2f24b996..a15187de 100644 --- a/src/handle/request.c +++ b/src/handle/request.c @@ -98,8 +98,22 @@ static int oidc_request_check_cookie_domain(request_rec *r, oidc_cfg_t *c, oidc_ return OK; } -#define OIDC_COOKIE_SAMESITE_LAX(c, r) \ - oidc_cfg_cookie_same_site_get(c) ? OIDC_COOKIE_EXT_SAME_SITE_LAX : OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r) +static const char *oidc_request_samesite_cookie(request_rec *r, struct oidc_cfg_t *c) { + const char *rv = NULL; + switch (oidc_cfg_cookie_same_site_get(c)) { + case OIDC_SAMESITE_COOKIE_STRICT: + case OIDC_SAMESITE_COOKIE_LAX: + rv = OIDC_HTTP_COOKIE_SAMESITE_LAX; + break; + case OIDC_SAMESITE_COOKIE_NONE: + rv = OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r); + break; + case OIDC_SAMESITE_COOKIE_DISABLED: + default: + break; + } + return rv; +} /* * set the state that is maintained between an authorization request and an authorization response @@ -135,7 +149,7 @@ static int oidc_request_authorization_set_cookie(request_rec *r, oidc_cfg_t *c, const char *cookieName = oidc_state_cookie_name(r, state); /* set it as a cookie */ - oidc_http_set_cookie(r, cookieName, cookieValue, -1, OIDC_COOKIE_SAMESITE_LAX(c, r)); + oidc_http_set_cookie(r, cookieName, cookieValue, -1, oidc_request_samesite_cookie(r, c)); return OK; } diff --git a/src/handle/response.c b/src/handle/response.c index 7a6c7311..e70a2fd4 100644 --- a/src/handle/response.c +++ b/src/handle/response.c @@ -327,6 +327,9 @@ apr_byte_t oidc_response_save_in_session(request_rec *r, oidc_cfg_t *c, oidc_ses sid = id_token_jwt->payload.sub; session->sid = oidc_response_make_sid_iss_unique(r, sid, oidc_cfg_provider_issuer_get(provider)); + /* indicate that this is a newly created session */ + oidc_session_set_session_new(r, session, 1); + /* store the session */ return oidc_session_save(r, session, TRUE); } @@ -352,7 +355,7 @@ static apr_byte_t oidc_response_proto_state_restore(request_rec *r, oidc_cfg_t * } /* clear state cookie because we don't need it anymore */ - oidc_http_set_cookie(r, cookieName, "", 0, OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r)); + oidc_http_set_cookie(r, cookieName, "", 0, OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r)); *proto_state = oidc_proto_state_from_cookie(r, c, cookieValue); if (*proto_state == NULL) diff --git a/src/http.h b/src/http.h index d1fdff3f..d729624a 100644 --- a/src/http.h +++ b/src/http.h @@ -94,6 +94,10 @@ #define OIDC_HTTP_HDR_VAL_NAVIGATE "navigate" #define OIDC_HTTP_HDR_VAL_DOCUMENT "document" +#define OIDC_HTTP_COOKIE_SAMESITE_LAX "SameSite=Lax" +#define OIDC_HTTP_COOKIE_SAMESITE_STRICT "SameSite=Strict" +#define OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r) oidc_util_request_is_secure(r, c) ? "SameSite=None" : NULL + typedef struct oidc_http_timeout_t { int request_timeout; // in seconds int connect_timeout; // in seconds diff --git a/src/mod_auth_openidc.c b/src/mod_auth_openidc.c index c13b6abf..c2b23078 100644 --- a/src/mod_auth_openidc.c +++ b/src/mod_auth_openidc.c @@ -662,6 +662,12 @@ apr_byte_t oidc_session_pass_tokens(request_rec *r, oidc_cfg_t *cfg, oidc_sessio } } + // if this is a newly created session, we'll write it again to update the samesite setting on the session cookie + if (oidc_session_get_session_new(r, session)) { + *needs_save = TRUE; + oidc_session_set_session_new(r, session, 0); + } + /* log message about session expiry */ oidc_log_session_expires(r, "session inactivity timeout", session->expiry); diff --git a/src/mod_auth_openidc.h b/src/mod_auth_openidc.h index 46422cfc..8d01951e 100644 --- a/src/mod_auth_openidc.h +++ b/src/mod_auth_openidc.h @@ -132,10 +132,6 @@ #define OIDC_APP_INFO_USERINFO_JWT "userinfo_jwt" #define OIDC_APP_INFO_SIGNED_JWT "signed_jwt" -#define OIDC_COOKIE_EXT_SAME_SITE_LAX "SameSite=Lax" -#define OIDC_COOKIE_EXT_SAME_SITE_STRICT "SameSite=Strict" -#define OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r) oidc_util_request_is_secure(r, c) ? "SameSite=None" : NULL - int oidc_check_user_id(request_rec *r); int oidc_fixups(request_rec *r); apr_byte_t oidc_enabled(request_rec *r); diff --git a/src/session.c b/src/session.c index 52c1a938..e89f26f4 100644 --- a/src/session.c +++ b/src/session.c @@ -183,13 +183,33 @@ static apr_byte_t oidc_session_load_cache(request_rec *r, oidc_session_t *z) { if (z->state == NULL) { /* delete the session cookie */ oidc_http_set_cookie(r, oidc_cfg_dir_cookie_get(r), "", 0, - OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r)); + OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r)); } } return rc; } +static const char *oidc_session_samesite_cookie(request_rec *r, struct oidc_cfg_t *c, int first_time) { + const char *rv = NULL; + switch (oidc_cfg_cookie_same_site_get(c)) { + case OIDC_SAMESITE_COOKIE_STRICT: + rv = first_time ? OIDC_HTTP_COOKIE_SAMESITE_LAX : OIDC_HTTP_COOKIE_SAMESITE_STRICT; + break; + case OIDC_SAMESITE_COOKIE_LAX: + rv = OIDC_HTTP_COOKIE_SAMESITE_LAX; + break; + case OIDC_SAMESITE_COOKIE_NONE: + rv = OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r); + break; + case OIDC_SAMESITE_COOKIE_DISABLED: + break; + default: + break; + } + return rv; +} + /* * save the session to the cache using a cookie for the index */ @@ -215,8 +235,7 @@ static apr_byte_t oidc_session_save_cache(request_rec *r, oidc_session_t *z, apr /* set the uuid in the cookie */ oidc_http_set_cookie(r, oidc_cfg_dir_cookie_get(r), z->uuid, oidc_cfg_persistent_session_cookie_get(c) ? z->expiry : -1, - oidc_cfg_cookie_same_site_get(c) ? OIDC_COOKIE_EXT_SAME_SITE_LAX - : OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r)); + oidc_session_samesite_cookie(r, c, first_time)); } else { @@ -224,7 +243,7 @@ static apr_byte_t oidc_session_save_cache(request_rec *r, oidc_session_t *z, apr oidc_cache_set_sid(r, z->sid, NULL, 0); /* clear the cookie */ - oidc_http_set_cookie(r, oidc_cfg_dir_cookie_get(r), "", 0, OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r)); + oidc_http_set_cookie(r, oidc_cfg_dir_cookie_get(r), "", 0, OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r)); /* remove the session from the cache */ rc = oidc_cache_set_session(r, z->uuid, NULL, 0); @@ -253,12 +272,10 @@ static apr_byte_t oidc_session_save_cookie(request_rec *r, oidc_session_t *z, ap if ((z->state != NULL) && (oidc_session_encode(r, c, z, &cookieValue, TRUE) == FALSE)) return FALSE; - oidc_http_set_chunked_cookie(r, oidc_cfg_dir_cookie_get(r), cookieValue, - oidc_cfg_persistent_session_cookie_get(c) ? z->expiry : -1, - oidc_cfg_session_cookie_chunk_size_get(c), - (z->state == NULL) ? OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r) - : oidc_cfg_cookie_same_site_get(c) ? OIDC_COOKIE_EXT_SAME_SITE_LAX - : OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r)); + oidc_http_set_chunked_cookie( + r, oidc_cfg_dir_cookie_get(r), cookieValue, oidc_cfg_persistent_session_cookie_get(c) ? z->expiry : -1, + oidc_cfg_session_cookie_chunk_size_get(c), + (z->state == NULL) ? OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r) : oidc_session_samesite_cookie(r, c, first_time)); return TRUE; } @@ -473,6 +490,8 @@ apr_byte_t oidc_session_set(request_rec *r, oidc_session_t *z, const char *key, #define OIDC_SESSION_KEY_ISSUER "iss" /* key for storing the provider specific user info refresh interval */ #define OIDC_SESSION_KEY_USERINFO_REFRESH_INTERVAL "uir" +/* key for storing whether this is a newly created session or not */ +#define OIDC_SESSION_KEY_SESSION_IS_NEW "sn" /* * helper functions @@ -768,3 +787,19 @@ void oidc_session_set_issuer(request_rec *r, oidc_session_t *z, const char *issu const char *oidc_session_get_issuer(request_rec *r, oidc_session_t *z) { return oidc_session_get_key2string(r, z, OIDC_SESSION_KEY_ISSUER); } + +/* + * new session + */ +void oidc_session_set_session_new(request_rec *r, oidc_session_t *z, const int is_new) { + if (z->state == NULL) + z->state = json_object(); + if (is_new) + json_object_set_new(z->state, OIDC_SESSION_KEY_SESSION_IS_NEW, json_integer(1)); + else + json_object_del(z->state, OIDC_SESSION_KEY_SESSION_IS_NEW); +} + +int oidc_session_get_session_new(request_rec *r, oidc_session_t *z) { + return oidc_session_get_int(r, z, OIDC_SESSION_KEY_SESSION_IS_NEW, 0); +} diff --git a/src/session.h b/src/session.h index 37eb0ae5..ff593c2f 100644 --- a/src/session.h +++ b/src/session.h @@ -107,5 +107,7 @@ const char *oidc_session_get_session_state(request_rec *r, oidc_session_t *z); void oidc_session_set_issuer(request_rec *r, oidc_session_t *z, const char *issuer); const char *oidc_session_get_issuer(request_rec *r, oidc_session_t *z); void oidc_session_set_client_id(request_rec *r, oidc_session_t *z, const char *client_id); +void oidc_session_set_session_new(request_rec *r, oidc_session_t *z, const int is_new); +int oidc_session_get_session_new(request_rec *r, oidc_session_t *z); #endif /* _MOD_AUTH_OPENIDC_SESSION_H_ */ diff --git a/src/state.c b/src/state.c index 0912e973..46bfb90f 100644 --- a/src/state.c +++ b/src/state.c @@ -139,7 +139,7 @@ static int oidc_state_cookies_delete_oldest(request_rec *r, oidc_cfg_t *c, int n if (oldest) { oidc_warn(r, "deleting oldest state cookie: %s (time until expiry %" APR_TIME_T_FMT " seconds)", oldest->name, apr_time_sec(oldest->timestamp - apr_time_now())); - oidc_http_set_cookie(r, oldest->name, "", 0, OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r)); + oidc_http_set_cookie(r, oldest->name, "", 0, OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r)); if (prev_oldest) prev_oldest->next = oldest->next; else @@ -186,7 +186,7 @@ int oidc_state_cookies_clean_expired(request_rec *r, oidc_cfg_t *c, const char * oidc_proto_state_get_original_url(proto_state)); oidc_http_set_cookie( r, cookieName, "", 0, - OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r)); + OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r)); } else { if (first == NULL) { first = apr_pcalloc( @@ -209,7 +209,7 @@ int oidc_state_cookies_clean_expired(request_rec *r, oidc_cfg_t *c, const char * "state cookie could not be retrieved/decoded, deleting: %s", cookieName); oidc_http_set_cookie(r, cookieName, "", 0, - OIDC_COOKIE_EXT_SAME_SITE_NONE(c, r)); + OIDC_HTTP_COOKIE_SAMESITE_NONE(c, r)); } } }