Forum Discussion
jim_mcmurchie_1
Nimbostratus
May 07, 2014Making Google Auth active
I am working with an APM to build a secure VPN. I have established AD based authentication but want to add Google auth as a second factor. I have written the iRule but have found that it is not bei...
jim_mcmurchie_1
Nimbostratus
May 09, 2014The iRule event agent is Google_authN_token_verify and is as follows when ACCESS_POLICY_AGENT_EVENT { if { [ACCESS::policy agent_id] eq "ga_code_verify" } { log local0.info "entering ga_code_verify" Google Authenticator verification settings
lock the user out after x attempts for a period of x seconds
set static::lockout_attempts 3
set static::lockout_period 30
logon page session variable name for code attempt form field
set static::ga_code_form_field "ga_code_attempt"
key (shared secret) storage method: ldap, ad, or datagroup
set static::ga_key_storage "datagroup"
LDAP attribute for key if storing in LDAP (optional)
set static::ga_key_ldap_attr "google_auth_key"
Active Directory attribute for key if storing in AD (optional)
set static::ga_key_ad_attr "google_auth_key"
datagroup name if storing key in a datagroup (optional)
set static::ga_key_dg "google_auth_keys"
DO NOT MODIFY BELOW THIS LINE
set lockout table
set static::lockout_state_table "[virtual name]_lockout_status"
set variables from APM logon page
set username [ACCESS::session data get session.logon.last.username]
set ga_code_attempt [ACCESS::session data get session.logon.last.$static::ga_code_form_field]
retrieve key from specified storage
set ga_key ""
switch $static::ga_key_storage {
ldap {
set ga_key [ACCESS::session data get session.ldap.last.attr.$static::ga_key_ldap_attr]
}
ad {
set ga_key [ACCESS::session data get session.ad.last.attr.$static::ga_key_ad_attr]
}
datagroup {
set ga_key [class lookup $username $static::ga_key_dg]
}
}log local0.info "ga_code_attempt=${ga_code_attempt}, ga_key=${ga_key}"
increment the number of login attempts for the user
set prev_attempts [table incr -notouch -subtable $static::lockout_state_table $username]
table timeout -subtable $static::lockout_state_table $username $static::lockout_period
verification result value:
0 = successful
1 = failed
2 = no key found
3 = invalid key length
4 = user locked out
make sure that the user isn't locked out before calculating GA code
if { $prev_attempts <= $static::lockout_attempts } {
check that a valid key was retrieved, then proceed
if { [string length $ga_key] == 16 } {
begin - Base32 decode to binary
Base32 alphabet (see RFC 4648)
array set static::b32_alphabet {
A 0 B 1 C 2 D 3
E 4 F 5 G 6 H 7
I 8 J 9 K 10 L 11
M 12 N 13 O 14 P 15
Q 16 R 17 S 18 T 19
U 20 V 21 W 22 X 23
Y 24 Z 25 2 26 3 27
4 28 5 29 6 30 7 31
}
set ga_key [string toupper $ga_key]
set l [string length $ga_key]
set n 0
set j 0
set ga_key_bin ""
for { set i 0 } { $i < $l } { incr i } {
set n [expr $n << 5]
set n [expr $n + $static::b32_alphabet([string index $ga_key $i])]
set j [incr j 5]
if { $j >= 8 } {
set j [incr j -8]
append ga_key_bin [format %c [expr ($n & (0xFF << $j)) >> $j]]
}
}
end - Base32 decode to binary
begin - HMAC-SHA1 calculation of Google Auth token
set time [binary format W* [expr [clock seconds] / 30]]
set ipad ""
set opad ""
for { set j 0 } { $j < [string length $ga_key_bin] } { incr j } {
binary scan $ga_key_bin @${j}H2 k
set o [expr 0x$k ^ 0x5C]
set i [expr 0x$k ^ 0x36]
append ipad [format %c $i]
append opad [format %c $o]
}
while { $j < 64 } {
append ipad 6
append opad \\
incr j
}
binary scan [sha1 $opad[sha1 ${ipad}${time}]] H* token
end - HMAC-SHA1 calculation of Google Auth hex token
begin - extract code from Google Auth hex token
set offset [expr ([scan [string index $token end] %x] & 0x0F) << 1]
set ga_code [expr (0x[string range $token $offset [expr $offset + 7]] & 0x7FFFFFFF) % 1000000]
set ga_code [format %06d $ga_code]
end - extract code from Google Auth hex token
if { $ga_code_attempt eq $ga_code } {
code verification successful
set ga_result 0
} else {
code verification failed
set ga_result 1
}
} elseif { [string length $ga_key] > 0 } {
invalid key length, greater than 0, but not length not equal to 16 chars
set ga_result 3
} else {
could not retrieve user's key
set ga_result 2
}
} else {
user locked out due to too many failed attempts
set ga_result 4
}
set code verification result in session variable
ACCESS::session data set session.custom.ga_result $ga_result
}}
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects