onelogin 0.1.0 → 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.
@@ -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