Open SSO Authentication

Problem this snippet solves:

A simple "Policy Agent" iRule that ensures that all incoming HTTP requests are authenticated against the OpenSSO server(s). I am by no means an iRule programmer, so I'm sure this can be optimized. So far it has been working for me, but if you find any bugs please let me know!

Code :

# OpenSSO "Policy Agent" that merely checks that the incoming request is from an authenticated
# user.  If not, the user is redirected to the appropriate Login UI until a valid SSO token
# is received
# this iRule is just a modified version of the code present by "deb" at

when RULE_INIT {
# set up the global variables we will need throughout the course of this iRule
# most of the customization to handle your specific deployment should be made here

set ::ckname "iPlanetDirectoryPro"

set domain ""
set expired_token "$::ckname=\"LOGOUT\"; expires=Fri, 31-Dec-2000 23
set expired_amlb "amlbcookie=\"LOGOUT\"; expires=Fri, 31-Dec-2000 23
set ::expired_cookies " Set-Cookie $expired_token Set-Cookie $expired_amlb"

# done with the intermediate strings now
unset domain
unset expired_token
unset expired_amlb

set ::loginUI ""

set ::valid_string "boolean=true"

# when the user has been authenticated, this will be set to the valid token
set validCookie ""

# these are the incoming HTTP requests which we have not checked yet. check against
# the OpenSSO server to ensure this is an authenticated user

if {[HTTP::cookie exists $::ckname]} {
set tokenid [string trimleft [HTTP::cookie value $::ckname] "\""]
set tokenid [string trimright "$tokenid" "\""]

if {[string length $validCookie] > 0 && $validCookie eq $tokenid} {
pool pool_policyagent
} else {
set validCookie ""

# if client hasn't already been validated, save the
# request so we can replay it to the LB server later
set LB_request [HTTP::request]

# inject lookup URI in place of original request
HTTP::uri "/opensso/identity/isTokenValid?tokenid=[URI::encode $tokenid]"

# and send the out-of-band validation query to the OpenSSO pool.
pool pool_opensso
} else {
# this request doesnt even have a token to validate, so we need to redirect the the Login UI
HTTP::redirect [format "$::loginUI" [URI::encode "https://[HTTP::host][HTTP::uri]"]]

# If validCookie is empty in response event, this is the response
# to the opensso check, so we collect entire payload (up to 16byte limit)
# to evaluate the OpenSSO response and to prevent this response
# from being returned to the client.
# Already-validated connections will bypass the rest of the rule.

if {[string length $validCookie] <= 0} {
if {[HTTP::header exists Content-Length] && ([HTTP::header Content-Length] < 16)} {
set clength [HTTP::header Content-Length]
} else {
set clength 16

HTTP::collect $clength

# HTTP_RESPONSE_DATA will only be triggered for an OpenSSO check.
# (All other requests have already been forwarded to the Policy Agent pool.)
# If response from OpenSSO indicates authentication, save the token
# and replay the original request to the Policy Agent pool. Otherwise, clear
# the users cookies and redirect to the Login UI

if {[HTTP::payload] contains $::valid_string} {
pool pool_policyagent
HTTP::retry $LB_request

# assume all further requests with this token are valid
regexp {iPlanetDirectoryPro=\"([^\s]*)\"[;]?} $LB_request totalMatch validCookie
unset totalMatch
} else {
# if we had a cookie, we dont now
set validCookie ""

# remove the invalid cookies and redirect to LoginUI
regexp {Host: ([^\s\t]*)\s} $LB_request totalMatch host
regexp {[GET|POST] (/.*) HTTP} $LB_request totalMatch uri
unset totalMatch

HTTP::respond 302 Location [format "$::loginUI" [URI::encode "https://$host$uri"]] $::expired_cookies

when LB_FAILED {
log local0.debug "PolicyAgent: LB failed for: [LB::server]"
log local0.debug "PolicyAgent: LB status: [LB::status]"
Published Mar 18, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment