Module: Duo

Extended by:
Duo
Included in:
Devise::DuoSecurityController, Duo
Defined in:
lib/duo_web.rb

Overview

A Ruby implementation of the Duo WebSDK

Constant Summary collapse

DUO_PREFIX =
'TX'.freeze
APP_PREFIX =
'APP'.freeze
AUTH_PREFIX =
'AUTH'.freeze
DUO_EXPIRE =
300
APP_EXPIRE =
3600
IKEY_LEN =
20
SKEY_LEN =
40
AKEY_LEN =
40
ERR_USER =
'ERR|The username passed to sign_request() is invalid.'.freeze
ERR_IKEY =
'ERR|The Duo integration key passed to sign_request() is invalid.'.freeze
ERR_SKEY =
'ERR|The Duo secret key passed to sign_request() is invalid.'.freeze
ERR_AKEY =
"ERR|The application secret key passed to sign_request() must be at least #{Duo::AKEY_LEN} characters.".freeze

Instance Method Summary collapse

Instance Method Details

#sign_request(ikey, skey, akey, username) ⇒ Object

Sign a Duo 2FA request

Parameters:

  • ikey (String)

    The Duo IKEY

  • skey (String)

    The Duo SKEY

  • akey (String)

    The Duo AKEY

  • username (String)

    Username to authenticate as



29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/duo_web.rb', line 29

def sign_request(ikey, skey, akey, username)
  return Duo::ERR_USER if !username || username.empty?
  return Duo::ERR_USER if username.include? '|'
  return Duo::ERR_IKEY if !ikey || ikey.to_s.length != Duo::IKEY_LEN
  return Duo::ERR_SKEY if !skey || skey.to_s.length != Duo::SKEY_LEN
  return Duo::ERR_AKEY if !akey || akey.to_s.length < Duo::AKEY_LEN

  vals = [username, ikey]

  duo_sig = sign_vals(skey, vals, Duo::DUO_PREFIX, Duo::DUO_EXPIRE)
  app_sig = sign_vals(akey, vals, Duo::APP_PREFIX, Duo::APP_EXPIRE)

  return [duo_sig, app_sig].join(':')
end

#verify_response(ikey, skey, akey, sig_response) ⇒ Object

Verify a Duo 2FA request

Parameters:

  • ikey (String)

    The Duo IKEY

  • skey (String)

    The Duo SKEY

  • akey (String)

    The Duo AKEY

  • sig_response (String)

    Response from Duo service



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/duo_web.rb', line 49

def verify_response(ikey, skey, akey, sig_response)
  begin
    auth_sig, app_sig = sig_response.to_s.split(':')
    auth_user = parse_vals(skey, auth_sig, Duo::AUTH_PREFIX, ikey)
    app_user = parse_vals(akey, app_sig, Duo::APP_PREFIX, ikey)
  rescue
    return nil
  end

  return nil if auth_user != app_user

  return auth_user
end