F5 Sites
  • F5.com
  • LearnF5
  • NGINX
  • MyF5
  • Partner Central
Contact
  • Under Attack?
  • F5 Support
  • DevCentral Support
  • F5 Sales
  • NGINX Sales
  • F5 Professional Services
Skip to contentBrand Logo
Forums
CrowdSRC
Articles
Groups
EventsSuggestionsHow Do I...?
RegisterSign In
  1. DevCentral
  2. CrowdSRC
  3. CodeShare

APM Full Step Up Authentication

Problem this snippet solves: By default, APM is not able to handle several authentication during a session. Once you are logged in, it’s finished, you can’t ask for authentication again. Since v1...
Updated Jun 06, 2023
Version 2.0
2-factor
authentication
BIG-IP Access Policy Manager (APM)
iRules
loa
programmability contest
security
step-up
Yann_Desmarest's avatar
Yann_Desmarest
Icon for Cirrus rankCirrus
Joined September 11, 2012
View Profile
Stanislas_Piro2's avatar
Stanislas_Piro2
Icon for Cumulonimbus rankCumulonimbus
Oct 27, 2016

Hi Yann,

Nice Job! I found another way for step-up authentication using ACL instead of Datagroup.

when CLIENT_ACCEPTED {
     retreive ACCESS Profile cookie settings to restore in cookie changes.
    if {[PROFILE::access domain_mode] equals 0 } {
        if { [set cookieproperties ";domain=[PROFILE::access domain_cookie]"] equals ";domain="} {set cookieproperties ""}
        if { [PROFILE::access secure_cookie]} {append cookieproperties ";secure"}
        if { [PROFILE::access httponly_cookie]} {append cookieproperties ";httponly"}
    }
}

when HTTP_REQUEST  {
     If user fails to authenticate in strong auth, restore the previous session cookie.
if { [HTTP::cookie exists AuthRollBack] & [HTTP::cookie exists Session1] } {
        HTTP::respond 302 noserver "Location" "[HTTP::uri]" "Cache-Control" "no-cache, must-revalidate" Set-Cookie "MRHSession=[HTTP::cookie Session1]$cookieproperties;path=/" Set-Cookie "LastMRH_Session=deleted$cookieproperties;expires=Thu, 01-Jan-1970 00:00:10 GMT;path=/" Set-Cookie "Session1=deleted$cookieproperties;expires=Thu, 01-Jan-1970 00:00:10 GMT;path=/" Set-Cookie "AuthRollBack=deleted;expires=Thu, 01-Jan-1970 00:00:10 GMT;path=/"
    }
    set referer [HTTP::header value Referer]
}
when ACCESS_ACL_DENIED {
      If User is denied by ACL and authnetication level is not strong, force to create a new session for strong authentication.
    if {[ACCESS::session data get session.custom.last.strong] == 0 } {
        ACCESS::respond 302 noserver "Location" "[HTTP::uri]" "Cache-Control" "no-cache, must-revalidate" Set-Cookie "MRHSession=deleted$cookieproperties;expires=Thu, 01-Jan-1970 00:00:10 GMT;path=/" Set-Cookie "LastMRH_Session=deleted$cookieproperties;expires=Thu, 01-Jan-1970 00:00:10 GMT;path=/" Set-Cookie "Session1=[HTTP::cookie MRHSession]$cookieproperties;path=/"
        ACCESS::session data set session.custom.last.Referer $referer
    }
}

when ACCESS_SESSION_STARTED {
    If new session and previous session is store in a cookie, prepare policy for strong authentication
    if { [HTTP::cookie exists Session1] and [ACCESS::session exists -state_allow -sid [set sessionid [HTTP::cookie value "Session1"]]] } {
         section : retrieve session variables from the first session

        ACCESS::session data set session.custom.last.username [ACCESS::session data get session.logon.last.username -sid $sessionid]
        ACCESS::session data set session.custom.last.password [ACCESS::session data get session.logon.last.password -sid $sessionid]

         End section

         store the first created session during standard authentication to avoid multiple active sessions
        ACCESS::session data set session.custom.last.session $sessionid
        ACCESS::session data set session.custom.last.strong 1
    } else {
        ACCESS::session data set session.custom.last.strong 0
    }
}

when ACCESS_POLICY_COMPLETED {
     If Strong authentication process
    if {[ACCESS::session data get session.custom.last.strong]} {
        if { ([ACCESS::policy result] equals "deny") } {
             restore previous session if the user failed to authenticate.
            ACCESS::session remove
            ACCESS::respond 302 noserver "Location" [ACCESS::session data get session.custom.last.Referer -sid [ACCESS::session data get session.custom.last.session]] "Cache-Control" "no-cache, must-revalidate" Set-Cookie "AuthRollBack=1;path=/"
        } else {
             Remove the first created session during standard authentication to avoid multiple active sessions
            ACCESS::session remove -sid [ACCESS::session data get session.custom.last.session]
        }
    }
}

The VPE is quite simple (I removed authentication boxes to test... it is simpler)!

In Strong Auth, I set the branch expression

expr { [mcget {session.custom.last.strong}] == 1 }

With this solution, you can assign different ACL based on AD group and manage step-up per user and not a global URL list.

If a user fails to authenticate on strong authentication, he is redirected to the referer stored in a session variable of the previous session.

This irule also manage the access profile cookie parameters (Secure, httponly, domain).

I removed the cookie encryption as F5 does not encrypt the default session cookie and I preserve cookie security parameters for session1 cookie.

This solution does not manage 2 way to authenticate (standard + strong / standard then strong) but always the same process : standard then strong.

ABOUT DEVCENTRAL

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

RESOURCES

Product DocumentationWhite PapersGlossaryCustomer StoriesWebinarsFree Online CoursesF5 CertificationLearnF5 Training

SUPPORT

Manage SubscriptionsProfessional ServicesProfessional ServicesCreate a Service RequestSoftware DownloadsSupport Portal

PARTNERS

Find a Reseller PartnerTechnology AlliancesBecome an F5 PartnerLogin to Partner Central

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