soteria 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +77 -0
- data/Rakefile +5 -0
- data/bin/bundler +17 -0
- data/bin/console +17 -0
- data/bin/htmldiff +17 -0
- data/bin/ldiff +17 -0
- data/bin/nokogiri +17 -0
- data/bin/rackup +17 -0
- data/bin/rake +17 -0
- data/bin/rspec +17 -0
- data/bin/setup +17 -0
- data/bin/socksify_ruby +17 -0
- data/lib/soteria.rb +10 -0
- data/lib/soteria/client.rb +326 -0
- data/lib/soteria/credential.rb +154 -0
- data/lib/soteria/credential_types.rb +13 -0
- data/lib/soteria/push.rb +141 -0
- data/lib/soteria/sms.rb +81 -0
- data/lib/soteria/user.rb +409 -0
- data/lib/soteria/utilities.rb +45 -0
- data/lib/soteria/version.rb +4 -0
- data/soteria.gemspec +26 -0
- data/spec/credential_spec.rb +121 -0
- data/spec/fixtures/credential/authenticate_credentials_response.xml +13 -0
- data/spec/fixtures/credential/credential_fail.xml +11 -0
- data/spec/fixtures/credential/credential_success.xml +12 -0
- data/spec/fixtures/credential/get_cred_info_response.xml +40 -0
- data/spec/fixtures/credential/get_server_time_response.xml +11 -0
- data/spec/fixtures/credential/register_sms_response.xml +12 -0
- data/spec/fixtures/push/authenticate_with_push_error.xml +9 -0
- data/spec/fixtures/push/authenticate_with_push_response.xml +14 -0
- data/spec/fixtures/sms/check_otp_success_response.xml +13 -0
- data/spec/fixtures/sms/send_sms_success_response.xml +10 -0
- data/spec/fixtures/user/add_credential_response.xml +9 -0
- data/spec/fixtures/user/clear_temp_password_response.xml +10 -0
- data/spec/fixtures/user/clear_user_pin_response.xml +10 -0
- data/spec/fixtures/user/create_user_response.xml +9 -0
- data/spec/fixtures/user/delete_user_response.xml +10 -0
- data/spec/fixtures/user/get_temp_pass_attr_response.xml +14 -0
- data/spec/fixtures/user/remove_credential_response.xml +10 -0
- data/spec/fixtures/user/set_temp_pass_attr_response.xml +10 -0
- data/spec/fixtures/user/set_temp_pass_response.xml +11 -0
- data/spec/fixtures/user/update_credential_response.xml +10 -0
- data/spec/fixtures/user/update_user_response.xml +10 -0
- data/spec/fixtures/wsdl/vipuserservices-1.7.xsd +1015 -0
- data/spec/fixtures/wsdl/vipuserservices-auth-1.7.wsdl +155 -0
- data/spec/fixtures/wsdl/vipuserservices-mgmt-1.7.wsdl +246 -0
- data/spec/fixtures/wsdl/vipuserservices-query-1.7.wsdl +114 -0
- data/spec/push_spec.rb +148 -0
- data/spec/sms_spec.rb +84 -0
- data/spec/soteria_spec.rb +8 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/user_spec.rb +245 -0
- metadata +206 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
module Soteria
|
2
|
+
|
3
|
+
class Credential
|
4
|
+
|
5
|
+
|
6
|
+
def get_return_hash(response_hash)
|
7
|
+
success = response_hash[:status] == '0000'
|
8
|
+
|
9
|
+
{
|
10
|
+
success: success,
|
11
|
+
message: response_hash[:status_message],
|
12
|
+
id: response_hash[:request_id],
|
13
|
+
auth_id: response_hash[:authn_id],
|
14
|
+
detail: response_hash[:detail_message]
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# Authenticate a user with a credential. A credential includes a physical token, the desktop VIP credential app or
|
20
|
+
# the mobile VIP credential app. Users must link their credential id to their user id for this authentication to work.
|
21
|
+
#
|
22
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP authentication WSDL.
|
23
|
+
# @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec db.
|
24
|
+
# @param [String] credential_code The code from the users credential that was entered into the website.
|
25
|
+
# @return [Hash] A hash with information on if the authentication was successful.
|
26
|
+
def authenticate_user_credential(client, user_id, credential_code)
|
27
|
+
result = client.call(:authenticate_user,
|
28
|
+
message: {
|
29
|
+
'vip:requestId': Utilities.get_request_id('authenticate_user_credential'),
|
30
|
+
'vip:userId': user_id,
|
31
|
+
'vip:otpAuthData':
|
32
|
+
{
|
33
|
+
'vip:otp': credential_code
|
34
|
+
}
|
35
|
+
})
|
36
|
+
|
37
|
+
get_return_hash(result.body[:authenticate_user_response])
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# Create the body for the authenticate credentials request.
|
43
|
+
#
|
44
|
+
# @param [Integer] otp The One Time Password to check if valid.
|
45
|
+
# @param [Array] credentials An array of hashes, with between 1 and 5 credentials. Each hash should contain 2 values :id - the id of the credential and :type - the type of the credential.
|
46
|
+
# @return [Hash] A hash representing the request body for the authenticate credentials request.
|
47
|
+
def get_auth_body(otp, credentials)
|
48
|
+
|
49
|
+
credential_array = []
|
50
|
+
|
51
|
+
credentials.each do |credential|
|
52
|
+
credential_array.push({'vip:credentialId': credential[:id], 'vip:credentialType': credential[:type]})
|
53
|
+
end
|
54
|
+
|
55
|
+
{
|
56
|
+
'vip:requestId': Utilities.get_request_id('authenticate_credentials'),
|
57
|
+
'vip:credentials': credential_array,
|
58
|
+
'vip:otpAuthData': {
|
59
|
+
'vip:otp': otp
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# Check if a otp is valid for a given credential.
|
67
|
+
#
|
68
|
+
# @param [Integer] otp The One Time Password to check if valid.
|
69
|
+
# @param [Array] credentials An array of hashes, with between 1 and 5 credentials. Each hash should contain 2 values :id - the id of the credential and :type - the type of the credential.
|
70
|
+
# @see CredentialTypes
|
71
|
+
# @return [Hash] A hash with all information about if the otp was successful
|
72
|
+
def authenticate_credentials(client, otp, credentials)
|
73
|
+
result = client.call(:authenticate_credentials, message: get_auth_body(otp, credentials))
|
74
|
+
get_return_hash(result.body[:authenticate_credentials_response])
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
# Register a SMS credential to the VIP Account. This must be done before you can add a SMS credential to a user.
|
79
|
+
#
|
80
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
81
|
+
# @param [Object] phone_number The phone number to register.
|
82
|
+
def register_sms(client, phone_number)
|
83
|
+
result = client.call(:register, message: {
|
84
|
+
'vip:requestId': Utilities.get_request_id('register_credential'),
|
85
|
+
'vip:smsDeliveryInfo': {
|
86
|
+
'vip:phoneNumber': phone_number
|
87
|
+
}
|
88
|
+
} )
|
89
|
+
|
90
|
+
get_return_hash(result.body[:register_response])
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
# Use getCredentialInfo to get the credential that was last bound to the user, When the credential was last authenticated and
|
95
|
+
# the friendly name for the credential.
|
96
|
+
#
|
97
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
|
98
|
+
# @param [String] credential_id The unique ID for the credential.
|
99
|
+
# @param [String] credential_type The type of the credential.
|
100
|
+
# @param [Boolean] include_push If this flag is present and set to be true, the response contains all the push attributes in the field pushAttributes.
|
101
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes. Also contains :credential which is a hash with info about the credential.
|
102
|
+
def get_credential_info(client, credential_id, credential_type, include_push)
|
103
|
+
message = {
|
104
|
+
'vip:requestId': Utilities.get_request_id('get_credential_info'),
|
105
|
+
'vip:credentialId': credential_id,
|
106
|
+
'vip:credentialType': credential_type
|
107
|
+
}
|
108
|
+
|
109
|
+
unless include_push == nil
|
110
|
+
message[:'vip:includePushAttributes'] = include_push
|
111
|
+
end
|
112
|
+
|
113
|
+
response = client.call(:get_credential_info, message: message)
|
114
|
+
response_hash = response.body[:get_credential_info_response]
|
115
|
+
|
116
|
+
ret = get_return_hash(response_hash)
|
117
|
+
|
118
|
+
# get the credential info
|
119
|
+
credential = {
|
120
|
+
id: response_hash[:credential_id],
|
121
|
+
type: response_hash[:credential_type],
|
122
|
+
enabled: response_hash[:credential_status] == 'ENABLED'
|
123
|
+
}
|
124
|
+
|
125
|
+
# add the bindings if they exist
|
126
|
+
unless response_hash[:num_bindings] == '0'
|
127
|
+
credential[:user_binding] = response_hash[:user_binding_detail]
|
128
|
+
end
|
129
|
+
|
130
|
+
ret[:credential] = credential
|
131
|
+
|
132
|
+
ret
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
# Use getServerTime to obtain the current server time.
|
137
|
+
#
|
138
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
|
139
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes. Also contains :time which is current server time.
|
140
|
+
def get_server_time(client)
|
141
|
+
response = client.call(:get_server_time, message: {'vip:requestId': Utilities.get_request_id('get_server_time')})
|
142
|
+
response_body = response.body[:get_server_time_response]
|
143
|
+
ret = get_return_hash(response_body)
|
144
|
+
|
145
|
+
unless response_body[:timestamp] == nil
|
146
|
+
ret[:time] = response_body[:timestamp]
|
147
|
+
end
|
148
|
+
|
149
|
+
ret
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
data/lib/soteria/push.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
require_relative 'utilities'
|
2
|
+
module Soteria
|
3
|
+
|
4
|
+
class Push
|
5
|
+
|
6
|
+
|
7
|
+
# Creates the body for a send push request.
|
8
|
+
#
|
9
|
+
# @param [String] user_id The id of the user to send the push to
|
10
|
+
# @param [Hash] options
|
11
|
+
# @return [Hash] A hash representing the body of the soap request to send a push notification.
|
12
|
+
def get_push_request_body(user_id, options)
|
13
|
+
|
14
|
+
# add in required values
|
15
|
+
message = {
|
16
|
+
'vip:requestId': Utilities.get_request_id('send_push_request'),
|
17
|
+
'vip:userId': user_id,
|
18
|
+
}
|
19
|
+
|
20
|
+
# no extra options so set the push auth data to nothing
|
21
|
+
# and return the body
|
22
|
+
if options == nil
|
23
|
+
message[:'vip:pushAuthData'] = ''
|
24
|
+
return message
|
25
|
+
end
|
26
|
+
|
27
|
+
#check if the user passed a pin, if so add it
|
28
|
+
if options.key?(:pin)
|
29
|
+
message[:'vip:pin'] = options[:pin]
|
30
|
+
end
|
31
|
+
|
32
|
+
# check for all push auth data options and add them
|
33
|
+
if options.key?(:title) || options.key?(:message) || options.key?(:profile) || options.key?(:time_out)
|
34
|
+
inner = []
|
35
|
+
if options.key?(:title)
|
36
|
+
inner.push({'vip:Key': 'display.message.title', 'vip:Value': options[:title]})
|
37
|
+
end
|
38
|
+
if options.key?(:message)
|
39
|
+
inner.push({'vip:Key': 'display.message.text', 'vip:Value': options[:message]})
|
40
|
+
end
|
41
|
+
if options.key?(:profile)
|
42
|
+
inner.push({'vip:Key': 'display.message.profile', 'vip:Value': options[:profile]})
|
43
|
+
end
|
44
|
+
|
45
|
+
# Add the options to the push auth data
|
46
|
+
if options.key?(:time_out)
|
47
|
+
message[:'vip:pushAuthData'] = {
|
48
|
+
'vip:displayParameters': inner,
|
49
|
+
'vip:requestParameters':
|
50
|
+
{
|
51
|
+
'vip:Key': 'request.timeout',
|
52
|
+
'vip:Value': options[:time_out]
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
else
|
57
|
+
message[:'vip:pushAuthData'] = {'vip:displayParameters': inner}
|
58
|
+
end
|
59
|
+
|
60
|
+
else
|
61
|
+
# dont add any push auth data
|
62
|
+
message[:'vip:pushAuthData'] = ''
|
63
|
+
end
|
64
|
+
|
65
|
+
# if options.key?(:level)
|
66
|
+
# message['authContext'] = {'params': {'Key': 'authLevel.level', 'Value': options[:level]}}
|
67
|
+
# end
|
68
|
+
|
69
|
+
message
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# Send a push notification to the specified user for authentication.
|
74
|
+
#
|
75
|
+
# @param [Savon::Client] client A Savon client object to make the call with.
|
76
|
+
# @see Savon::Client
|
77
|
+
# @param [String] user_id The id of the user to send the push to
|
78
|
+
# @param [Hash] options
|
79
|
+
def send_push(client, user_id, options)
|
80
|
+
|
81
|
+
# get the body of the request
|
82
|
+
request_body = get_push_request_body(user_id, options)
|
83
|
+
push_res = client.call(:authenticate_user_with_push, message: request_body)
|
84
|
+
result_hash = push_res.body[:authenticate_user_with_push_response]
|
85
|
+
|
86
|
+
# 6040 is the status code for a push being sent, any other code the push was not sent
|
87
|
+
success = result_hash[:status] == '6040'
|
88
|
+
|
89
|
+
{
|
90
|
+
success: success,
|
91
|
+
id: result_hash[:request_id],
|
92
|
+
transaction_id: result_hash[:transaction_id],
|
93
|
+
message: result_hash[:status_message]
|
94
|
+
}
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
# Polls for the status of the push notification. This is necessary because VIP does not have push support.
|
100
|
+
# This will poll until the response is no longer push in progress, then it will return a hash with the results.
|
101
|
+
#
|
102
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
|
103
|
+
# @param [String] transaction_id The id of the push transaction. id is in the hash returned from the send_push call
|
104
|
+
# @param [Int] interval An integer value in seconds that is the interval between polling VIP Services for a push response.
|
105
|
+
# @param [Int] time_out An integer value in seconds that is the timeout for polling. This should match the timeout that was set for the push message.
|
106
|
+
# @return [Hash] A hash with information on if the authentication was successful.
|
107
|
+
def poll_for_response(client, transaction_id, interval, time_out)
|
108
|
+
|
109
|
+
1.upto(time_out/interval) do
|
110
|
+
|
111
|
+
response = client.call(:poll_push_status,
|
112
|
+
message: {
|
113
|
+
'vip:requestId': Utilities.get_request_id("poll_push_status"),
|
114
|
+
'vip:transactionId': transaction_id
|
115
|
+
})
|
116
|
+
|
117
|
+
# The status of the push is called transaciton status
|
118
|
+
transaction_status = response.body[:poll_push_status_response][:transaction_status]
|
119
|
+
call_status = response.body[:poll_push_status_response]
|
120
|
+
|
121
|
+
# 7001 is in progress so we are waiting for that to change
|
122
|
+
if transaction_status[:status] != '7001'
|
123
|
+
|
124
|
+
success = transaction_status[:status] == '7000'
|
125
|
+
return {
|
126
|
+
success: success,
|
127
|
+
message: transaction_status[:status_message],
|
128
|
+
id: call_status[:request_id]
|
129
|
+
}
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
sleep interval
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
data/lib/soteria/sms.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
module Soteria
|
2
|
+
|
3
|
+
class SMS
|
4
|
+
|
5
|
+
|
6
|
+
# Creates the body for a send SMS otp request.
|
7
|
+
#
|
8
|
+
# @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec database.
|
9
|
+
# @param [Int] phone_number The phone number that the sms code should be sent to.
|
10
|
+
# @return [Hash] A hash with all information about if the otp was successful.
|
11
|
+
def create_send_sms_body(user_id, phone_number)
|
12
|
+
{
|
13
|
+
'vip:requestId': Utilities.get_request_id('send_sms_otp'),
|
14
|
+
'vip:userId': user_id,
|
15
|
+
'vip:smsDeliveryInfo':
|
16
|
+
{
|
17
|
+
'vip:phoneNumber': phone_number
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# Send a sms One Time Password to a user.
|
24
|
+
#
|
25
|
+
# @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec database.
|
26
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
27
|
+
# @param [Int] phone_number The phone number that the sms code should be sent to.
|
28
|
+
# @return [Hash] A hash with all the appropriate information about the status of the SMS.
|
29
|
+
def send_sms(client, user_id, phone_number)
|
30
|
+
sms_res = client.call(:send_otp, message: create_send_sms_body(user_id, phone_number))
|
31
|
+
result_hash = sms_res.body[:send_otp_response]
|
32
|
+
success = result_hash[:status] == '0000'
|
33
|
+
|
34
|
+
{
|
35
|
+
success: success,
|
36
|
+
id: result_hash[:request_id],
|
37
|
+
message: result_hash[:status_message]
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# Creates the body for a check otp request.
|
43
|
+
#
|
44
|
+
# @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec db.
|
45
|
+
# @param [Object] otp The otp that was sent to the user via sms or voice
|
46
|
+
# @return [Hash] A hash representing the body of the soap request to check if an otp is valid.
|
47
|
+
def create_check_otp_body(user_id, otp)
|
48
|
+
{
|
49
|
+
'vip:requestId': Utilities.get_request_id('check_sms_otp'),
|
50
|
+
'vip:userId': user_id,
|
51
|
+
'vip:otpAuthData':
|
52
|
+
{
|
53
|
+
'vip:otp': otp
|
54
|
+
}
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Check if the otp that a user entered is valid or not.
|
60
|
+
#
|
61
|
+
# @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec db.
|
62
|
+
# @param [Object] otp The otp that was sent to the user via sms or voice
|
63
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP authentication WSDL.
|
64
|
+
# @return [Hash] A hash with all information about if the otp was successful
|
65
|
+
def check_otp(client, user_id, otp)
|
66
|
+
check_otp_response = client.call(:check_otp, message: create_check_otp_body(user_id, otp))
|
67
|
+
result_hash = check_otp_response.body[:check_otp_response]
|
68
|
+
|
69
|
+
success = result_hash[:status] == '0000'
|
70
|
+
|
71
|
+
{
|
72
|
+
success: success,
|
73
|
+
id: result_hash[:request_id],
|
74
|
+
message: result_hash[:status_message]
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/lib/soteria/user.rb
ADDED
@@ -0,0 +1,409 @@
|
|
1
|
+
module Soteria
|
2
|
+
|
3
|
+
class User
|
4
|
+
|
5
|
+
|
6
|
+
# Add a new user to the list of users in Symantec VIP database.
|
7
|
+
#
|
8
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
9
|
+
# @param [String] user_id Id of the user to create.
|
10
|
+
# @param [String] pin an optional value that is a pin for the user. The PIN may be 4 to 128 international characters in length, depending on restrictions of the PIN policy.
|
11
|
+
# @return [Hash] A hash that contains: :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
12
|
+
def create(client, user_id, pin)
|
13
|
+
message = {
|
14
|
+
'vip:requestId': Utilities.get_request_id('create_user'),
|
15
|
+
'vip:userId': user_id
|
16
|
+
}
|
17
|
+
|
18
|
+
unless pin.nil?
|
19
|
+
message['vip:pin'] = pin
|
20
|
+
end
|
21
|
+
|
22
|
+
response = client.call(:create_user, message: message)
|
23
|
+
|
24
|
+
get_return_hash(response.body[:create_user_response])
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# Delete a user from the database of Symantec VIP users.
|
29
|
+
#
|
30
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
31
|
+
# @param [String] user_id Id of the user to delete.
|
32
|
+
# @return [Hash] A hash that contains: :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
33
|
+
def delete(client, user_id)
|
34
|
+
response = client.call(:delete_user,
|
35
|
+
message: {
|
36
|
+
'vip:requestId': Utilities.get_request_id('delete_user'),
|
37
|
+
'vip:userId': user_id
|
38
|
+
})
|
39
|
+
|
40
|
+
get_return_hash(response.body[:delete_user_response])
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Creates the body for a add credential request.
|
45
|
+
#
|
46
|
+
# @param [String] user_id Id of the user to add a credential to.
|
47
|
+
# @param [String] credential_id
|
48
|
+
# @param [String] credential_type must be one of the keys to the credential types from the Utilities class.
|
49
|
+
# @see Utilities::CREDENTIAL_TYPES
|
50
|
+
# @param [Hash] options A hash that can contain the following. :name adds a friendly name to the credential added to vip, :otp sends a otp from the credential with the request to verify that the user actually has possession of the credential
|
51
|
+
# @return [Hash] A hash representing the body of the soap request to add a credential.
|
52
|
+
def get_add_credential_message(user_id, credential_id, credential_type, options)
|
53
|
+
message = {
|
54
|
+
'vip:requestId': Utilities.get_request_id('add_credential'),
|
55
|
+
'vip:userId': user_id
|
56
|
+
}
|
57
|
+
|
58
|
+
credential_detail = {
|
59
|
+
'vip:credentialId': credential_id,
|
60
|
+
'vip:credentialType': credential_type
|
61
|
+
}
|
62
|
+
|
63
|
+
unless options == nil
|
64
|
+
if options.key?(:name)
|
65
|
+
credential_detail[:'vip:friendlyName'] = options[:name]
|
66
|
+
end
|
67
|
+
|
68
|
+
if options.key?(:otp)
|
69
|
+
message[:'vip:otpAuthData'] = {
|
70
|
+
'vip:otp': options[:otp]
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
message[:'vip:credentialDetail'] = credential_detail
|
76
|
+
|
77
|
+
message
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# Add a credential to an existing user in the Symantec VIP database.
|
82
|
+
#
|
83
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
84
|
+
# @param [String] user_id Id of the user to add a credential to.
|
85
|
+
# @param [String] credential_id Unique identifier of the credential.
|
86
|
+
# @param [String] credential_type must be one of the keys to the credential types from the Utilities class.
|
87
|
+
# @see Utilities::CREDENTIAL_TYPES
|
88
|
+
# @param [Hash] options A hash that can contain the following. :name adds a friendly name to the credential added to vip, :otp sends a otp from the credential with the request to verify that the user actually has possession of the credential
|
89
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
90
|
+
def add_credential(client, user_id, credential_id, credential_type, options)
|
91
|
+
response = client.call(:add_credential, message: get_add_credential_message(user_id, credential_id, credential_type, options))
|
92
|
+
get_return_hash(response.body[:add_credential_response])
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
# Remove a credential from a given user. If the Device deletion policy for Remembered Devices is set to Admin Only,
|
97
|
+
# credentials can only be removed through VIP Manager. The removeCredential API will return the error 6010: This
|
98
|
+
# account is not authorized to perform the requested operation
|
99
|
+
#
|
100
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
101
|
+
# @param [String] user_id Id of the user to remove a credential from.
|
102
|
+
# @param [String] credential_id Unique identifier of the credential.
|
103
|
+
# @param [String] credential_type must be one of the keys to the credential types from the Utilities class.
|
104
|
+
# @see Utilities::CREDENTIAL_TYPES
|
105
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
106
|
+
def remove_credential(client, user_id, credential_id, credential_type)
|
107
|
+
response = client.call(:remove_credential, message: {
|
108
|
+
'vip:requestId': Utilities.get_request_id('remove_credential'),
|
109
|
+
'vip:userId': user_id,
|
110
|
+
'vip:credentialId': credential_id,
|
111
|
+
'vip:credentialType': credential_type
|
112
|
+
})
|
113
|
+
|
114
|
+
get_return_hash(response.body[:remove_credential_response])
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
# Updates the friendly name of a users credential.
|
119
|
+
#
|
120
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
121
|
+
# @param [String] user_id Id of the user to remove a credential from.
|
122
|
+
# @param [String] credential_id Unique identifier of the credential.
|
123
|
+
# @param [String] credential_type must be one of the keys to the credential types from the Utilities class.
|
124
|
+
# @see Utilities::CREDENTIAL_TYPES
|
125
|
+
# @param [Object] name A user-defined name to identify the credential.
|
126
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
127
|
+
def update_credential(client, user_id, credential_id, credential_type, name)
|
128
|
+
response = client.call(:update_credential, message: {
|
129
|
+
'vip:requestId': Utilities.get_request_id('update_credential'),
|
130
|
+
'vip:userId': user_id,
|
131
|
+
'vip:credentialId': credential_id,
|
132
|
+
'vip:credentialType': credential_type,
|
133
|
+
'vip:friendlyName': name
|
134
|
+
})
|
135
|
+
|
136
|
+
get_return_hash(response.body[:update_credential_response])
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# Get all the credentials that have been last bound to a user or the last authentication, as well as the friendly
|
141
|
+
# name for the user's credential.
|
142
|
+
#
|
143
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
|
144
|
+
# @param [String] user_id Id of the user to get information about.
|
145
|
+
# @param [Boolean] include_push If the users push details should be returned.
|
146
|
+
# @return [Hash] A hash that contains; :credentials a array of credentials available, :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
147
|
+
def get_user_info(client, user_id, include_push)
|
148
|
+
response = client.call(:get_user_info, message: {
|
149
|
+
'vip:requestId': Utilities.get_request_id('get_user_info'),
|
150
|
+
'vip:userId': user_id,
|
151
|
+
'vip:includePushAttributes': include_push
|
152
|
+
})
|
153
|
+
|
154
|
+
response_hash = response.body[:get_user_info_response]
|
155
|
+
|
156
|
+
credentials = []
|
157
|
+
|
158
|
+
if response_hash[:num_bindings] == nil || response_hash[:num_bindings] == '0'
|
159
|
+
credentials = nil
|
160
|
+
|
161
|
+
else
|
162
|
+
response_hash[:credential_binding_detail].each do |credential|
|
163
|
+
|
164
|
+
bind_detail = credential[:binding_detail]
|
165
|
+
|
166
|
+
if credential[:credential_type] == 'STANDARD_OTP'
|
167
|
+
push_attrs = credential[:push_attributes]
|
168
|
+
credentials.push({
|
169
|
+
type: 'STANDARD_OTP',
|
170
|
+
enabled: response_hash[:credential_status] == 'ENABLED' && bind_detail[:bind_status] == 'ENABLED',
|
171
|
+
friendly_name: bind_detail[:friendly_name],
|
172
|
+
push: push_check(push_attrs),
|
173
|
+
credential_id: credential[:credential_id]
|
174
|
+
})
|
175
|
+
|
176
|
+
elsif credential[:credential_type] == 'SMS_OTP'
|
177
|
+
credentials.push({
|
178
|
+
type: 'SMS_OTP',
|
179
|
+
enabled: response_hash[:credential_status] == 'ENABLED' && bind_detail[:bind_status] == 'ENABLED',
|
180
|
+
friendly_name: bind_detail[:friendly_name],
|
181
|
+
push: false,
|
182
|
+
credential_id: credential[:credential_id]
|
183
|
+
})
|
184
|
+
elsif credential[:credential_type] == 'VOICE_OTP'
|
185
|
+
credentials.push({
|
186
|
+
type: 'VOICE_OTP',
|
187
|
+
enabled: response_hash[:credential_status] == 'ENABLED' && bind_detail[:bind_status] == 'ENABLED',
|
188
|
+
friendly_name: bind_detail[:friendly_name],
|
189
|
+
push: false,
|
190
|
+
credential_id: credential[:credential_id]
|
191
|
+
})
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
ret = get_return_hash(response_hash)
|
199
|
+
ret[:credentials] = credentials
|
200
|
+
ret
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
# Use updateUser to update information about a user in VIP User Services.
|
205
|
+
#
|
206
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
207
|
+
# @param [String] user_id The unique ID for the user.
|
208
|
+
# @param [Object] options
|
209
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
210
|
+
def update_user(client, user_id, options)
|
211
|
+
message = {
|
212
|
+
'vip:requestId': Utilities.get_request_id('update_user'),
|
213
|
+
'vip:userId': user_id
|
214
|
+
}
|
215
|
+
|
216
|
+
unless options == nil
|
217
|
+
if options.key?(:newId)
|
218
|
+
message[:'vip:newUserId'] = options[:newId]
|
219
|
+
end
|
220
|
+
|
221
|
+
if options.key?(:status)
|
222
|
+
message[:'vip:newUserStatus'] = options[:status]
|
223
|
+
end
|
224
|
+
|
225
|
+
if options.key?(:oldPin)
|
226
|
+
message[:'vip:oldPin'] = options[:oldPin]
|
227
|
+
end
|
228
|
+
|
229
|
+
if options.key?(:newPin)
|
230
|
+
message[:'vip:newPin'] = options[:newPin]
|
231
|
+
end
|
232
|
+
|
233
|
+
if options.key?(:pinReset)
|
234
|
+
message[:'vip:forcePinReset'] = options[:pinReset]
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
response = client.call(:update_user, message: message)
|
240
|
+
get_return_hash(response.body[:update_user_response])
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
# Use clearUserPin to remove an assigned PIN from a user.
|
245
|
+
#
|
246
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
247
|
+
# @param [String] user_id The unique ID for the user.
|
248
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
249
|
+
def clear_user_pin(client, user_id)
|
250
|
+
response = client.call(:clear_user_pin, message: {
|
251
|
+
'vip:requestId': Utilities.get_request_id('clear_pin'),
|
252
|
+
'vip:userId': user_id
|
253
|
+
})
|
254
|
+
|
255
|
+
get_return_hash(response.body[:clear_user_pin_response])
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
# Use setTemporaryPasswordAttributes to change the expiration date for a temporary security code you previously set.
|
260
|
+
#
|
261
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
262
|
+
# @param [String] user_id The unique ID for the user.
|
263
|
+
# @param [Object] options
|
264
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
265
|
+
def set_temp_pass_attr(client, user_id, options)
|
266
|
+
message = {
|
267
|
+
'vip:requestId': Utilities.get_request_id('set_temp_pass_attr'),
|
268
|
+
'vip:userId': user_id
|
269
|
+
}
|
270
|
+
|
271
|
+
unless options == nil
|
272
|
+
inner = {}
|
273
|
+
if options.key?(:oneTime)
|
274
|
+
inner[:'vip:oneTimeUseOnly'] = options[:oneTime]
|
275
|
+
end
|
276
|
+
|
277
|
+
if options.key?(:expireTime)
|
278
|
+
inner[:'vip:expirationTime'] = options[:expireTime]
|
279
|
+
end
|
280
|
+
|
281
|
+
message[:'vip:temporaryPasswordAttributes'] = inner
|
282
|
+
end
|
283
|
+
|
284
|
+
response = client.call(:set_temporary_password_attributes, message: message)
|
285
|
+
get_return_hash(response.body[:set_temporary_password_attributes_response])
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
# Use getTemporaryPasswordAttributes to poll VIP User Services every three to five seconds to check the status of a
|
290
|
+
# push notification. The push notification is validated against the notification’s unique transaction ID.
|
291
|
+
#
|
292
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
|
293
|
+
# @param [String] user_id The unique ID for the user.
|
294
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
295
|
+
def get_temp_pass_attr(client, user_id)
|
296
|
+
response = client.call(:get_temporary_password_attributes, message: {
|
297
|
+
'vip:requestId': Utilities.get_request_id('get_temp_pass_attr'),
|
298
|
+
'vip:userId': user_id
|
299
|
+
})
|
300
|
+
response_hash = response.body[:get_temporary_password_attributes_response]
|
301
|
+
|
302
|
+
ret = get_return_hash(response_hash)
|
303
|
+
|
304
|
+
unless response_hash[:temp_pwd_attributes] == nil
|
305
|
+
ret[:oneTime] = response_hash[:temp_pwd_attributes][:one_time_use_only]
|
306
|
+
ret[:expiration] = response_hash[:temp_pwd_attributes][:expiration_time]
|
307
|
+
end
|
308
|
+
|
309
|
+
ret
|
310
|
+
end
|
311
|
+
|
312
|
+
|
313
|
+
# Use setTemporaryPassword to set a temporary security code for a user. You can optionally set an
|
314
|
+
# expiration date for the security code, or set it for one-time use only. The request requires the user ID and
|
315
|
+
# optionally, the temporary security code string. If you do not provide a security code, VIP User Services generates
|
316
|
+
# one for you.
|
317
|
+
#
|
318
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
319
|
+
# @param [String] user_id The unique ID for the user.
|
320
|
+
# @param [Int] phone The phone or mobile device number to which the VIP User Service should deliver the security code.
|
321
|
+
# @param [Hash] options
|
322
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
323
|
+
def set_temp_password(client, user_id, phone, options)
|
324
|
+
message = {
|
325
|
+
'vip:requestId': Utilities.get_request_id('set_temp_pass'),
|
326
|
+
'vip:userId': user_id
|
327
|
+
}
|
328
|
+
|
329
|
+
phone_options = {'vip:phoneNumber': phone}
|
330
|
+
|
331
|
+
unless options == nil
|
332
|
+
if options.key?(:otp)
|
333
|
+
message[:'vip:temporaryPassword'] = options[:otp]
|
334
|
+
end
|
335
|
+
|
336
|
+
if options.key?(:expireTime)
|
337
|
+
message[:'vip:expirationTime'] = options[:expireTime]
|
338
|
+
end
|
339
|
+
|
340
|
+
if options.key?(:oneTime)
|
341
|
+
message[:'vip:temporaryPasswordAttributes'] = { 'vip:oneTimeUseOnly': options[:oneTime] }
|
342
|
+
end
|
343
|
+
|
344
|
+
if options.key?(:from)
|
345
|
+
phone_options[:'vip:expirationTime'] = options[:from]
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
message[:'vip:smsDeliveryInfo'] = phone_options
|
350
|
+
|
351
|
+
response = client.call(:set_temporary_password, message: message)
|
352
|
+
|
353
|
+
ret = get_return_hash(response.body[:set_temporary_password_response])
|
354
|
+
ret[:password] = response.body[:set_temporary_password_response][:temporary_password]
|
355
|
+
|
356
|
+
ret
|
357
|
+
end
|
358
|
+
|
359
|
+
|
360
|
+
# Use clearTemporaryPassword to add users to VIP User Services.to remove a temporary security code from a user. If the
|
361
|
+
# user attempts to use a temporary security that has been cleared, VIP User Services returns an error stating the
|
362
|
+
# security code is not set. If the user validates a security code using a valid credential, any temporary security
|
363
|
+
# code that is set for that user is automatically cleared.
|
364
|
+
#
|
365
|
+
# @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
|
366
|
+
# @param [String] user_id The unique ID for the user.
|
367
|
+
# @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
|
368
|
+
def clear_temp_pass(client, user_id)
|
369
|
+
message = {
|
370
|
+
'vip:requestId': Utilities.get_request_id('clear_temp_pass'),
|
371
|
+
'vip:userId': user_id
|
372
|
+
}
|
373
|
+
|
374
|
+
response = client.call(:clear_temporary_password, message: message)
|
375
|
+
get_return_hash(response.body[:clear_temporary_password_response])
|
376
|
+
end
|
377
|
+
|
378
|
+
|
379
|
+
# Helper function to loop through an array of hashes with key value pairs and return if push is enabled.
|
380
|
+
#
|
381
|
+
# @param [Array] attrs A array of hash attributes
|
382
|
+
# @return [Boolean] If push is enabled for the give attributes
|
383
|
+
def push_check(attrs)
|
384
|
+
attrs.each do |a|
|
385
|
+
if a[:key] == 'PUSH_ENABLED'
|
386
|
+
return a[:value]
|
387
|
+
end
|
388
|
+
end
|
389
|
+
false
|
390
|
+
end
|
391
|
+
|
392
|
+
|
393
|
+
# Helper function to create the hash to return. All user calls have the same return values.
|
394
|
+
#
|
395
|
+
# @param [Hash] response_hash
|
396
|
+
# @return [Hash] A hash with the appropriate values. Included are: :success - a boolean if the operation was successful,
|
397
|
+
def get_return_hash(response_hash)
|
398
|
+
success = response_hash[:status] == '0000'
|
399
|
+
|
400
|
+
{
|
401
|
+
success: success,
|
402
|
+
message: response_hash[:status_message],
|
403
|
+
id: response_hash[:request_id]
|
404
|
+
}
|
405
|
+
end
|
406
|
+
|
407
|
+
end
|
408
|
+
|
409
|
+
end
|