Forum Discussion

kj07208_118528's avatar
Mar 13, 2014

302 Redirect and http headers

I have a iRule that I'm trying to do a redirect but make the redirect pass http headers to another server (this is in a different domain). The access policy will authenticate the user and get certain information from AD. This information needs to be sent to the other web application with the data in http headers (not my doing 🙂 ). Can headers be passed this way and what would be the syntax for the http:respond with http headers?

when ACCESS_POLICY_COMPLETED {
    set policy_result [ACCESS::policy result]
    switch $policy_result {
    "allow" {
        set clientid "12345"   
        set userid "[ACCESS::session data get session.saml.last.attr.name.employeeID]"   
        set timestamp "[ACCESS::session data get session.custom.form.timestamp]"   
        log local0. "***** clientId $clientid"
        log local0. "***** userid $userid"
        log local0. "***** timestamp $timestamp"
        HTTP::respond 302 Location "https://xyz.domain.com/" "client_id" $clientid "client_userid" $userid "client_timestamp" $timestamp        
       Trying to do something like this HTTP::response 302 Location "https://xyz" "http-header client_id $clientid"  "http-header client_userid $user ..."             

    }
    "deny" {
        ACCESS::respond 401 content "Error: Failure in Authentication" Connection Close
    }
    }
}

3 Replies

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account

    If you're using the HTTP::respond command then you certainly could post your own headers and data in that way. Have you tested this yet?

     

    • kj07208_118528's avatar
      kj07208_118528
      Icon for Cirrus rankCirrus
      Tried by I'm getting an error I think that it is due to syntax or I'm trying to do this in the wrong place I'm not that familiar with the flow of http request processing in F5.
  • If I may add, a few things:

    1. You definitely want to use ACCESS::respond inside the ACCESS_POLICY_COMPLETED event, otherwise your syntax is good.

      ACCCESS::respond 302 Location $url "HDR name" "value" "HDR name" "value"...        
      
    2. Browsers don't generally relay HTTP headers. You can certainly send them to the browser, but they won't be returned. For that you need a cookie (a type of header actually). HTTP cookies were created to allow browsers to maintain application "state" and are ~always~ relayed back to the server once they're set.

      ACCESS::respond 302 Location $url "Set-Cookie" "cookiename=value; path=/"        
      

      There are a few additional options that you can use when setting a cookie (domain, expires, secure, and httponly) and all are "scoping" mechanisms that tell the browser under what condition to send, or not to send a cookie (ie. the URI matches a specific path, the URL matches a specific domain, the cookie isn't expired, the cookie should only be sent over secure connections, and the cookie should not be accessible to client side script, respectively).

    3. Now here's where it gets a little tricky. By default, browsers will generally only relay cookies in the "domain" in which they're set. It's an interpretation of the "same origin policy" and is an important security feature for browsers. You wouldn't want a cookie sent on an MSN site to be used on a Goole site. I say generally because there are ways around this, but most of the workarounds are not easy. If the servers are in the same domain, that is, the same second-level or higher domain (ex. www.domain.com, shop.domain.com, and vote.domain.com = *.domain.com), then you can specify a domain option in the Set-Cookie header that will permit the browser to send the cookie to any matching domain.

      "Set-Cookie" "cookiename=value; path=/; domain=.domain.com"        
      

      But if that's not the case between these two services, then sending a cookie is going to be tough. Of the workarounds to the cross domain restriction, one reliable and often used option is a URI. Assuming this isn't private data, and who would put private data in a cookie anyway (sarcasm but a sad reality) then a URI would be an easy option:

      ACCESS::respond 302 Location "https://site.otherdomain.com/?data=[URI::encode [b64encode ...some data...]]"        
      

      Here I've taken the value I want to send, base64-encoded it, URI-encoded it, and then added it to a query string parameter in the HTTP redirect URI. I could have optionally encrypted it, but again who puts sensitive data in a cookie anyway. If the other side was also an F5 (though not expressly required) it'd be a simple matter of reversing that process to fetch the data:

      when HTTP_REQUEST {        
          if { [URI::query [HTTP::uri] data] ne "" } {            
              set data [b64decode [URI::decode [URI::query [HTTP::uri] data]]]        
          }            
      }        
      when HTTP_RESPONSE {        
          if { [info exists data] } {            
              HTTP::cookie insert name "data-from-other-site" value $data                
              unset data
          }            
      }        
      

      If the "data" query string exists in the request (at the other site), we extract it, decode it, optionally do something with it in the request, and then insert it as a local cookie back to the browser. That is of course just one option.