@@ -611,8 +611,8 @@ static int oidc_clean_expired_state_cookies(request_rec *r, oidc_cfg *c,
611611/*
612612 * restore the state that was maintained between authorization request and response in an encrypted cookie
613613 */
614- static apr_byte_t oidc_restore_proto_state (request_rec * r , oidc_cfg * c , const char * state ,
615- oidc_proto_state_t * * proto_state ) {
614+ static apr_byte_t oidc_restore_proto_state (request_rec * r , oidc_cfg * c ,
615+ const char * state , oidc_proto_state_t * * proto_state ) {
616616
617617 oidc_debug (r , "enter" );
618618
@@ -624,12 +624,15 @@ static apr_byte_t oidc_restore_proto_state(request_rec *r, oidc_cfg *c, const ch
624624 /* get the state cookie value first */
625625 char * cookieValue = oidc_util_get_cookie (r , cookieName );
626626 if (cookieValue == NULL ) {
627- oidc_error (r , "no \"%s\" state cookie found: check domain and samesite cookie settings" , cookieName );
627+ oidc_error (r ,
628+ "no \"%s\" state cookie found: check domain and samesite cookie settings" ,
629+ cookieName );
628630 return FALSE;
629631 }
630632
631633 /* clear state cookie because we don't need it anymore */
632- oidc_util_set_cookie (r , cookieName , "" , 0 , OIDC_COOKIE_EXT_SAME_SITE_NONE (c , r ));
634+ oidc_util_set_cookie (r , cookieName , "" , 0 ,
635+ OIDC_COOKIE_EXT_SAME_SITE_NONE (c , r ));
633636
634637 * proto_state = oidc_proto_state_from_cookie (r , c , cookieValue );
635638 if (* proto_state == NULL )
@@ -641,7 +644,9 @@ static apr_byte_t oidc_restore_proto_state(request_rec *r, oidc_cfg *c, const ch
641644 char * calc = oidc_get_browser_state_hash (r , c , nonce );
642645 /* compare the calculated hash with the value provided in the authorization response */
643646 if (_oidc_strcmp (calc , state ) != 0 ) {
644- oidc_error (r , "calculated state from cookie does not match state parameter passed back in URL: \"%s\" != \"%s\"" , state , calc );
647+ oidc_error (r ,
648+ "calculated state from cookie does not match state parameter passed back in URL: \"%s\" != \"%s\"" ,
649+ state , calc );
645650 oidc_proto_state_destroy (* proto_state );
646651 return FALSE;
647652 }
@@ -652,14 +657,14 @@ static apr_byte_t oidc_restore_proto_state(request_rec *r, oidc_cfg *c, const ch
652657 if (apr_time_now () > ts + apr_time_from_sec (c -> state_timeout )) {
653658 oidc_error (r , "state has expired" );
654659 if ((c -> default_sso_url == NULL )
655- || (apr_table_get (r -> subprocess_env , "OIDC_NO_DEFAULT_URL_ON_STATE_TIMEOUT" ) != NULL )) {
656- oidc_util_html_send_error ( r , c -> error_template , "Invalid Authentication Response" , apr_psprintf ( r -> pool , "This is due to a timeout; please restart your authentication session by re-entering the URL/bookmark you originally wanted to access: %s" , oidc_proto_state_get_original_url ( * proto_state )),
657- OK );
658- /*
659- * a hack for Apache 2.4 to prevent it from writing its own 500/400/302 HTML document
660- * text by making ap_send_error_response in http_protocol.c return early...
661- */
662- r -> header_only = 1 ;
660+ || (apr_table_get (r -> subprocess_env ,
661+ "OIDC_NO_DEFAULT_URL_ON_STATE_TIMEOUT" ) != NULL )) {
662+ oidc_util_html_send_error ( r , c -> error_template ,
663+ "Invalid Authentication Response" ,
664+ apr_psprintf ( r -> pool ,
665+ "This is due to a timeout; please restart your authentication session by re-entering the URL/bookmark you originally wanted to access: %s" ,
666+ oidc_proto_state_get_original_url ( * proto_state )),
667+ OK ) ;
663668 }
664669 oidc_proto_state_destroy (* proto_state );
665670 return FALSE;
@@ -669,7 +674,8 @@ static apr_byte_t oidc_restore_proto_state(request_rec *r, oidc_cfg *c, const ch
669674 oidc_proto_state_set_state (* proto_state , state );
670675
671676 /* log the restored state object */
672- oidc_debug (r , "restored state: %s" , oidc_proto_state_to_string (r , * proto_state ));
677+ oidc_debug (r , "restored state: %s" ,
678+ oidc_proto_state_to_string (r , * proto_state ));
673679
674680 /* we've made it */
675681 return TRUE;
@@ -1997,8 +2003,8 @@ static int oidc_handle_authorization_response(request_rec *r, oidc_cfg *c,
19972003
19982004 /* match the returned state parameter against the state stored in the browser */
19992005 if (oidc_authorization_response_match_state (r , c ,
2000- apr_table_get (params , OIDC_PROTO_STATE ), & provider , & proto_state )
2001- == FALSE) {
2006+ apr_table_get (params , OIDC_PROTO_STATE ), & provider ,
2007+ & proto_state ) == FALSE) {
20022008 if (c -> default_sso_url != NULL ) {
20032009 oidc_warn (r ,
20042010 "invalid authorization response state; a default SSO URL is set, sending the user there: %s" ,
@@ -2009,11 +2015,21 @@ static int oidc_handle_authorization_response(request_rec *r, oidc_cfg *c,
20092015 }
20102016 oidc_error (r ,
20112017 "invalid authorization response state and no default SSO URL is set, sending an error..." );
2012- // if content was already returned via html/http send then don't return 500
2013- // but send 200 to avoid extraneous internal error document text to be sent
2014- return ((r -> user ) && (_oidc_strncmp (r -> user , "" , 1 ) == 0 )) ?
2015- OK :
2016- HTTP_BAD_REQUEST ;
2018+
2019+ // detect if we've set a (timeout) error message in oidc_authorization_response_match_state
2020+ if (apr_table_get (r -> subprocess_env , OIDC_ERROR_ENVVAR ) != NULL ) {
2021+ // overrides the OK from the timeout detection
2022+ return HTTP_BAD_REQUEST ;
2023+ } else if (c -> error_template ) {
2024+ // for backwards compatibility
2025+ if ((r -> user ) && (_oidc_strncmp (r -> user , "" , 1 ) == 0 ))
2026+ return HTTP_BAD_REQUEST ;
2027+ }
2028+
2029+ return oidc_util_html_send_error (r , c -> error_template ,
2030+ "Invalid Authorization Response" ,
2031+ "Could not match the authorization response to an earlier request via the state parameter and corresponding state cookie" ,
2032+ HTTP_BAD_REQUEST );
20172033 }
20182034
20192035 /* see if the response is an error response */
@@ -2088,7 +2104,8 @@ static int oidc_handle_authorization_response(request_rec *r, oidc_cfg *c,
20882104 return HTTP_INTERNAL_SERVER_ERROR ;
20892105 }
20902106
2091- oidc_debug (r , "set remote_user to \"%s\" in new session \"%s\"" , r -> user , session -> uuid );
2107+ oidc_debug (r , "set remote_user to \"%s\" in new session \"%s\"" ,
2108+ r -> user , session -> uuid );
20922109
20932110 } else {
20942111 oidc_error (r , "remote user could not be set" );
@@ -4186,57 +4203,71 @@ static authz_status oidc_handle_unauthorized_user24(request_rec *r) {
41864203
41874204 oidc_debug (r , "enter" );
41884205
4189- oidc_cfg * c = ap_get_module_config (r -> server -> module_config , & auth_openidc_module );
4206+ oidc_cfg * c = ap_get_module_config (r -> server -> module_config ,
4207+ & auth_openidc_module );
41904208 char * html_head = NULL ;
41914209
41924210 if (apr_strnatcasecmp ((const char * ) ap_auth_type (r ),
4193- OIDC_AUTH_TYPE_OPENID_OAUTH20 ) == 0 ) {
4194- oidc_debug (r , "setting environment variable %s to \"%s\" for usage in mod_headers" , OIDC_OAUTH_BEARER_SCOPE_ERROR , OIDC_OAUTH_BEARER_SCOPE_ERROR_VALUE );
4195- apr_table_set (r -> subprocess_env , OIDC_OAUTH_BEARER_SCOPE_ERROR , OIDC_OAUTH_BEARER_SCOPE_ERROR_VALUE );
4211+ OIDC_AUTH_TYPE_OPENID_OAUTH20 ) == 0 ) {
4212+ oidc_debug (r ,
4213+ "setting environment variable %s to \"%s\" for usage in mod_headers" ,
4214+ OIDC_OAUTH_BEARER_SCOPE_ERROR ,
4215+ OIDC_OAUTH_BEARER_SCOPE_ERROR_VALUE );
4216+ apr_table_set (r -> subprocess_env , OIDC_OAUTH_BEARER_SCOPE_ERROR ,
4217+ OIDC_OAUTH_BEARER_SCOPE_ERROR_VALUE );
41964218 return AUTHZ_DENIED ;
41974219 }
41984220
41994221 /* see if we've configured OIDCUnAutzAction for this path */
42004222 switch (oidc_dir_cfg_unautz_action (r )) {
4201- case OIDC_UNAUTZ_RETURN403 :
4202- case OIDC_UNAUTZ_RETURN401 :
4203- if (oidc_dir_cfg_unauthz_arg (r )) {
4204- oidc_util_html_send (r , "Authorization Error" , NULL , NULL , oidc_dir_cfg_unauthz_arg (r ),
4205- HTTP_UNAUTHORIZED );
4206- r -> header_only = 1 ;
4207- }
4208- return AUTHZ_DENIED ;
4209- case OIDC_UNAUTZ_RETURN302 :
4210- html_head =
4211- apr_psprintf (r -> pool , "<meta http-equiv=\"refresh\" content=\"0; url=%s\">" , oidc_dir_cfg_unauthz_arg (r ));
4212- oidc_util_html_send (r , "Authorization Error Redirect" , html_head , NULL , NULL ,
4223+ case OIDC_UNAUTZ_RETURN403 :
4224+ case OIDC_UNAUTZ_RETURN401 :
4225+ if (oidc_dir_cfg_unauthz_arg (r )) {
4226+ oidc_util_html_send_error (r , c -> error_template ,
4227+ "Authorization Error" , oidc_dir_cfg_unauthz_arg (r ),
42134228 HTTP_UNAUTHORIZED );
4214- r -> header_only = 1 ;
4229+ if (c -> error_template )
4230+ r -> header_only = 1 ;
4231+ }
4232+ return AUTHZ_DENIED ;
4233+ case OIDC_UNAUTZ_RETURN302 :
4234+ html_head = apr_psprintf (r -> pool ,
4235+ "<meta http-equiv=\"refresh\" content=\"0; url=%s\">" ,
4236+ oidc_dir_cfg_unauthz_arg (r ));
4237+ oidc_util_html_send (r , "Authorization Error Redirect" , html_head , NULL ,
4238+ NULL ,
4239+ HTTP_UNAUTHORIZED );
4240+ r -> header_only = 1 ;
4241+ return AUTHZ_DENIED ;
4242+ case OIDC_UNAUTZ_AUTHENTICATE :
4243+ /*
4244+ * exception handling: if this looks like an HTTP request that cannot
4245+ * complete an authentication round trip to the provider, we
4246+ * won't redirect the user and thus avoid creating a state cookie
4247+ */
4248+ if (oidc_is_auth_capable_request (r ) == FALSE)
42154249 return AUTHZ_DENIED ;
4216- case OIDC_UNAUTZ_AUTHENTICATE :
4217- /*
4218- * exception handling: if this looks like an HTTP request that cannot
4219- * complete an authentication round trip to the provider, we
4220- * won't redirect the user and thus avoid creating a state cookie
4221- */
4222- if (oidc_is_auth_capable_request (r ) == FALSE)
4223- return AUTHZ_DENIED ;
4224- break ;
4250+ break ;
42254251 }
42264252
4227- oidc_authenticate_user (r , c , NULL , oidc_get_current_url (r , c -> x_forwarded_headers ), NULL ,
4228- NULL , NULL , oidc_dir_cfg_path_auth_request_params (r ), oidc_dir_cfg_path_scope (r ));
4253+ oidc_authenticate_user (r , c , NULL ,
4254+ oidc_get_current_url (r , c -> x_forwarded_headers ), NULL ,
4255+ NULL , NULL , oidc_dir_cfg_path_auth_request_params (r ),
4256+ oidc_dir_cfg_path_scope (r ));
42294257
42304258 const char * location = oidc_util_hdr_out_location_get (r );
42314259
4232- if ((oidc_request_state_get (r , OIDC_REQUEST_STATE_KEY_DISCOVERY ) != NULL ) && (location == NULL ))
4260+ if ((oidc_request_state_get (r , OIDC_REQUEST_STATE_KEY_DISCOVERY ) != NULL )
4261+ && (location == NULL ))
42334262 return AUTHZ_GRANTED ;
42344263
42354264 if (location != NULL ) {
4236- oidc_debug (r , "send HTML refresh with authorization redirect: %s" , location );
4265+ oidc_debug (r , "send HTML refresh with authorization redirect: %s" ,
4266+ location );
42374267
4238- html_head =
4239- apr_psprintf (r -> pool , "<meta http-equiv=\"refresh\" content=\"0; url=%s\">" , location );
4268+ html_head = apr_psprintf (r -> pool ,
4269+ "<meta http-equiv=\"refresh\" content=\"0; url=%s\">" ,
4270+ location );
42404271 oidc_util_html_send (r , "Stepup Authentication" , html_head , NULL , NULL ,
42414272 HTTP_UNAUTHORIZED );
42424273 /*
0 commit comments