soteria 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|