2FA
@
Your Finger Tips
Agenda
- Who Am I?
- Why 2FA?
- How to achieve 2FA in Grails?
- Introduction to DUO Security
- DUO Workflow
- DUO Web SDKs
- Demo
- DUO Admin API
- Questions
Do you Know?
Do you Have?
Are You?
Security Factors
Do you Know?
password
answer to security question
stolen, weak, leaked, phished
Do you Have?
token
RSA
PIN
hardware token, manual entry
Are You?
the person you claim you are
biometrics (Apple touch)
retina scan
biometrics devices, availability
Why 2FA?
Combination of 2 such factors:
Password + token
Additional step in the process of fully authenticating a User
2FA can be annoying at times, however, only critical paths can be selectively chosen for 2FA. Example: during login or just before placing an order during check out
Spring Security
Spring Security REST
OAuth
pac4j
and more ...
Security in Grails
2FA
in
Grails
&
Spring Boot ?
https://duo.com/
https://duo.com/
- Cloud based access security provider
- 2nd Factor Auth as Push Notification to registered device is the key
- Also supports SMS, call (Landline) features
- Seamless SDK integration
- SDK available for plethora of languages
- Intuitive DUO administration with activity reporting
- Supports variety of platforms and VPN (Cisco, Citrix, many more ...)
Authentication without DUO
username
password
Login Success
Authentication with DUO
username
password
Login Success
IFRAME provided by DUO Web
1
2
1. Primary login success, call sign_request() provided by SDK.
2. Secondary login success, upon DUO Push/SMS, call verify_response()
Network Diagram*
DUO SDK & API
-
DUO Web SDK
-
Simple Java and JavaScript Client for web apps
-
Ad Hoc User Profile creation
-
Seamless Integration with Grails / Spring Boot
-
On the fly registration of users for DUO Push
-
-
DUO Admin API
-
Simple REST Api
-
Customized CRUD operations on User Profiles
-
Fine grain control of User profiles
-
Essential for app admins and User registrations
-
User profile creation in DUO can piggy back on app level registrations for User
-
DUO Web SDK
Prerequisites
- Setup account and application in DUO Administration
- Capture hostName, integrationKey & securityKey
- Add them as configurations (application.yml) or use config server or externalize secured configuration (ex: Vault)
- Install DUO app in device to test 2FA
DUO Web SDK
// build.gradle
dependencies {
// Duo Web SDK
compile 'com.duosecurity:DuoWeb:1.2-SNAPSHOT'
// DUO Client required for ADMIN API
compile 'com.duosecurity:duo-client:0.2.1'
}
// assets
//= require duo/Duo-Web-v2.min.js
DUO Web SDK
Spring Security Login Success Handler
grails.plugin.springsecurity.successHandler.defaultTargetUrl = '/duo/login'
Make sure above path is @Secured
DUO Login uses Duo Web SDK to get sig_request string
// DuoController.groovy
@Secured("isAuthenticated()")
def login() {
User user = springSecurityService.currentUser
DuoSignResponse duoDigResponse = duoService.signRequest(user.username)
[duoSigResponse: duoDigResponse]
}
// DuoService.groovy
import com.duosecurity.duoweb.DuoWeb
DuoSignResponse signRequest(String username) {
String sigRequest = DuoWeb.signRequest(
duoCredentials.ikey,
duoCredentials.skey,
duoCredentials.akey,
"${usernamePrefix}-$username"
)
return new DuoSignResponse(
duoCredentials.getHostname(),
sigRequest,
getPostCallbackUrl()
)
}
IFRAME uses hostname, sig_request & callback url
// /duo/login.gsp
<iframe
id="duo_iframe"
data-host="${duoSigResponse.hostname}"
data-sig-request="${duoSigResponse.sigRequest}"
data-post-action="${duoSigResponse.postCallbackUrl}"
width="100%"
height="420"
frameborder="0">
</iframe>
IFRAME attributes can be customized based on need and device
Push notification received,
approve login attempt from device
On successful authentication via DUO Push Notification or SMS, callback url is invoked by IFRAME.
In this case the callback is "/duo/verify" to verify the sig_response provided by DUO
// DuoService.groovy
import com.duosecurity.duoweb.DuoWeb
String verifyResponse(String sigResponse) {
String authUser = null
try {
authUser = DuoWeb.verifyResponse(
duoCredentials.ikey,
duoCredentials.skey,
duoCredentials.akey,
sigResponse
)
} catch (DuoWebException | NoSuchAlgorithmException | InvalidKeyException | IOException e) {
log.error("Exception from DUO", e)
}
return authUser
}
Based on the response of verify_response() from DUO, application can decide whether to redirect successfully or let user know that they are unauthorized to access
// DuoController.groovy
@Secured("isAuthenticated()")
def verify() {
// POST callback with request parameter sig_response
// which is a pipe delimited string.
String sigResponse = request.getParameter('sig_response')
String authUser = duoService.verifyResponse(sigResponse);
// Verify response returns back a valid String as authenticated User
// which signifies successful DUO authentication verification
// else, a null is returned for unsuccessful
// DUO authentication verification
if(authUser) {
redirect controller: 'sample'
} else {
render status: HttpStatus.UNAUTHORIZED,
text: "Failed DUO Authentication"
}
}
DEMO
&
Code Review
DUO Admin API
REST API to handle:
- Users
- Groups
- Admins
- Tokens
- Devices
- and more ....
https://duo.com/docs/adminapi
DUO Admin API
- Uses a different set of integration key, secret key as compared to DUO Web SDK
- DUO client library (duo-client) provides HTTP client to access Admin API
- Can be easily integrated as after() interceptor to CRUD operations in order to create/update/delete entities.
- Fine grain control of User administration as compared to DUO Web SDK
https://duo.com/docs/adminapi
DUO Admin API
https://duo.com/docs/adminapi
// application.yml
duo:
enabled: true
env: dev
host: api-17XXXaf.duosecurity.com
websdk:
ikey: DIQ4FQ6XXXXXXO27YYYYY
skey: PlP9ZxQXtwXECfV5CRBsRgBndg2yLXXX
admin:
ikey: DIQ4FC7ZZZZZZZ4SQ3BGD
skey: P8kMx5M6XXXXKmGTlj3GXPhHaXmvKYZZ
DUO Admin API
https://duo.com/docs/adminapi
// DuoAdminService.yml
// Create User
import com.duosecurity.client.Http
import com.squareup.okhttp.Response
// Create Request
Http request = new Http(
HttpMethod.POST.name(),
duoAdminCredentials.hostname,
"/admin/v1/users"
)
//Add request params
request.addParam("username", "jdoe")
request.addParam("realname", "John Doe")
request.addParam("email", "jdoe@example.com")
request.addParam("status", "active")
// Make sure signRequest is always called just before execute because
// params and headers should all be set before calling signRequest
request.signRequest(duoAdminCredentials.ikey, duoAdminCredentials.skey)
// Execute HTTP Request
Response result = request.executeHttpRequest()
return result.isSuccessful()
DUO Admin API
https://duo.com/docs/adminapi
Adds the user to DUO Admin and sets status to active
"Simplicity is the ultimate sophistication."
- Leonardo da Vinci
Alternatives
SecureKey
Telesign
Encap
SyferLock
http://bit.ly/2uK2XfF
Who uses DUO?
KAYAK
Safelite Auto Glass
University Of Michigan
Yelp
Federal and State Agencies
and many more ....
Resources
https://duo.com/docs/duoweb
https://duo.com/docs/adminapi
https://github.com/dmahapatro/grails-two-factor
Questions?
THANK YOU
2FA at your finger tips
By Dhiraj Mahapatro
2FA at your finger tips
- 1,837