F5 Sites
  • F5.com
  • F5 Labs
  • MyF5
  • NGINX
  • Partner Central
  • Education Services Portal (ESP)
Contact
  • Under Attack?
  • F5 Support
  • DevCentral Support
  • F5 Sales
  • NGINX Sales
  • F5 Professional Services
Skip to contentBrand Logo
Forums
CrowdSRC
Articles
GroupsEventsSuggestionsHow Do I...?
RegisterSign In
  1. DevCentral
  2. CrowdSRC
  3. CodeShare

APM Sharepoint authentication

Problem this snippet solves: Updated version to support Webdav with windows explorer after Nicolas's comment. APM is a great authentication service but it does it only with forms. The default be...
Published Apr 20, 2016
Version 1.0
BIG-IP Access Policy Manager (APM)
editing office documents
iRules
ms-ofba
programmability contest
security
sharepoint
Stanislas_Piro2's avatar
Stanislas_Piro2
Icon for Cumulonimbus rankCumulonimbus
Joined January 04, 2011
View Profile
Stanislas_Piro2's avatar
Stanislas_Piro2
Icon for Cumulonimbus rankCumulonimbus
Sep 15, 2016

Hi Kai,

I followed all your advices (except lockout, One solution instead of blocking with table can be deleting in ACCESS_POLICY_COMPLETED sessions of user with same username if VPE lockout occurs)

here is the new version :

when RULE_INIT {
   set static::Basic_Realm_Text "SharePoint Authentication"
}

when CLIENT_ACCEPTED {
    set inject_session_cookie 0
    set last_ua_agent "init"
}

when HTTP_REQUEST {
    if { ! [ info exists SP_PROFILE_RESTRICT_SINGLE_IP ] } {
        set SP_PROFILE_RESTRICT_SINGLE_IP        [PROFILE::access restrict_to_single_client_ip]
    } 
     Identify User-Agents type
    if { $last_ua_agent equals [set last_ua_agent [HTTP::header value "User-Agent"]] } {
         Do nothing, keep previous request authschema value
        log local0. $last_ua_agent
    } elseif {[HTTP::header exists "X-FORMS_BASED_AUTH_ACCEPTED"] && (([HTTP::header "X-FORMS_BASED_AUTH_ACCEPTED"] equals "t") || ([HTTP::header "X-FORMS_BASED_AUTH_ACCEPTED"] equals "f"))} {
        set clientless_mode 0; set form_mode 1
    } else {
        set clientless_mode 0
        set form_mode 0
        switch -glob -- [string tolower [HTTP::header "User-Agent"]] "*office protocol discovery*" - \
            "*microsoft office*" - \
            "*microsoft data access internet publishing provider*" - \
            "*non-browser*" - \
            "msoffice 12*" - \
            "*microsoft-webdav-miniredir*" - \
            {*ms frontpage 1[23456789]*} {
                 Implicit MSOFBA support detected.   
                set form_mode 1
            } "*ms frontpage*" {
                 Legacy client detected
                set clientless_mode 1
            } "*mozilla*" - \
            "*opera*" {
                 Regular web browser detected.  
                set clientless_mode 0
            } default { 
                set clientless_mode 1
            }
   }
   if { $clientless_mode || $form_mode } {
        if { ( [set sessionid [HTTP::cookie value "MRHSession"]] ne "" ) and ( [ACCESS::session exists -state_allow $sessionid] ) } then {
             Allow the successfully pre authenticated request to pass
            return
        } else {
             Check if persistent APM session cookie is present and valid
            if { ( [set sessionid [HTTP::cookie value "MRHSession_SP"]] ne "" ) and ( [ACCESS::session exists -state_allow $sessionid] ) } then {
                 Restore APM session cookie value
                if { [catch {HTTP::cookie insert name "MRHSession" value $sessionid} ] } {log local0. "[IP::client_addr]:[TCP::client_port] : TCL error on HTTP cookie insert MRHSession : URL : [HTTP::host][HTTP::path] - Headers : [HTTP::request]"} else {return}
                HTTP::cookie insert name "MRHSession" value $sessionid
                set inject_session_cookie 1 
                 Allow the successfully pre authenticated request to pass
                return
            }
        }
    } else {
        set sessionid [HTTP::cookie value "MRHSession"]
        return
    }      
    if { $clientless_mode } {
      if { [ string match -nocase {basic *} [HTTP::header Authorization] ] == 1 } {
         set clientless(insert_mode) 1
         set clientless(src_ip)      [IP::remote_addr]
         set clientless(username)    [ string tolower [HTTP::username] ]
         set clientless(password)    [HTTP::password]
         if { $SP_PROFILE_RESTRICT_SINGLE_IP == 0 } {
                binary scan [md5 "$clientless(password)"] H* clientless(hash)
         } else {
                binary scan [md5 "$clientless(password)$clientless(src_ip)"] H* clientless(hash)
         }
         set user_key "$clientless(username).$clientless(hash)"
         set clientless(cookie_list)             [ ACCESS::user getsid $user_key ]
         if { [ llength $clientless(cookie_list) ] != 0 } {
            set clientless(cookie) [ ACCESS::user getkey [ lindex $clientless(cookie_list) 0 ] ]
            if { $clientless(cookie) != "" } {
               HTTP::cookie insert name MRHSession value $clientless(cookie)
               set clientless(insert_mode) 0
            }
        }
        if { $clientless(insert_mode) } {
            HTTP::header insert "clientless-mode" 1
            HTTP::header insert "username" $clientless(username)
            HTTP::header insert "password" $clientless(password)
        }
        unset clientless
        } else {
            HTTP::respond 401 noserver WWW-Authenticate "Basic realm=\"$static::Basic_Realm_Text\"" Set-Cookie "MRHSession=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/" Connection close
            return
        }
    } elseif {$form_mode && [HTTP::path] ne "/sp-msofba-form"}{
        HTTP::respond 403 -version "1.1" \
            content "Access Denied. Make sure that your client is correctly configured. See https://support.microsoft.com/en-us/kb/932118 for further information." \
            noserver \
            "Content-Type" "text/html" \
            "X-FORMS_BASED_AUTH_REQUIRED" "https://[getfield [HTTP::host] ":" 1]/sp-msofba-form" \
            "X-FORMS_BASED_AUTH_RETURN_URL" "https://[getfield [HTTP::host] ":" 1]/sp-msofba-completed" \
            "X-FORMS_BASED_AUTH_DIALOG_SIZE" "800x600" \
            "Set-Cookie" "MRHSession=deleted;path=/;secure" \
            "Set-Cookie" "LastMRH_Session=deleted;path=/;secure" \
            "Set-Cookie" "MRHSession=deleted; expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;secure" \
            "Set-Cookie" "LastMRH_Session=deleted; expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;secure"
        return
    }
}


