Filtering_authentication_methods

Problem this snippet solves:

In certain circumstances, some clients, when presented with multiple WWW-Authenticate headers in 401 responses, misbehave in unpredictable ways. Sometimes, this misbehavior can be resolved by not presenting the client with certain authentication challenges while leaving the ones they support alone.

This iRule allows for filtering Authentication challenges based on the User-Agent value of the client and the requested URI. The criteria should be tuned according to the needs of the clients and the application.

The provided configuration removes Basic authentication challenges from responses to Microsoft Outlook and Office clients specifically when they request the autodiscover service.

Code :

when HTTP_REQUEST {
  ## Set all flags to false for each request
  set FILTER_AUTH_NEGOTIATE 0
  set FILTER_AUTH_NTLM 0
  set FILTER_AUTH_BASIC 0

  ## Uncomment the following to enable logging
  set FILTER_AUTH_LOG "[IP::client_addr]:[TCP::client_port] requested [HTTP::header Host][HTTP::path [HTTP::uri]] and had these Auth methods retained or removed: "  
  

  ## Based on User-Agent and URI path, set the filter flags
  ## These are case sensitive patterns  
  switch -glob [HTTP::header User-Agent] {
"MSRPC" -
"*Microsoft Office*" -
    "*MSIE*" {
  ## For all Internet Explorer clients and other MS Outlook clients that use given User-Agent values  
      switch -glob [HTTP::path [HTTP::uri]] {
"/xml/autodiscover.aspx" -  
    "/autodiscover/autodiscover.xml" { set FILTER_AUTH_BASIC 1 }
      }
    }
    default {
  ## NO-OP
    }
  }
}

when HTTP_RESPONSE {
if { [HTTP::status] == 401 } {

  ## Store all values of WWW-Authenticate
  set WWW_AUTH_VALUE_LIST [HTTP::header values WWW-Authenticate]

  ## Remove all header instances from the response
  HTTP::header remove WWW-Authenticate

  ## Selectively put the values back in.

  foreach WWW_AUTH_VALUE $WWW_AUTH_VALUE_LIST {
    switch -glob [string tolower $WWW_AUTH_VALUE] {
  "negotiate *" {
if { not $FILTER_AUTH_NEGOTIATE } { 
  HTTP::header insert WWW-Authenticate $WWW_AUTH_VALUE
  if { [info exists FILTER_AUTH_LOG] } { append FILTER_AUTH_LOG "+NEGOTIATE " } 
} else {
  if { [info exists FILTER_AUTH_LOG] } { append FILTER_AUTH_LOG "-NEGOTIATE " }
    }  
      }
  "ntlm *" {
if { not $FILTER_AUTH_NTLM } { 
  HTTP::header insert WWW-Authenticate $WWW_AUTH_VALUE 
  if { [info exists FILTER_AUTH_LOG] } { append FILTER_AUTH_LOG "+NTLM " }  
    } else {
  if { [info exists FILTER_AUTH_LOG] } { append FILTER_AUTH_LOG "-NTLM " }
    }
      }
  "basic *" {
if { not $FILTER_AUTH_BASIC } { 
  HTTP::header insert WWW-Authenticate $WWW_AUTH_VALUE 
  if { [info exists FILTER_AUTH_LOG] } { append FILTER_AUTH_LOG "+BASIC " }  
} else {
  if { [info exists FILTER_AUTH_LOG] } { append FILTER_AUTH_LOG "-BASIC " }
    }
      }
    }  
  }

  ## If logging is enabled, send the constructed log line to syslog now
  if { [info exists FILTER_AUTH_LOG] } { log local0. $FILTER_AUTH_LOG }

  if { not [HTTP::header exists WWW-Authenticate] } {
# If all authentication challenges are filtered out, a 401 is not legal
# Replace with a 403 with explanatory content
set NO_AUTH_REMAINING "No authentication methods remaining."
set NO_AUTH_CONTENT_TYPE "text/plain"
HTTP::respond 403 content $NO_AUTH_REMAINING noserver Content-Type $NO_AUTH_CONTENT_TYPE  Content-Length [string length $NO_AUTH_REMAINING]
  }
}  
}
Published Mar 17, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment