post preservation
1 TopicSupport for POST preservation when APM Multidomain SSO is configured
Problem this snippet solves: F5 doesn't support the preservation of the initial POST request when the Virtual Server has an access profile configured for Multidomain SSO. After authentication, the user is redirected to the initial URL endpoint and issue a GET request instead of a POST request. How to use this snippet: We share a code sample to demonstrate how to support POST preservation in this typical scenario. This irule may need some additional configuration and settings to work properly. As a PoC, we configured two endpoints : sp.expertlab.net and idp.expertlab.net on the same Virtual Server and access profile. The access profile is configured for Multidomain SSO and we prompt the user for a form based authentication. We also added a dummy form prompted to the user after authentication to simplify our testing. Please note that the irule has been successfully tested with Chrome and Firefox. We are still running tests for Internet Explorer and Edge Browsers. Note : APM behave differently between v11, v12 and v13. To make POST preservation work for v11 and v12, you need to add the following variable assign settings before the Allow ending in your access policy : session.server.body = Session Variable session.server.initial_req_body session.policy.result.redirect.url = Session Variable session.server.landinguri_base64 Please note that the order of variable assignment is very important. Moreover, you need to change the name of the request body session variable in the irule too (static::body_var) Flow in v13.x POST https://sp.example.net/post_action.php 307 Temporary Redirect - Location: https://idp.example.net/F5Networks-SSO-Req?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA POST https://idp.example.net/F5Networks-SSO-Req?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA 302 Found - Location: /my.policy GET https://idp.example.net/my.policy 200 OK POST https://idp.example.net/my.policy 302 Found - Location: https://sp.example.net/F5Networks-SSO-Resp?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA&TOKEN=123954 GET https://sp.example.net/F5Networks-SSO-Resp?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA&TOKEN=123954 302 Found - Location: https://sp.example.net/post_action.php?ct=application%2Fx-www-form-urlencoded GET https://sp.example.net/post_action.php?ct=application%2Fx-www-form-urlencoded 200 OK - Body contains JS to force an auto-POST action POST https://sp.example.net/post_action.php ... Flow in v12.x POST https://sp.example.net/post_action.php 307 Temporary Redirect - Location: https://idp.example.net/F5Networks-SSO-Req?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA POST https://idp.example.net/F5Networks-SSO-Req?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA 302 Found - Location: /my.policy GET https://idp.example.net/my.policy 200 OK POST https://idp.example.net/my.policy 302 Found - Location: https://idp.example.net/F5Networks-SSO-Req?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA GET https://idp.example.net/F5Networks-SSO-Req?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA 302 Found - Location: https://sp.example.net/F5Networks-SSO-Resp?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA&TOKEN=123954 GET https://sp.example.net/F5Networks-SSO-Resp?SSO_ORIG_URI=aHR0cHM6Ly9zcC5leGFtcGxlLm5ldC9wb3N0X2FjdGlvbi5waHA&TOKEN=123954 302 Found - Location: https://sp.example.net/post_action.php?ct=application%2Fx-www-form-urlencoded GET https://sp.example.net/post_action.php?ct=application%2Fx-www-form-urlencoded 200 OK - Body contains JS to force an auto-POST action POST https://sp.example.net/post_action.php ... Code : ### # POST preservation feature # for Virtual Server with Multidomain SSO configured # # require : APM ### ### # Special notes # To support POST preservation in v11 and v12, # the administrator needs to configure special session variable assignment before the Allow ending in a Access policy # session.server.body = Session Variable session.server.initial_req_body # session.policy.result.redirect.url = Session Variable session.server.landinguri_base64 ### ### # Release notes # # 2017/11/23 # * Basic support for POST preservation in v13 # * Add support for v11 and v12 environments # # 2017/11/24 # * Replace static::idp_host by [PROFILE::access primary_auth_service] # * Add a static var to enable or disable the dummy form designed for testing purposes # * Avoid POSTing real body multiple times. A dummy var is used to retrieve the original POST content # # 2017/11/25 # * Remove some coding errors # * Refactoring of some parts of the irule ### when RULE_INIT { set static::md_start_uri "/F5Networks-SSO-Req?SSO_ORIG_URI=" # for v11.x and v12.x deployment # set static::body_var "session.server.body" # for v13.x deployment set static::body_var "session.server.initial_req_body" # enable or disable autogenerated testing forms set static::dummy_form 1 } when HTTP_REQUEST { if { ![ACCESS::session exists [HTTP::cookie MRHSession]] and !([HTTP::path] eq "/F5Networks-SSO-Resp") } { if { [HTTP::method] eq "POST" } { # save post data set ct [HTTP::header Content-Type] set uri [HTTP::uri] if { [URI::query $uri] != "" } { set uri $uri&ct=[URI::encode $ct]&f5-mdsso-post=1 } else { set uri $uri?ct=[URI::encode $ct]&f5-mdsso-post=1 } HTTP::respond 307 noserver Location "[PROFILE::access primary_auth_service]$static::md_start_uri[URI::encode [b64encode https://[HTTP::host]$uri]]" Connection Close return } else { HTTP::respond 302 noserver Location "[PROFILE::access primary_auth_service]$static::md_start_uri[URI::encode [b64encode https://[HTTP::host][HTTP::uri]]]" Connection Close return } } if { [ACCESS::session exists [HTTP::cookie MRHSession]] and [HTTP::query] contains "f5-mdsso-post=1" and [ACCESS::session data get $static::body_var] != "" } { set ct [URI::decode [URI::query [HTTP::uri] ct]] set dummy [getfield [expr {rand()}] "." 2] ACCESS::session data set session.server.dummy $dummy ACCESS::session data set session.server.ct $ct HTTP::respond 200 content " this page is used to hold your data while you are being authorized for your request. you will be forwarded to continue the authorization process. if this does not happen automatically, please click the continue button below. " noserver Content-Type "text/html" return } if { [ACCESS::session exists [HTTP::cookie MRHSession]] and [HTTP::method] eq "POST" and [HTTP::payload] contains "dummy" and [ACCESS::session data get session.server.dummy] eq [URI::query "/?[HTTP::payload]" dummy] } { HTTP::header replace Content-Type [ACCESS::session data get session.server.ct] HTTP::payload replace 0 [HTTP::header Content-Length] [ACCESS::session data get $static::body_var] } }1.4KViews0likes8Comments