when HTTP_RESPONSE {
     Insert persistent cookie for html content type and private session
    if { [HTTP::header "Content-Type" ] contains "text/html" } {
        HTTP::cookie remove MRHSession_SP
        HTTP::cookie insert name MRHSession_SP value $sessionid path "/"
        HTTP::cookie expires MRHSession_SP 120 relative
        HTTP::cookie secure MRHSession_SP enable
    }
     Insert session cookie if session was recovered from persistent cookie
    if { ([info exists "inject_session_cookie"]) && ($inject_session_cookie) } {
        HTTP::cookie insert name MRHSession value $sessionid path "/"
        HTTP::cookie secure MRHSession enable
    }
}

when ACCESS_SESSION_STARTED {
    if {([info exists "clientless_mode"])} {
        ACCESS::session data set session.clientless $clientless_mode
    }
    if { [ info exists user_key ] } {
        ACCESS::session data set "session.user.uuid" $user_key
    }
}

when ACCESS_POLICY_COMPLETED {
    if { ([info exists "clientless_mode"]) && ($clientless_mode) && ([ACCESS::policy result] equals "deny") } {
        set min "[PROFILE::access min_failure_delay]000"
        set max "[PROFILE::access max_failure_delay]000"
        after [expr {int(rand() * ($max + 1 - $min)) + $min}]
        ACCESS::respond 401 noserver WWW-Authenticate "Basic realm=\"$static::Basic_Realm_Text\"" Connection close
        unset min max
        ACCESS::session remove
    } 
}

when ACCESS_ACL_ALLOWED {
    switch -glob [string tolower [HTTP::path]] {
        "/sp-msofba-form" {
            ACCESS::respond 302 noserver Location "/sp-msofba-completed"
        }
        "/sp-msofba-completed" {
            ACCESS::respond 200 content {
                
                Authenticated
                Good Work, you are Authenticated
                
            } noserver
        }
        "*/signout.aspx" {
             Disconnect session and redirect to APM logout Page
            ACCESS::respond 302 noserver Location "/vdesk/hangup.php3"
            return
        }
        "/_layouts/accessdenied.aspx" {
             Disconnect session and redirect to APM Logon Page
            if {[string tolower [URI::query [HTTP::uri] loginasanotheruser]] equals "true" } {
                ACCESS::session remove
                ACCESS::respond 302 noserver Location "/"
                return
            }
        }
        default {
             No Actions
        }
    }
}

Help guide the future of your DevCentral Community!

What tools do you use to collaborate? (1min - anonymous)

ABOUT DEVCENTRAL

DevCentral NewsTechnical ForumTechnical ArticlesTechnical CrowdSRCCommunity GuidelinesDevCentral EULAGet a Developer Lab LicenseBecome a DevCentral MVP

RESOURCES

Product DocumentationWhite PapersGlossaryCustomer StoriesWebinarsFree Online CoursesTraining & Certification

SUPPORT

Manage SubscriptionsProfessional ServicesCreate a Service RequestSoftware DownloadsSupport Portal

PARTNERS

Find a Reseller PartnerTechnology AlliancesBecome an F5 PartnerLogin to Partner Central

©2024 F5, Inc. All rights reserved.
TrademarksPoliciesPrivacyCalifornia PrivacyDo Not Sell My Personal Information