onelogin 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1503 @@
1
+ require 'onelogin/version'
2
+ require 'onelogin/api/util'
3
+ require 'onelogin/api/cursor'
4
+ require 'json'
5
+ require 'httparty'
6
+ require 'nokogiri'
7
+ require 'time'
8
+
9
+ module OneLogin
10
+ module Api
11
+ # Client class
12
+ #
13
+ # Client class of the OneLogin's Ruby SDK.
14
+ # It makes the API calls to the Onelogin's platform described
15
+ # at https://developers.onelogin.com/api-docs/1/getting-started/dev-overview.
16
+ #
17
+ class Client
18
+ include OneLogin::Api::Util
19
+
20
+ attr_accessor :client_id, :client_secret, :region
21
+ attr_accessor :user_agent, :error, :error_description
22
+
23
+ NOKOGIRI_OPTIONS = Nokogiri::XML::ParseOptions::STRICT |
24
+ Nokogiri::XML::ParseOptions::NONET
25
+
26
+ DEFAULT_USER_AGENT = "onelogin-ruby-sdk v#{OneLogin::VERSION}".freeze
27
+
28
+ # Create a new instance of the Client.
29
+ #
30
+ # @param config [Hash] Client Id, Client Secret and Region
31
+ #
32
+ def initialize(config)
33
+ options = Hash[config.map { |(k, v)| [k.to_sym, v] }]
34
+
35
+ @client_id = options[:client_id]
36
+ @client_secret = options[:client_secret]
37
+ @region = options[:region] || 'us'
38
+ @max_results = options[:max_results] || 1000
39
+
40
+ validate_config
41
+
42
+ @user_agent = DEFAULT_USER_AGENT
43
+ end
44
+
45
+ def validate_config
46
+ raise ArgumentError, 'client_id & client_secret are required' unless @client_id && @client_secret
47
+ end
48
+
49
+ # Clean any previous error registered at the client.
50
+ #
51
+ def clean_error
52
+ @error = nil
53
+ @error_description = nil
54
+ end
55
+
56
+ def extract_error_message_from_response(response)
57
+ message = ''
58
+ content = JSON.parse(response.body)
59
+ if content && content.has_key?('status')
60
+ status = content['status']
61
+ if status.has_key?('message')
62
+ message = status['message']
63
+ elsif status.has_key?('type')
64
+ message = status['type']
65
+ end
66
+ end
67
+ message
68
+ end
69
+
70
+ def expired?
71
+ Time.now.utc > @expiration
72
+ end
73
+
74
+ def prepare_token
75
+ if @access_token.nil?
76
+ access_token
77
+ elsif expired?
78
+ regenerate_token
79
+ end
80
+ end
81
+
82
+ def handle_operation_response(response)
83
+ result = false
84
+ begin
85
+ content = JSON.parse(response.body)
86
+ if content && content.has_key?('status') && content['status'].has_key?('type') && content['status']['type'] == "success"
87
+ result = true
88
+ end
89
+ rescue Exception => e
90
+ result = false
91
+ end
92
+
93
+ result
94
+ end
95
+
96
+ def handle_session_token_response(response)
97
+ content = JSON.parse(response.body)
98
+ if content && content.has_key?('status') && content['status'].has_key?('message') && content.has_key?('data')
99
+ if content['status']['message'] == "Success"
100
+ return OneLogin::Api::Models::SessionTokenInfo.new(content['data'][0])
101
+ elsif content['status']['message'] == "MFA is required for this user"
102
+ return OneLogin::Api::Models::SessionTokenMFAInfo.new(content['data'][0])
103
+ else
104
+ raise "Status Message type not reognized: %s" % content['status']['message']
105
+ end
106
+ end
107
+
108
+ nil
109
+ end
110
+
111
+ def handle_saml_endpoint_response(response)
112
+ content = JSON.parse(response.body)
113
+ if content && content.has_key?('status') && content.has_key?('data') && content['status'].has_key?('message') && content['status'].has_key?('type')
114
+ status_type = content['status']['type']
115
+ status_message = content['status']['message']
116
+ saml_endpoint_response = OneLogin::Api::Models::SAMLEndpointResponse.new(status_type, status_message)
117
+ if status_message == 'Success'
118
+ saml_endpoint_response.saml_response = content['data']
119
+ else
120
+ mfa = OneLogin::Api::Models::MFA.new(content['data'][0])
121
+ saml_endpoint_response.mfa = mfa
122
+ end
123
+
124
+ return saml_endpoint_response
125
+ end
126
+
127
+ nil
128
+ end
129
+
130
+ def headers
131
+ {
132
+ 'Content-Type' => 'application/json',
133
+ 'User-Agent' => @user_agent
134
+ }
135
+ end
136
+
137
+ def authorized_headers(bearer = true)
138
+ authorization = if bearer
139
+ "bearer:#{@access_token}"
140
+ else
141
+ "client_id:#{@client_id},client_secret:#{@client_secret}"
142
+ end
143
+
144
+ headers.merge({
145
+ 'Authorization' => authorization
146
+ })
147
+ end
148
+
149
+ ############################
150
+ # OAuth 2.0 Tokens Methods #
151
+ ############################
152
+
153
+ # Generates an access token and refresh token that you may use to
154
+ # call Onelogin's API methods.
155
+ #
156
+ # @return [OneLoginToken] Returns the generated OAuth Token info
157
+ #
158
+ # @see {https://developers.onelogin.com/api-docs/1/oauth20-tokens/generate-tokens Generate Tokens documentation}
159
+ def access_token
160
+ clean_error
161
+
162
+ begin
163
+ url = url_for(TOKEN_REQUEST_URL)
164
+
165
+ data = {
166
+ 'grant_type' => 'client_credentials'
167
+ }
168
+
169
+ response = HTTParty.post(
170
+ url,
171
+ headers: authorized_headers(false),
172
+ body: data.to_json
173
+ )
174
+
175
+ if response.code == 200
176
+ json_data = JSON.parse(response.body)
177
+ if json_data && json_data['data']
178
+ token = OneLogin::Api::Models::OneLoginToken.new(json_data['data'][0])
179
+ @access_token = token.access_token
180
+ @refresh_token = token.refresh_token
181
+ @expiration = token.created_at + token.expires_in
182
+ return token
183
+ end
184
+ else
185
+ @error = response.code.to_s
186
+ @error_description = extract_error_message_from_response(response)
187
+ end
188
+ rescue Exception => e
189
+ @error = '500'
190
+ @error_description = e.message
191
+ end
192
+
193
+ nil
194
+ end
195
+
196
+ # Refreshing tokens provides a new set of access and refresh tokens.
197
+ #
198
+ # @return [OneLoginToken] Returns the refreshed OAuth Token info
199
+ #
200
+ # @see {https://developers.onelogin.com/api-docs/1/oauth20-tokens/refresh-tokens Refresh Tokens documentation}
201
+ def regenerate_token
202
+ clean_error
203
+
204
+ begin
205
+ url = url_for(TOKEN_REQUEST_URL)
206
+
207
+ data = {
208
+ 'grant_type' => 'refresh_token',
209
+ 'access_token' => @access_token,
210
+ 'refresh_token' => @refresh_token
211
+ }
212
+
213
+ response = HTTParty.post(
214
+ url,
215
+ headers: headers,
216
+ body: data.to_json
217
+ )
218
+
219
+ if response.code == 200
220
+ json_data = JSON.parse(response.body)
221
+ if json_data && json_data['data']
222
+ token = OneLogin::Api::Models::OneLoginToken.new(json_data['data'][0])
223
+ @access_token = token.access_token
224
+ @refresh_token = token.refresh_token
225
+ @expiration = token.created_at + token.expires_in
226
+ return token
227
+ end
228
+ else
229
+ @error = response.code.to_s
230
+ @error_description = extract_error_message_from_response(response)
231
+ end
232
+ rescue Exception => e
233
+ @error = '500'
234
+ @error_description = e.message
235
+ end
236
+
237
+ nil
238
+ end
239
+
240
+ # Revokes an access token and refresh token pair.
241
+ #
242
+ # @return [Boolean] If the opeation succeded
243
+ #
244
+ # @see {https://developers.onelogin.com/api-docs/1/oauth20-tokens/revoke-tokens Revoke Tokens documentation}
245
+ def revoke_token
246
+ clean_error
247
+
248
+ begin
249
+ url = url_for(TOKEN_REVOKE_URL)
250
+
251
+ data = {
252
+ access_token: @access_token
253
+ }
254
+
255
+ response = HTTParty.post(
256
+ url,
257
+ headers: authorized_headers(false),
258
+ body: data.to_json
259
+ )
260
+
261
+ if response.code == 200
262
+ @access_token = nil
263
+ @refresh_token = nil
264
+ @expiration = nil
265
+ return true
266
+ else
267
+ @error = response.code.to_s
268
+ @error_description = extract_error_message_from_response(response)
269
+ end
270
+ rescue Exception => e
271
+ @error = '500'
272
+ @error_description = e.message
273
+ end
274
+
275
+ false
276
+ end
277
+
278
+ # Gets current rate limit details about an access token.
279
+ #
280
+ # @return [RateLimit] Returns the rate limit info
281
+ #
282
+ # @see {https://developers.onelogin.com/api-docs/1/oauth20-tokens/get-rate-limit Get Rate Limit documentation}
283
+ def get_rate_limits
284
+ clean_error
285
+ prepare_token
286
+
287
+ begin
288
+ url = url_for(GET_RATE_URL)
289
+
290
+ response = HTTParty.get(
291
+ url,
292
+ headers: authorized_headers
293
+ )
294
+
295
+ if response.code == 200
296
+ json_data = JSON.parse(response.body)
297
+ if json_data && json_data['data']
298
+ return OneLogin::Api::Models::RateLimit.new(json_data['data'])
299
+ end
300
+ else
301
+ @error = response.code.to_s
302
+ @error_description = extract_error_message_from_response(response)
303
+ end
304
+ rescue Exception => e
305
+ @error = '500'
306
+ @error_description = e.message
307
+ end
308
+
309
+ nil
310
+ end
311
+
312
+ ################
313
+ # User Methods #
314
+ ################
315
+
316
+ # Gets a list of User resources. (if no limit provided, by default gt 50 elements)
317
+ #
318
+ # @param params [Hash] Parameters to filter the result of the list
319
+ #
320
+ # @return [Array] list of User objects
321
+ #
322
+ # @see {https://developers.onelogin.com/api-docs/1/users/get-users Get Users documentation}
323
+ def get_users(params = {})
324
+ clean_error
325
+ prepare_token
326
+
327
+ begin
328
+ options = {
329
+ model: OneLogin::Api::Models::User,
330
+ headers: authorized_headers,
331
+ max_results: @max_results,
332
+ params: params
333
+ }
334
+
335
+ return Cursor.new(url_for(GET_USERS_URL), options)
336
+
337
+ rescue Exception => e
338
+ @error = '500'
339
+ @error_description = e.message
340
+ end
341
+
342
+ nil
343
+ end
344
+
345
+ # Gets User by ID.
346
+ #
347
+ # @param user_id [Integer] Id of the user
348
+ #
349
+ # @return [User] the user identified by the id
350
+ #
351
+ # @see {https://developers.onelogin.com/api-docs/1/users/get-user-by-id Get User by ID documentation}
352
+ def get_user(user_id)
353
+ clean_error
354
+ prepare_token
355
+
356
+ begin
357
+
358
+ url = url_for(GET_USER_URL, user_id)
359
+
360
+ response = HTTParty.get(
361
+ url,
362
+ headers: authorized_headers
363
+ )
364
+
365
+ if response.code == 200
366
+ json_data = JSON.parse(response.body)
367
+ if json_data && json_data['data']
368
+ return OneLogin::Api::Models::User.new(json_data['data'][0])
369
+ end
370
+ else
371
+ @error = response.code.to_s
372
+ @error_description = extract_error_message_from_response(response)
373
+ end
374
+ rescue Exception => e
375
+ @error = '500'
376
+ @error_description = e.message
377
+ end
378
+
379
+ nil
380
+ end
381
+
382
+ # Gets a list of apps accessible by a user, not including personal apps.
383
+ #
384
+ # @param user_id [Integer] Id of the user
385
+ #
386
+ # @return [Array] the apps of the user identified by the id
387
+ #
388
+ # @see {https://developers.onelogin.com/api-docs/1/users/get-apps-for-user Get Apps for a User documentation}
389
+ def get_user_apps(user_id)
390
+ clean_error
391
+ prepare_token
392
+
393
+ begin
394
+ options = {
395
+ model: OneLogin::Api::Models::App,
396
+ headers: authorized_headers
397
+ }
398
+
399
+ return Cursor.new(url_for(GET_APPS_FOR_USER_URL, user_id), options)
400
+
401
+ rescue Exception => e
402
+ @error = '500'
403
+ @error_description = e.message
404
+ end
405
+
406
+ nil
407
+ end
408
+
409
+ # Gets a list of role IDs that have been assigned to a user.
410
+ #
411
+ # @param user_id [Integer] Id of the user
412
+ #
413
+ # @return [Array] the role ids of the user identified by the id
414
+ #
415
+ # @see {https://developers.onelogin.com/api-docs/1/users/get-roles-for-user Get Roles for a User documentation}
416
+ def get_user_roles(user_id)
417
+ clean_error
418
+ prepare_token
419
+
420
+ begin
421
+ url = url_for(GET_ROLES_FOR_USER_URL, user_id)
422
+
423
+ response = HTTParty.get(
424
+ url,
425
+ headers: authorized_headers
426
+ )
427
+
428
+ role_ids = []
429
+ if response.code == 200
430
+ json_data = JSON.parse(response.body)
431
+ role_ids = json_data['data'][0] if json_data && json_data['data']
432
+ else
433
+ @error = response.code.to_s
434
+ @error_description = extract_error_message_from_response(response)
435
+ end
436
+
437
+ return role_ids
438
+ rescue Exception => e
439
+ @error = '500'
440
+ @error_description = e.message
441
+ end
442
+
443
+ nil
444
+ end
445
+
446
+ # Gets a list of all custom attribute fields (also known as custom user fields) that have been defined for OL account.
447
+ #
448
+ # @return [Array] the custom attributes of the account
449
+ #
450
+ # @see {https://developers.onelogin.com/api-docs/1/users/get-custom-attributes Get Custom Attributes documentation}
451
+ def get_custom_attributes
452
+ clean_error
453
+ prepare_token
454
+
455
+ begin
456
+ url = url_for(GET_CUSTOM_ATTRIBUTES_URL)
457
+
458
+ response = HTTParty.get(
459
+ url,
460
+ headers: authorized_headers
461
+ )
462
+
463
+ custom_attributes = []
464
+ if response.code == 200
465
+ json_data = JSON.parse(response.body)
466
+ if json_data && json_data['data']
467
+ custom_attributes = json_data['data'][0]
468
+ end
469
+ else
470
+ @error = response.code.to_s
471
+ @error_description = extract_error_message_from_response(response)
472
+ end
473
+
474
+ return custom_attributes
475
+ rescue Exception => e
476
+ @error = '500'
477
+ @error_description = e.message
478
+ end
479
+
480
+ nil
481
+ end
482
+
483
+ # Creates an user
484
+ #
485
+ # @param user_params [Hash] User data (firstname, lastname, email, username, company,
486
+ # department, directory_id, distinguished_name,
487
+ # external_id, group_id, invalid_login_attempts,
488
+ # locale_code, manager_ad_id, member_of,
489
+ # openid_name, phone, samaccountname, title,
490
+ # userprincipalname)
491
+ #
492
+ # @return [User] the created user
493
+ #
494
+ # @see {https://developers.onelogin.com/api-docs/1/users/create-user Create User documentation}
495
+ def create_user(user_params)
496
+ clean_error
497
+ prepare_token
498
+
499
+ begin
500
+ url = url_for(CREATE_USER_URL)
501
+
502
+ response = HTTParty.post(
503
+ url,
504
+ headers: authorized_headers,
505
+ body: user_params.to_json
506
+ )
507
+
508
+ if response.code == 200
509
+ json_data = JSON.parse(response.body)
510
+ if json_data && json_data['data']
511
+ return OneLogin::Api::Models::User.new(json_data['data'][0])
512
+ end
513
+ else
514
+ @error = response.code.to_s
515
+ @error_description = extract_error_message_from_response(response)
516
+ end
517
+ rescue Exception => e
518
+ @error = '500'
519
+ @error_description = e.message
520
+ end
521
+
522
+ nil
523
+ end
524
+
525
+ # Updates an user
526
+ #
527
+ # @param user_id [Integer] Id of the user
528
+ # @param user_params [Hash] User data (firstname, lastname, email, username, company,
529
+ # department, directory_id, distinguished_name,
530
+ # external_id, group_id, invalid_login_attempts,
531
+ # locale_code, manager_ad_id, member_of,
532
+ # openid_name, phone, samaccountname, title,
533
+ # userprincipalname)
534
+ #
535
+ # @return [User] the modified user
536
+ #
537
+ # @see {https://developers.onelogin.com/api-docs/1/users/update-user Update User by ID documentation}
538
+ def update_user(user_id, user_params)
539
+ clean_error
540
+ prepare_token
541
+
542
+ begin
543
+ url = url_for(UPDATE_USER_URL, user_id)
544
+
545
+ response = HTTParty.put(
546
+ url,
547
+ headers: authorized_headers,
548
+ body: user_params.to_json
549
+ )
550
+
551
+ if response.code == 200
552
+ json_data = JSON.parse(response.body)
553
+ if json_data && json_data['data']
554
+ return OneLogin::Api::Models::User.new(json_data['data'][0])
555
+ end
556
+ else
557
+ @error = response.code.to_s
558
+ @error_description = extract_error_message_from_response(response)
559
+ end
560
+ rescue Exception => e
561
+ @error = '500'
562
+ @error_description = e.message
563
+ end
564
+
565
+ nil
566
+ end
567
+
568
+ # Assigns Roles to User
569
+ #
570
+ # @param user_id [Integer] Id of the user
571
+ # @param role_ids [Array] List of role ids to be added
572
+ #
573
+ # @return [Boolean] if the action succeed
574
+ #
575
+ # @see {https://developers.onelogin.com/api-docs/1/users/assign-role-to-user Assign Role to User documentation}
576
+ def assign_role_to_user(user_id, role_ids)
577
+ clean_error
578
+ prepare_token
579
+
580
+ begin
581
+ url = url_for(ADD_ROLE_TO_USER_URL, user_id)
582
+
583
+ data = {
584
+ 'role_id_array' => role_ids
585
+ }
586
+
587
+ response = HTTParty.put(
588
+ url,
589
+ headers: authorized_headers,
590
+ body: data.to_json
591
+ )
592
+
593
+ if response.code == 200
594
+ return handle_operation_response(response)
595
+ else
596
+ @error = response.code.to_s
597
+ @error_description = extract_error_message_from_response(response)
598
+ end
599
+ rescue Exception => e
600
+ @error = '500'
601
+ @error_description = e.message
602
+ end
603
+
604
+ false
605
+ end
606
+
607
+ # Removes Role from User
608
+ #
609
+ # @param user_id [Integer] Id of the user
610
+ # @param role_ids [Array] List of role ids to be removed
611
+ #
612
+ # @return [Boolean] if the action succeed
613
+ #
614
+ # @see {https://developers.onelogin.com/api-docs/1/users/remove-role-from-user Remove Role from User documentation}
615
+ def remove_role_from_user(user_id, role_ids)
616
+ clean_error
617
+ prepare_token
618
+
619
+ begin
620
+ url = url_for(DELETE_ROLE_TO_USER_URL, user_id)
621
+
622
+ data = {
623
+ 'role_id_array' => role_ids
624
+ }
625
+
626
+ response = HTTParty.put(
627
+ url,
628
+ headers: authorized_headers,
629
+ body: data.to_json
630
+ )
631
+
632
+ if response.code == 200
633
+ return handle_operation_response(response)
634
+ else
635
+ @error = response.code.to_s
636
+ @error_description = extract_error_message_from_response(response)
637
+ end
638
+ rescue Exception => e
639
+ @error = '500'
640
+ @error_description = e.message
641
+ end
642
+
643
+ false
644
+ end
645
+
646
+ # Sets Password by ID Using Cleartext
647
+ #
648
+ # @param user_id [Integer] Id of the user
649
+ # @param password [String] Set to the password value using cleartext.
650
+ # @param password_confirmation [String] Ensure that this value matches the password value exactly.
651
+ # @validate_policy [Boolean] Force validation against assigned OneLogin user password policy
652
+ #
653
+ # @return [Boolean] if the action succeed
654
+ #
655
+ # @see {https://developers.onelogin.com/api-docs/1/users/set-password-in-cleartext Set Password by ID Using Cleartext documentation}
656
+ def set_password_using_clear_text(user_id, password, password_confirmation, validate_policy=false)
657
+ clean_error
658
+ prepare_token
659
+
660
+ begin
661
+ url = url_for(SET_PW_CLEARTEXT, user_id)
662
+
663
+ data = {
664
+ 'password' => password,
665
+ 'password_confirmation' => password_confirmation,
666
+ 'validate_policy' => validate_policy
667
+ }
668
+
669
+ response = HTTParty.put(
670
+ url,
671
+ headers: authorized_headers,
672
+ body: data.to_json
673
+ )
674
+
675
+ if response.code == 200
676
+ return handle_operation_response(response)
677
+ else
678
+ @error = response.code.to_s
679
+ @error_description = extract_error_message_from_response(response)
680
+ end
681
+ rescue Exception => e
682
+ @error = '500'
683
+ @error_description = e.message
684
+ end
685
+
686
+ false
687
+ end
688
+
689
+ # Set Password by ID Using Salt and SHA-256
690
+ #
691
+ # @param user_id [Integer] Id of the user
692
+ # @param password [String] Set to the password value using cleartext.
693
+ # @param password_confirmation [String] Ensure that this value matches the password value exactly.
694
+ # @param password_algorithm [String] Set to salt+sha256.
695
+ # @param password_salt [String] (Optional) To provide your own salt value.
696
+ #
697
+ # @return [Boolean] if the action succeed
698
+ #
699
+ # @see {https://developers.onelogin.com/api-docs/1/users/set-password-using-sha-256 Set Password by ID Using Salt and SHA-256 documentation}
700
+ def set_password_using_hash_salt(user_id, password, password_confirmation, password_algorithm, password_salt=nil)
701
+ clean_error
702
+ prepare_token
703
+
704
+ begin
705
+ url = url_for(SET_PW_SALT, user_id)
706
+
707
+ data = {
708
+ 'password' => password,
709
+ 'password_confirmation' => password_confirmation,
710
+ 'password_algorithm' => password_algorithm
711
+ }
712
+
713
+ unless password_salt.nil?
714
+ data['password_salt'] = password_salt
715
+ end
716
+
717
+ response = HTTParty.put(
718
+ url,
719
+ headers: authorized_headers,
720
+ body: data.to_json
721
+ )
722
+
723
+ if response.code == 200
724
+ return handle_operation_response(response)
725
+ else
726
+ @error = response.code.to_s
727
+ @error_description = extract_error_message_from_response(response)
728
+ end
729
+ rescue Exception => e
730
+ @error = '500'
731
+ @error_description = e.message
732
+ end
733
+
734
+ false
735
+ end
736
+
737
+ # Set Custom Attribute Value
738
+ #
739
+ # @param user_id [Integer] Id of the user
740
+ # @param custom_attributes [Hash] Provide one or more key value pairs composed of the custom attribute field shortname and the value that you want to set the field to.
741
+ #
742
+ # @return [Boolean] if the action succeed
743
+ #
744
+ # @see {https://developers.onelogin.com/api-docs/1/users/set-custom-attribute Set Custom Attribute Value documentation}
745
+ def set_custom_attribute_to_user(user_id, custom_attributes)
746
+ clean_error
747
+ prepare_token
748
+
749
+ begin
750
+ url = url_for(SET_CUSTOM_ATTRIBUTE_TO_USER_URL, user_id)
751
+
752
+ data = {
753
+ 'custom_attributes' => custom_attributes
754
+ }
755
+
756
+ response = HTTParty.put(
757
+ url,
758
+ headers: authorized_headers,
759
+ body: data.to_json
760
+ )
761
+
762
+ if response.code == 200
763
+ return handle_operation_response(response)
764
+ else
765
+ @error = response.code.to_s
766
+ @error_description = extract_error_message_from_response(response)
767
+ end
768
+ rescue Exception => e
769
+ @error = '500'
770
+ @error_description = e.message
771
+ end
772
+
773
+ false
774
+ end
775
+
776
+ # Log a user out of any and all sessions.
777
+ #
778
+ # @param user_id [Integer] Id of the user to be logged out
779
+ #
780
+ # @return [Boolean] if the action succeed
781
+ #
782
+ # @see {https://developers.onelogin.com/api-docs/1/users/log-user-out Log User Out documentation}
783
+ def log_user_out(user_id)
784
+ clean_error
785
+ prepare_token
786
+
787
+ begin
788
+ url = url_for(LOG_USER_OUT_URL, user_id)
789
+
790
+ response = HTTParty.put(
791
+ url,
792
+ headers: authorized_headers
793
+ )
794
+
795
+ if response.code == 200
796
+ return handle_operation_response(response)
797
+ else
798
+ @error = response.code.to_s
799
+ @error_description = extract_error_message_from_response(response)
800
+ end
801
+ rescue Exception => e
802
+ @error = '500'
803
+ @error_description = e.message
804
+ end
805
+
806
+ false
807
+ end
808
+
809
+ # Use this call to lock a user's account based on the policy assigned to
810
+ # the user, for a specific time you define in the request, or until you
811
+ # unlock it.
812
+ #
813
+ # @param user_id [Integer] Id of the user to be locked
814
+ # @param minutes [Integer] Set to the number of minutes for which you want to lock the user account. (0 to delegate on policy)
815
+ #
816
+ # @return [Boolean] if the action succeed
817
+ #
818
+ # @see {https://developers.onelogin.com/api-docs/1/users/lock-user-account Lock User Account documentation}
819
+ def lock_user(user_id, minutes)
820
+ clean_error
821
+ prepare_token
822
+
823
+ begin
824
+ url = url_for(LOCK_USER_URL, user_id)
825
+
826
+ data = {
827
+ 'locked_until' => minutes
828
+ }
829
+
830
+ response = HTTParty.put(
831
+ url,
832
+ headers: authorized_headers,
833
+ body: data.to_json
834
+ )
835
+
836
+ if response.code == 200
837
+ return handle_operation_response(response)
838
+ else
839
+ @error = response.code.to_s
840
+ @error_description = extract_error_message_from_response(response)
841
+ end
842
+ rescue Exception => e
843
+ @error = '500'
844
+ @error_description = e.message
845
+ end
846
+
847
+ false
848
+ end
849
+
850
+ # Deletes an user
851
+ #
852
+ # @param user_id [Integer] Id of the user to be logged out
853
+ #
854
+ # @return [Boolean] if the action succeed
855
+ #
856
+ # @see {https://developers.onelogin.com/api-docs/1/users/delete-user Delete User by ID documentation}
857
+ def delete_user(user_id)
858
+ clean_error
859
+ prepare_token
860
+
861
+ begin
862
+ url = url_for(DELETE_USER_URL, user_id)
863
+
864
+ response = HTTParty.delete(
865
+ url,
866
+ headers: authorized_headers
867
+ )
868
+
869
+ if response.code == 200
870
+ return handle_operation_response(response)
871
+ else
872
+ @error = response.code.to_s
873
+ @error_description = extract_error_message_from_response(response)
874
+ end
875
+ rescue Exception => e
876
+ @error = '500'
877
+ @error_description = e.message
878
+ end
879
+
880
+ false
881
+ end
882
+
883
+ # Generates a session login token in scenarios in which MFA may or may not be required.
884
+ # A session login token expires two minutes after creation.
885
+ #
886
+ # @param query_params [Hash] Query Parameters (username_or_email, password, subdomain, return_to_url,
887
+ # ip_address, browser_id)
888
+ # @param allowed_origin [String] Custom-Allowed-Origin-Header. Required for CORS requests only.
889
+ # Set to the Origin URI from which you are allowed to send a request
890
+ # using CORS.
891
+ #
892
+ # @return [SessionTokenInfo|SessionTokenMFAInfo] if the action succeed
893
+ #
894
+ # @see {https://developers.onelogin.com/api-docs/1/users/create-session-login-token Create Session Login Token documentation}
895
+ def create_session_login_token(query_params, allowed_origin='')
896
+ clean_error
897
+ prepare_token
898
+
899
+ begin
900
+ url = url_for(SESSION_LOGIN_TOKEN_URL)
901
+
902
+ unless allowed_origin.nil? || allowed_origin.empty?
903
+ headers['Custom-Allowed-Origin-Header-1'] = allowed_origin
904
+ end
905
+
906
+ if query_params.nil? || !query_params.has_key?('username_or_email') || !query_params.has_key?('password') || !query_params.has_key?('subdomain')
907
+ raise "username_or_email, password and subdomain are required parameters"
908
+ end
909
+
910
+ response = HTTParty.post(
911
+ url,
912
+ headers: authorized_headers,
913
+ body: query_params.to_json
914
+ )
915
+
916
+ if response.code == 200
917
+ return handle_session_token_response(response)
918
+ else
919
+ @error = response.code.to_s
920
+ @error_description = extract_error_message_from_response(response)
921
+ end
922
+ rescue Exception => e
923
+ @error = '500'
924
+ @error_description = e.message
925
+ end
926
+
927
+ nil
928
+ end
929
+
930
+ # Verify a one-time password (OTP) value provided for multi-factor authentication (MFA).
931
+ #
932
+ # @param device_id [String] Provide the MFA device_id you are submitting for verification.
933
+ # @param state_token [String] Provide the state_token associated with the MFA device_id you are submitting for verification.
934
+ # @param otp_token [String] (Optional) Provide the OTP value for the MFA factor you are submitting for verification.
935
+ #
936
+ # @return [SessionTokenInfo] if the action succeed
937
+ #
938
+ # @see {https://developers.onelogin.com/api-docs/1/users/verify-factor Verify Factor documentation}
939
+ def get_session_token_verified(device_id, state_token, otp_token=nil)
940
+ clean_error
941
+ prepare_token
942
+
943
+ begin
944
+ url = url_for(GET_TOKEN_VERIFY_FACTOR)
945
+
946
+ data = {
947
+ 'device_id'=> device_id.to_s,
948
+ 'state_token'=> state_token
949
+ }
950
+
951
+ unless otp_token.nil? || otp_token.empty?
952
+ data['otp_token'] = otp_token
953
+ end
954
+
955
+ response = HTTParty.post(
956
+ url,
957
+ headers: authorized_headers,
958
+ body: data.to_json
959
+ )
960
+
961
+ if response.code == 200
962
+ return handle_session_token_response(response)
963
+ else
964
+ @error = response.code.to_s
965
+ @error_description = extract_error_message_from_response(response)
966
+ end
967
+ rescue Exception => e
968
+ @error = '500'
969
+ @error_description = e.message
970
+ end
971
+
972
+ nil
973
+ end
974
+
975
+ ################
976
+ # Role Methods #
977
+ ################
978
+
979
+ # Gets a list of Role resources. (if no limit provided, by default get 50 elements)
980
+ #
981
+ # @param params [Hash] Parameters to filter the result of the list
982
+ #
983
+ # @return [Array] list of Role objects
984
+ #
985
+ # @see {https://developers.onelogin.com/api-docs/1/roles/get-roles Get Roles documentation}
986
+ def get_roles(params = {})
987
+ clean_error
988
+ prepare_token
989
+
990
+ begin
991
+ options = {
992
+ model: OneLogin::Api::Models::Role,
993
+ headers: authorized_headers,
994
+ max_results: @max_results,
995
+ params: params
996
+ }
997
+
998
+ return Cursor.new(url_for(GET_ROLES_URL), options)
999
+
1000
+ rescue Exception => e
1001
+ @error = '500'
1002
+ @error_description = e.message
1003
+ end
1004
+
1005
+ nil
1006
+ end
1007
+
1008
+ # Gets Role by ID.
1009
+ #
1010
+ # @param role_id [Integer] Id of the Role
1011
+ #
1012
+ # @return [Role] the role identified by the id
1013
+ #
1014
+ # @see {https://developers.onelogin.com/api-docs/1/roles/get-role-by-id Get Role by ID documentation}
1015
+ def get_role(role_id)
1016
+ clean_error
1017
+ prepare_token
1018
+
1019
+ begin
1020
+ url = url_for(GET_ROLE_URL, role_id)
1021
+
1022
+ response = HTTParty.get(
1023
+ url,
1024
+ headers: authorized_headers
1025
+ )
1026
+
1027
+ if response.code == 200
1028
+ json_data = JSON.parse(response.body)
1029
+ if json_data && json_data['data']
1030
+ return OneLogin::Api::Models::Role.new(json_data['data'][0])
1031
+ end
1032
+ else
1033
+ @error = response.code.to_s
1034
+ @error_description = extract_error_message_from_response(response)
1035
+ end
1036
+ rescue Exception => e
1037
+ @error = '500'
1038
+ @error_description = e.message
1039
+ end
1040
+
1041
+ nil
1042
+ end
1043
+
1044
+ #################
1045
+ # Event Methods #
1046
+ #################
1047
+
1048
+ # List of all OneLogin event types available to the Events API.
1049
+ #
1050
+ # @return [Array] the list of event type
1051
+ #
1052
+ # @see {https://developers.onelogin.com/api-docs/1/events/event-types Get Event Types documentation}
1053
+ def get_event_types
1054
+ clean_error
1055
+ prepare_token
1056
+
1057
+ begin
1058
+ options = {
1059
+ model: OneLogin::Api::Models::EventType,
1060
+ headers: authorized_headers
1061
+ }
1062
+
1063
+ return Cursor.new(url_for(GET_EVENT_TYPES_URL), options)
1064
+
1065
+ rescue Exception => e
1066
+ @error = '500'
1067
+ @error_description = e.message
1068
+ end
1069
+
1070
+ nil
1071
+ end
1072
+
1073
+ # Gets a list of Event resources. (if no limit provided, by default get 50 elements)
1074
+ #
1075
+ # @param params [Hash] Parameters to filter the result of the list
1076
+ #
1077
+ # @return [Array] list of Event objects
1078
+ #
1079
+ # @see {https://developers.onelogin.com/api-docs/1/events/get-events Get Events documentation}
1080
+ def get_events(params={})
1081
+ clean_error
1082
+ prepare_token
1083
+
1084
+ begin
1085
+ options = {
1086
+ model: OneLogin::Api::Models::Event,
1087
+ headers: authorized_headers,
1088
+ max_results: @max_results,
1089
+ params: params
1090
+ }
1091
+
1092
+ return Cursor.new(url_for(GET_EVENTS_URL), options)
1093
+
1094
+ rescue Exception => e
1095
+ @error = '500'
1096
+ @error_description = e.message
1097
+ end
1098
+
1099
+ nil
1100
+ end
1101
+
1102
+ # Gets Event by ID.
1103
+ #
1104
+ # @param event_id [Integer] Id of the Event
1105
+ #
1106
+ # @return [Event] the event identified by the id
1107
+ #
1108
+ # @see {https://developers.onelogin.com/api-docs/1/events/get-event-by-id Get Event by ID documentation}
1109
+ def get_event(event_id)
1110
+ clean_error
1111
+ prepare_token
1112
+
1113
+ begin
1114
+ url = url_for(GET_EVENT_URL, event_id)
1115
+
1116
+ response = HTTParty.get(
1117
+ url,
1118
+ headers: authorized_headers
1119
+ )
1120
+
1121
+ if response.code == 200
1122
+ json_data = JSON.parse(response.body)
1123
+ if json_data && json_data['data']
1124
+ return OneLogin::Api::Models::Event.new(json_data['data'][0])
1125
+ end
1126
+ else
1127
+ @error = response.code.to_s
1128
+ @error_description = extract_error_message_from_response(response)
1129
+ end
1130
+ rescue Exception => e
1131
+ @error = '500'
1132
+ @error_description = e.message
1133
+ end
1134
+
1135
+ nil
1136
+ end
1137
+
1138
+ # Create an event in the OneLogin event log.
1139
+ #
1140
+ # @param event_params [Hash] Event data (event_type_id, account_id, actor_system,
1141
+ # actor_user_id, actor_user_name, app_id,
1142
+ # assuming_acting_user_id, custom_message,
1143
+ # directory_sync_run_id, group_id, group_name,
1144
+ # ipaddr, otp_device_id, otp_device_name,
1145
+ # policy_id, policy_name, role_id, role_name,
1146
+ # user_id, user_name)
1147
+ #
1148
+ # @return [Boolean] the result of the operation
1149
+ #
1150
+ # @see {https://developers.onelogin.com/api-docs/1/events/create-event Create Event documentation}
1151
+ def create_event(event_params)
1152
+ clean_error
1153
+ prepare_token
1154
+
1155
+ begin
1156
+ url = url_for(CREATE_EVENT_URL)
1157
+
1158
+ response = HTTParty.post(
1159
+ url,
1160
+ headers: authorized_headers,
1161
+ body: event_params.to_json
1162
+ )
1163
+
1164
+ if response.code == 200
1165
+ return handle_operation_response(response)
1166
+ else
1167
+ @error = response.code.to_s
1168
+ @error_description = extract_error_message_from_response(response)
1169
+ end
1170
+ rescue Exception => e
1171
+ @error = '500'
1172
+ @error_description = e.message
1173
+ end
1174
+
1175
+ false
1176
+ end
1177
+
1178
+ #################
1179
+ # Group Methods #
1180
+ #################
1181
+
1182
+ # Gets a list of Group resources (element of groups limited with the limit parameter).
1183
+ #
1184
+ # @return [Array] the list of groups
1185
+ #
1186
+ # @see {https://developers.onelogin.com/api-docs/1/groups/get-groups Get Groups documentation}
1187
+ def get_groups(params = {})
1188
+ clean_error
1189
+ prepare_token
1190
+
1191
+ begin
1192
+ options = {
1193
+ model: OneLogin::Api::Models::Group,
1194
+ headers: authorized_headers,
1195
+ max_results: @max_results,
1196
+ params: params
1197
+ }
1198
+
1199
+ return Cursor.new(url_for(GET_GROUPS_URL), options)
1200
+
1201
+ rescue Exception => e
1202
+ @error = '500'
1203
+ @error_description = e.message
1204
+ end
1205
+
1206
+ nil
1207
+ end
1208
+
1209
+ # Gets Group by ID.
1210
+ #
1211
+ # @param group_id [Integer] Id of the Group
1212
+ #
1213
+ # @return [Group] the group identified by the id
1214
+ #
1215
+ # @see {https://developers.onelogin.com/api-docs/1/groups/get-group-by-id Get Group by ID documentation}
1216
+ def get_group(group_id)
1217
+ clean_error
1218
+ prepare_token
1219
+
1220
+ begin
1221
+ url = url_for(GET_GROUP_URL, group_id)
1222
+
1223
+ response = HTTParty.get(
1224
+ url,
1225
+ headers: authorized_headers
1226
+ )
1227
+
1228
+ if response.code == 200
1229
+ json_data = JSON.parse(response.body)
1230
+ if json_data && json_data['data']
1231
+ return OneLogin::Api::Models::Group.new(json_data['data'][0])
1232
+ end
1233
+ else
1234
+ @error = response.code.to_s
1235
+ @error_description = extract_error_message_from_response(response)
1236
+ end
1237
+ rescue Exception => e
1238
+ @error = '500'
1239
+ @error_description = e.message
1240
+ end
1241
+
1242
+ nil
1243
+ end
1244
+
1245
+ ##########################
1246
+ # SAML Assertion Methods #
1247
+ ##########################
1248
+
1249
+ # Generates a SAML Assertion.
1250
+ #
1251
+ # @param username_or_email [String] username or email of the OneLogin user accessing the app
1252
+ # @param password [String] Password of the OneLogin user accessing the app
1253
+ # @param app_id [String] App ID of the app for which you want to generate a SAML token
1254
+ # @param subdomain [String] subdomain of the OneLogin account related to the user/app
1255
+ # @param ip_address [String] (Optional) whitelisted IP address that needs to be bypassed (some MFA scenarios)
1256
+ #
1257
+ # @return [SAMLEndpointResponse] object with an encoded SAMLResponse
1258
+ #
1259
+ # @see {https://developers.onelogin.com/api-docs/1/saml-assertions/generate-saml-assertion Generate SAML Assertion documentation}
1260
+ def get_saml_assertion(username_or_email, password, app_id, subdomain, ip_address=nil)
1261
+ clean_error
1262
+ prepare_token
1263
+
1264
+ begin
1265
+ url = url_for(GET_SAML_ASSERTION_URL)
1266
+
1267
+ data = {
1268
+ 'username_or_email'=> username_or_email,
1269
+ 'password'=> password,
1270
+ 'app_id'=> app_id,
1271
+ 'subdomain'=> subdomain,
1272
+ }
1273
+
1274
+ unless ip_address.nil? || ip_address.empty?
1275
+ data['ip_address'] = ip_address
1276
+ end
1277
+
1278
+ response = HTTParty.post(
1279
+ url,
1280
+ headers: authorized_headers,
1281
+ body: data.to_json
1282
+ )
1283
+
1284
+ if response.code == 200
1285
+ return handle_saml_endpoint_response(response)
1286
+ else
1287
+ @error = response.code.to_s
1288
+ @error_description = extract_error_message_from_response(response)
1289
+ end
1290
+ rescue Exception => e
1291
+ @error = '500'
1292
+ @error_description = e.message
1293
+ end
1294
+
1295
+ nil
1296
+ end
1297
+
1298
+ # Verify a one-time password (OTP) value provided for a second factor when multi-factor authentication (MFA) is required for SAML authentication.
1299
+ #
1300
+ # @param app_id [String] App ID of the app for which you want to generate a SAML token
1301
+ # @param devide_id [String] Provide the MFA device_id you are submitting for verification.
1302
+ # @param state_token [String] Provide the state_token associated with the MFA device_id you are submitting for verification.
1303
+ # @param otp_token [String] (Optional) Provide the OTP value for the MFA factor you are submitting for verification.
1304
+ # @param url_endpoint [String] (Optional) Specify an url where return the response.
1305
+ #
1306
+ # @return [SAMLEndpointResponse] object with an encoded SAMLResponse
1307
+ #
1308
+ # @see {https://developers.onelogin.com/api-docs/1/saml-assertions/verify-factor Verify Factor documentation}
1309
+ def get_saml_assertion_verifying(app_id, device_id, state_token, otp_token=nil, url_endpoint=nil)
1310
+ clean_error
1311
+ prepare_token
1312
+
1313
+ begin
1314
+
1315
+ if url_endpoint.nil? || url_endpoint.empty?
1316
+ url = url_for(GET_SAML_VERIFY_FACTOR)
1317
+ else
1318
+ url = url_endpoint
1319
+ end
1320
+
1321
+ data = {
1322
+ 'app_id'=> app_id,
1323
+ 'device_id'=> device_id.to_s,
1324
+ 'state_token'=> state_token
1325
+ }
1326
+
1327
+ unless otp_token.nil? || otp_token.empty?
1328
+ data['otp_token'] = otp_token
1329
+ end
1330
+
1331
+ response = HTTParty.post(
1332
+ url,
1333
+ headers: authorized_headers,
1334
+ body: data.to_json
1335
+ )
1336
+
1337
+ if response.code == 200
1338
+ return handle_saml_endpoint_response(response)
1339
+ else
1340
+ @error = response.code.to_s
1341
+ @error_description = extract_error_message_from_response(response)
1342
+ end
1343
+ rescue Exception => e
1344
+ @error = '500'
1345
+ @error_description = e.message
1346
+ end
1347
+
1348
+ nil
1349
+ end
1350
+
1351
+ ########################
1352
+ # Invite Links Methods #
1353
+ ########################
1354
+
1355
+ # Generates an invite link for a user that you have already created in your OneLogin account.
1356
+ #
1357
+ # @param email [String] Set to the email address of the user that you want to generate an invite link for.
1358
+ #
1359
+ # @return [String] the invitation link
1360
+ #
1361
+ # @see {https://developers.onelogin.com/api-docs/1/invite-links/generate-invite-link Generate Invite Link documentation}
1362
+ def generate_invite_link(email)
1363
+ clean_error
1364
+ prepare_token
1365
+
1366
+ begin
1367
+ url = url_for(GENERATE_INVITE_LINK_URL)
1368
+
1369
+ data = {
1370
+ 'email'=> email
1371
+ }
1372
+
1373
+ response = HTTParty.post(
1374
+ url,
1375
+ headers: authorized_headers,
1376
+ body: data.to_json
1377
+ )
1378
+
1379
+ if response.code == 200
1380
+ json_data = JSON.parse(response.body)
1381
+ if json_data && json_data['data']
1382
+ return json_data['data'][0]
1383
+ end
1384
+ else
1385
+ @error = response.code.to_s
1386
+ @error_description = extract_error_message_from_response(response)
1387
+ end
1388
+ rescue Exception => e
1389
+ @error = '500'
1390
+ @error_description = e.message
1391
+ end
1392
+
1393
+ nil
1394
+ end
1395
+
1396
+ # Sends an invite link to a user that you have already created in your OneLogin account.
1397
+ #
1398
+ # @param email [String] Set to the email address of the user that you want to send an invite link for.
1399
+ # @param personal_email [String] (Optional) If you want to send the invite email to an email other than the
1400
+ # one provided in email, provide it here. The invite link will be
1401
+ # sent to this address instead.
1402
+ #
1403
+ # @return [String] the result of the operation
1404
+ #
1405
+ # @see {https://developers.onelogin.com/api-docs/1/invite-links/send-invite-link Send Invite Link documentation}
1406
+ def send_invite_link(email, personal_email=nil)
1407
+ clean_error
1408
+ prepare_token
1409
+
1410
+ begin
1411
+ url = url_for(SEND_INVITE_LINK_URL)
1412
+
1413
+ data = {
1414
+ 'email'=> email
1415
+ }
1416
+
1417
+ unless personal_email.nil? || personal_email.empty?
1418
+ data['personal_email'] = personal_email
1419
+ end
1420
+
1421
+ response = HTTParty.post(
1422
+ url,
1423
+ headers: authorized_headers,
1424
+ body: data.to_json
1425
+ )
1426
+
1427
+ if response.code == 200
1428
+ return handle_operation_response(response)
1429
+ else
1430
+ @error = response.code.to_s
1431
+ @error_description = extract_error_message_from_response(response)
1432
+ end
1433
+ rescue Exception => e
1434
+ @error = '500'
1435
+ @error_description = e.message
1436
+ end
1437
+
1438
+ false
1439
+ end
1440
+
1441
+ # Lists apps accessible by a OneLogin user.
1442
+ #
1443
+ # @param token [String] Provide your embedding token.
1444
+ # @param email [String] Provide the email of the user for which you want to return a list of embeddable apps.
1445
+ #
1446
+ # @return [Array] the embed apps
1447
+ #
1448
+ # @see {https://developers.onelogin.com/api-docs/1/embed-apps/get-apps-to-embed-for-a-user Get Apps to Embed for a User documentation}
1449
+ def get_embed_apps(token, email)
1450
+ clean_error
1451
+
1452
+ begin
1453
+ response = HTTParty.get(
1454
+ EMBED_APP_URL,
1455
+ headers: {
1456
+ 'User-Agent' => @user_agent
1457
+ },
1458
+ query: {
1459
+ token: token,
1460
+ email: email
1461
+ }
1462
+ )
1463
+
1464
+ if response.code == 200 && !(response.body.nil? || response.body.empty?)
1465
+ return retrieve_apps_from_xml(response.body)
1466
+ else
1467
+ @error = response.code.to_s
1468
+ unless response.body.nil? || response.body.empty?
1469
+ @error_description = response.body
1470
+ end
1471
+ end
1472
+ rescue Exception => e
1473
+ @error = '500'
1474
+ @error_description = e.message
1475
+ end
1476
+
1477
+ nil
1478
+ end
1479
+
1480
+ def retrieve_apps_from_xml(xml_content)
1481
+ doc = Nokogiri::XML(xml_content) do |config|
1482
+ config.options = NOKOGIRI_OPTIONS
1483
+ end
1484
+
1485
+ node_list = doc.xpath("/apps/app")
1486
+ attributes = ['id', 'icon', 'name', 'provisioned', 'extension_required', 'personal', 'login_id']
1487
+ apps = []
1488
+ node_list.each do |node|
1489
+ app_data = {}
1490
+ node.children.each do |children|
1491
+ if attributes.include? children.name
1492
+ app_data[children.name] = children.content
1493
+ end
1494
+ end
1495
+ apps << OneLogin::Api::Models::EmbedApp.new(app_data)
1496
+ end
1497
+
1498
+ apps
1499
+ end
1500
+
1501
+ end
1502
+ end
1503
+ end