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 behavior is to redirect user to /my.policy to process VPE. this redirect is only supported for GET method.
Sharepoint provide 3 different access types:
- browsing web site with a browser
- Editing documents with Office
- browser folder with webdav client (or editing documents with libreoffice through webdav protocol)
This irule display best authentication method for each of these access types:
- browsers authenticate with default authentication method (form based authentication)
- Microsoft office authenticate with Form based authentication (with support of MS-OFBA protocol)
- Libreoffice and webdav clients authenticate with 401 basic authentication
Form based authentication (browser and Microsoft office) is compatible (validated for one customer) with SAML authentication
Editing documents is managed with a persistent cookie expiring after 5 minutes. to be shared between IE and Office, it requires :
- cookie is persistent (expiration date instead of deleted at the end of session)
- web site defined as "trusted sites" in IE.
How to use this snippet:
install this irule and enable it on the VS.
Code :
when RULE_INIT { array set static::MSOFBA { ReqHeader "X-FORMS_BASED_AUTH_REQUIRED" ReqVal "/sp-ofba-form" ReturnHeader "X-FORMS_BASED_AUTH_RETURN_URL" ReturnVal "/sp-ofba-completed" SizeHeader "X-FORMS_BASED_AUTH_DIALOG_SIZE" SizeVal "800x600" } set static::ckname "MRHSession_SP" set static::Basic_Realm_Text "SharePoint Authentication" } when HTTP_REQUEST { set apmsessionid [HTTP::cookie value MRHSession] set persist_cookie [HTTP::cookie value $static::ckname] set clientless_mode 0 set form_mode 0 # Identify User-Agents type if {[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 { switch -glob [string tolower [HTTP::header "User-Agent"]] { "*microsoft-webdav-miniredir*" { set clientless_mode 1 } "*microsoft data access internet publishing provider*" - "*office protocol discovery*" - "*microsoft office*" - "*non-browser*" - "msoffice 12*" { set form_mode 1 } "*mozilla/4.0 (compatible; ms frontpage*" { if { [ string range [getfield [string tolower [HTTP::header "User-Agent"]] "MS FrontPage " 2] 0 1] > 12 } { set form_mode 1 } else { set clientless_mode 1 } } "*mozilla*" - "*opera*" { set clientless_mode 0 } default { set clientless_mode 1 } } } if { $clientless_mode || $form_mode } { if { [HTTP::cookie exists "MRHSession"] } {set apmstatus [ACCESS::session exists -state_allow $apmsessionid]} else {set apmstatus 0} if { !($apmstatus) && [HTTP::cookie exists $static::ckname] } {set apmpersiststatus [ACCESS::session exists -state_allow $persist_cookie]} else {set apmpersiststatus 0} if { ($apmpersiststatus) && !($apmstatus) } { # Add MRHSession cookie for non browser user-agent first request and persistent cookie present if { [catch {HTTP::cookie insert name "MRHSession" value $persist_cookie} ] } {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} } } else { return } if { $clientless_mode && !($apmstatus)} { if { !([HTTP::header Authorization] == "") } { set clientless(insert_mode) 1 set clientless(username) [ string tolower [HTTP::username] ] set clientless(password) [HTTP::password] binary scan [md5 "$clientless(password)"] 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 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 && !($apmstatus) && !([HTTP::path] equals $static::MSOFBA(ReqVal))}{ HTTP::respond 403 -version "1.1" noserver \ $static::MSOFBA(ReqHeader) "https://[HTTP::host]$static::MSOFBA(ReqVal)" \ $static::MSOFBA(ReturnHeader) "https://[HTTP::host]$static::MSOFBA(ReturnVal)" \ $static::MSOFBA(SizeHeader) $static::MSOFBA(SizeVal) \ "Connection" "Close" 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 $static::ckname HTTP::cookie insert name $static::ckname value $apmsessionid path "/" HTTP::cookie expires $static::ckname 120 relative HTTP::cookie secure $static::ckname enable } # Insert session cookie if session was recovered from persistent cookie if { ([info exists "apmpersiststatus"]) && ($apmpersiststatus) } { HTTP::cookie insert name MRHSession value $persist_cookie 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") } { ACCESS::respond 401 noserver WWW-Authenticate "Basic realm=$static::Basic_Realm_Text" Connection close ACCESS::session remove } } when ACCESS_ACL_ALLOWED { switch -glob [string tolower [HTTP::path]] { "/sp-ofba-form" { ACCESS::respond 302 noserver Location "https://[HTTP::host]$static::MSOFBA(ReturnVal)" } "/sp-ofba-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 } } }
Tested this on version:
11.5- Stanislas_Piro2Cumulonimbus
it's not an irule issue but may be a browser behavior change.
- asaf_01_136490Nimbostratus
check that you getting the cookies- i had an issues that the time + timezone was not sync and the cookies was expired .
HTTP::cookie remove $static::ckname HTTP::cookie insert name $static::ckname value $apmsessionid path "/" HTTP::cookie expires $static::ckname 120 relative HTTP::cookie secure $static::ckname enable
- Stanislas_Piro2Cumulonimbus
What is the exact behavior? You says you are prompted... but what kind of prompt?
OFBA? Basic auth pop-up?
With other browsers, is there any OFBA prompt?
- sergio_baza_aloAltocumulus
Actually I'm using the iRule v2.
What I've noticed, (putting logs in the iRule) is that the IE and the Edge uses the same user agent so the behaviour shouldn't be different
EDGE: Jan 23 10:36:54 F5 info tmm1[18133]: Rule /Common/iRule_edicion_documentos : UA: microsoft office excel 2014 (16.0.8431) windows nt 10.0
IE: Jan 23 10:39:40 F5 info tmm[18133]: Rule /Common/iRule_edicion_documentos : UA: microsoft office excel 2014 (16.0.8431) windows nt 10.0
Does anybody has an idea of why is this happening?
Kind regards
- sergio_baza_aloAltocumulus
Hello,
With the new version I'm still having the issue :(
Kind regards
- Nicolas_COLLETNimbostratus
Hello,
It's possible to try the new version of this irule :
Best regards
- sergio_baza_aloAltocumulus
Hello all,
This iRule is working great for me in IE, Firefox and Chrome but I'm having problems with Edge. Everytime I try to open a Microsoft Office document I'm prompted for credentials.
Does someone know how to fix this?
Kind regards
- ryanm99Nimbostratus
Hello Everyone,
I am attempting to set up the iRule that was shared here to allow Microsoft Office Mobile apps to access SharePoint through APM. I am currently running version 13.0.0. When I attempt to access the environment, I get the following in the APM log file:
May 19 22:34:17 DV-BIGIP01 err tmm1[19118]: 01490514:3: (null):Common:00000000: Access encountered error: ERR_ARG. File: ../modules/hudfilter/access/access.c, Function: access_sanitize_portal_headers, Line: 15499 May 19 22:34:17 DV-BIGIP01 err tmm1[19118]: 01490514:3: (null):Common:00000000: Access encountered error: ERR_ARG. File: ../modules/hudfilter/access/access.c, Function: access_forward_request_to_portal, Line: 15578 May 19 22:34:17 DV-BIGIP01 err tmm1[19118]: 01490514:3: (null):Common:00000000: Access encountered error: ERR_ARG. File: ../modules/hudfilter/access/access.c, Function: access_process_state_client_enforce_session, Line: 7261 May 19 22:34:17 DV-BIGIP01 err tmm1[19118]: 01490514:3: (null):Common:00000000: Access encountered error: ERR_ARG. File: ../modules/hudfilter/access/access.c, Function: hud_access_handler, Line: 2735
Does anyone have any ideas on something I could try? On the mobile app side it just spins at connecting for a while and eventually times out. Thanks!text
- Daphne_WonRet. Employee
Everyone, I like to engage the folks here that have deployed OFBA iRules to support authentication access from native Office apps to Sharepoint on-prem. Can you email me to see what authentication methods you need, what version of the Office clients you need to support, and what versions of the Sharepoints you have deployed for? You can email me at d.won@.
- asaf_01_136490Nimbostratus
Hey Kai , can you please publish the final version . another thing , you need to disable the protected mode in IE.