onelogin 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b149586910635855872b58c39e17cecf82dbf489
4
- data.tar.gz: 1886b20c18c654706ba9b815187a1ab33bb9f5ab
3
+ metadata.gz: e2f3757a3f4b5a485045078f5e97498e20190ff9
4
+ data.tar.gz: c2175985e00c53f6fa83d27bbd666ea55dda977f
5
5
  SHA512:
6
- metadata.gz: 9786512a9794cdc1e267436ed1021d275ab05c147b4f80e01a5a6add0027abb12a9fac0148877cfe91ac099ce46c7d6e4ece02a25555ae0dfcbe51910b3dd054
7
- data.tar.gz: 2f5aa83177a386e77c256ad884e4bd1fbdcf945f7c42f32a82b6d09cbdb3abbc38404abbf6728137369784eb88f96077d3c58648ba7b2555ca1e5a13812edf00
6
+ metadata.gz: 4e4056a209d371b7566248766646fd442996b52ae530106b6b0fbe57885306b7f1ca981a4f1d94a6b726c6e7942970f21352b3148137ffe696fdeb107981ddbf
7
+ data.tar.gz: 6b2c498d6067207d8306c90dd65ff2cd6d6f78848a6e716b6f9ebdbf404eb19e1dc3870c6095e03ebe86708ff796bac5a25bf77620627014f64e45d89758f6cf
data/README.md CHANGED
@@ -235,6 +235,9 @@ apps = client.get_user_apps(user.id)
235
235
  # Get User Roles
236
236
  role_ids = client.get_user_roles(user.id)
237
237
 
238
+ # Generate MFA Token
239
+ mfa_token = client.generate_mfa_token(user.id)
240
+
238
241
  # Create user
239
242
  new_user_params = {
240
243
  email: "testcreate_1@example.com",
@@ -7,8 +7,6 @@ over the look & feel.
7
7
 
8
8
  The downside to this approach is that you have to implement MFA and password resets etc yourself. However we do have the APIs for these actions available and have demonstrated how to use them in this app.
9
9
 
10
- ![Custom Login](https://s3.amazonaws.com/onelogin-screenshots/dev_site/images/custom-login-os.gif)
11
-
12
10
  If you want a standards based, out of the box way to authenticate users then we recommend you use [our OpenId Connect implementation](https://github.com/onelogin/onelogin-oidc-ruby).
13
11
 
14
12
  ## Get Started
@@ -17,6 +15,9 @@ The sample tries to keep everything as simple as possible so only
17
15
  implements
18
16
  * Login - Authenticate users in a single request to OneLogin with out any redirects
19
17
  * MFA - Does MFA verification if required
18
+ * Password Reset with user verification via MFA
19
+ * Self sign Up / Create a new user
20
+ * Onboard / Activate a user
20
21
  * User Apps - List apps available to a user and provides SSO links
21
22
  * User Roles - Lists a users roles
22
23
  * Logout - destroying the local session and revoking the token at OneLogin
@@ -12,64 +12,4 @@
12
12
  *
13
13
  *= require_tree .
14
14
  *= require_self
15
- */
16
-
17
- body {
18
- padding: 20px;
19
- font-family: Arial, Helvetica, sans-serif
20
- }
21
-
22
- .alert, .error {
23
- color: red;
24
- text-align: center;
25
- }
26
-
27
- .row {
28
- padding: 5px 0px;
29
- }
30
-
31
- .row span {
32
- display: inline-block;
33
- font-weight: bold;
34
- }
35
-
36
- .form {
37
- width: 300px;
38
- margin: 0 auto;
39
- text-align: center;
40
- padding: 50px;
41
- background: green; /* For browsers that do not support gradients */
42
- background: -webkit-linear-gradient(left, orange , yellow, green, cyan, blue, violet); /* For Safari 5.1 to 6.0 */
43
- background: -o-linear-gradient(right, orange, yellow, green, cyan, blue, violet); /* For Opera 11.1 to 12.0 */
44
- background: -moz-linear-gradient(right, orange, yellow, green, cyan, blue, violet); /* For Firefox 3.6 to 15 */
45
- background: linear-gradient(to right, orange , yellow, green, cyan, blue, violet); /* Standard syntax (must be last) */
46
- }
47
-
48
- .form input {
49
- width: 90%;
50
- padding: 5px;
51
- margin: 5px;
52
- }
53
-
54
- .form h1 {
55
- color: #fff;
56
- }
57
-
58
- .login-footer {
59
- width: 300px;
60
- margin: 50px auto;
61
- text-align: center;
62
- }
63
-
64
- form.edit div {
65
- padding: 10px;
66
- }
67
-
68
- table.list {
69
- width: 100%;
70
- }
71
-
72
- table.list tr td {
73
- padding: 5px;
74
- border-bottom: 1px #ccc solid;
75
- }
15
+ */
@@ -1,7 +1,7 @@
1
1
  class SessionsController < ApplicationController
2
2
  def new
3
3
  response = log_in(params['username'], params['password'])
4
- status = response ? :ok : :unauthorized
4
+ status = response[:error] ? :unauthorized : :ok
5
5
 
6
6
  render json: response, status: status
7
7
  end
@@ -17,7 +17,7 @@ class SessionsController < ApplicationController
17
17
  # available to verify token before
18
18
  # password reset is completed
19
19
  def forgot_password
20
- user = validate_user(params['username'])
20
+ user = validate_user(params['forgot_username'])
21
21
 
22
22
  devices = get_mfa_devices(user.id)
23
23
 
@@ -28,9 +28,9 @@ class SessionsController < ApplicationController
28
28
 
29
29
  # Verify MFA token and then update password
30
30
  def reset_password
31
- if verify_token(params['device_id'], params['otp_token'])
31
+ if verify_token(params['reset_device_id'], params['reset_otp_token'])
32
32
  status = :ok
33
- response = set_password(session[:user_id], params['password'])
33
+ response = set_password(session[:user_id], params['new_password'])
34
34
  else
35
35
  status = :unauthorized
36
36
  response = 'Invalid token'
@@ -1,6 +1,6 @@
1
1
  class UsersController < ApplicationController
2
2
 
3
- before_action :require_current_user
3
+ before_action :require_current_user, except: [:new, :create, :onboard, :activate]
4
4
  before_action :set_user, only: [:show, :edit, :update, :destroy]
5
5
 
6
6
  # GET /users
@@ -16,7 +16,6 @@ class UsersController < ApplicationController
16
16
 
17
17
  # GET /users/new
18
18
  def new
19
- @user = User.new
20
19
  end
21
20
 
22
21
  # GET /users/1/edit
@@ -26,17 +25,52 @@ class UsersController < ApplicationController
26
25
  # POST /users
27
26
  # POST /users.json
28
27
  def create
29
- @user = User.new(user_params)
28
+ # Create a user
29
+ user = api_client.create_user(user_params)
30
+ # Update custom attributes
31
+ api_client.set_custom_attribute_to_user(user.id, custom_user_params)
32
+ # Set status to unactivated
33
+ api_client.update_user(user.id, status: 0)
30
34
 
31
- respond_to do |format|
32
- if @user.save
33
- format.html { redirect_to @user, notice: 'User was successfully created.' }
34
- format.json { render :show, status: :created, location: @user }
35
- else
36
- format.html { render :new }
37
- format.json { render json: @user.errors, status: :unprocessable_entity }
38
- end
35
+ if api_client.error
36
+ puts api_client.error_description
37
+ end
38
+
39
+ redirect_to onboard_path, notice: 'User has been created with status set to unactivated'
40
+ end
41
+
42
+ # GET /onboard
43
+ def onboard
44
+ end
45
+
46
+ # POST /activate
47
+ def activate
48
+ # Search for a user with this email address
49
+ @user = api_client.get_users(email: user_params[:email]).first
50
+
51
+ unless @user && verify_dob && verify_ssn
52
+ return redirect_to onboard_path, notice: "User #{user_params[:email]} was not verified"
53
+ end
54
+
55
+ # Update password
56
+ unless api_client.set_password_using_clear_text(@user.id, user_params[:password], user_params[:password])
57
+ return redirect_to onboard_path, notice: "Password update failed. #{api_client.error_description}"
39
58
  end
59
+
60
+ # Activate user
61
+ api_client.update_user(@user.id, status: 1)
62
+
63
+ # Redirect to login page
64
+ redirect_to home_index_path
65
+ end
66
+
67
+ # Verify dob and ssn match
68
+ def verify_ssn
69
+ @user.custom_attributes["custom_ssn"].eql? (custom_user_params[:custom_ssn])
70
+ end
71
+
72
+ def verify_dob
73
+ @user.custom_attributes["custom_dob"].eql? (custom_user_params[:custom_dob])
40
74
  end
41
75
 
42
76
  # PATCH/PUT /users/1
@@ -70,17 +104,13 @@ class UsersController < ApplicationController
70
104
  end
71
105
 
72
106
  private
73
- # Use callbacks to share common setup or constraints between actions.
74
- def set_user
75
- @user = api_client.get_user(params[:id])
76
- end
77
107
 
78
108
  # Never trust parameters from the scary internet, only allow the white list through.
79
109
  def user_params
80
- params.permit(:firstname, :lastname, :email, :phone, :custom_field)
110
+ params.permit(:firstname, :lastname, :email, :phone, :custom_field, :username, :password)
81
111
  end
82
112
 
83
113
  def custom_user_params
84
- params.permit(:custom_field)
114
+ params.permit(:custom_field, :custom_dob, :custom_ssn)
85
115
  end
86
116
  end
@@ -8,7 +8,7 @@ module SessionsHelper
8
8
  },
9
9
  request.base_url # included for CORS session cookie request
10
10
  )
11
- return nil unless response
11
+ return { error: api_client.error_description } unless response
12
12
 
13
13
  if response.is_a? OneLogin::Api::Models::SessionTokenMFAInfo
14
14
  session[:state_token] = response.state_token
@@ -1,2 +1,3 @@
1
1
  module UsersHelper
2
+
2
3
  end
@@ -20,7 +20,9 @@
20
20
  <label for="password">Password</label>
21
21
  <%= password_field_tag :password, nil, placeholder: 'Enter Password', class: 'form-control' %>
22
22
  </div>
23
- <button type="submit" class="btn btn-primary">Login</button> or <a href="#" class="forgot">Forgot Password</a>
23
+ <button type="submit" class="btn btn-primary">Login</button>
24
+ <hr/>
25
+ <a href="#" class="forgot">Forgot Password</a> | <a href="/signup">Sign Up</a>
24
26
  <% end %>
25
27
 
26
28
  <%= form_tag("/verify_mfa", method: "post", class: 'mfa-form') do %>
@@ -37,24 +39,24 @@
37
39
 
38
40
  <%= form_tag("/forgot_password", method: "post", class: 'forgot-password-form') do %>
39
41
  <div class="form-group">
40
- <label for="username">Username</label>
41
- <%= text_field_tag :username, nil, placeholder: 'Enter Username', class: 'form-control' %>
42
+ <label for="forgot_username">Username</label>
43
+ <%= text_field_tag :forgot_username, nil, placeholder: 'Enter Username', class: 'form-control' %>
42
44
  </div>
43
45
  <button type="submit" class="btn btn-primary">Reset Password</button> or <a href="/">Login</a>
44
46
  <% end %>
45
47
 
46
48
  <%= form_tag("/reset_password", method: "post", class: 'reset-password-form') do %>
47
49
  <div class="form-group">
48
- <label for="device_id">MFA Device</label>
49
- <%= select_tag :device_id, nil, {:class => 'form-control'} %>
50
+ <label for="reset_device_id">MFA Device</label>
51
+ <%= select_tag :reset_device_id, nil, {:class => 'form-control'} %>
50
52
  </div>
51
53
  <div class="form-group">
52
- <label for="otp_token">Token</label>
53
- <%= text_field_tag :otp_token, nil, placeholder: 'Enter Token', class: 'form-control' %>
54
+ <label for="reset_otp_token">Token</label>
55
+ <%= text_field_tag :reset_otp_token, nil, placeholder: 'Enter Token', class: 'form-control' %>
54
56
  </div>
55
57
  <div class="form-group">
56
- <label for="password">New Password</label>
57
- <%= password_field_tag :password, nil, placeholder: 'Enter New Password', class: 'form-control' %>
58
+ <label for="new_password">New Password</label>
59
+ <%= password_field_tag :new_password, nil, placeholder: 'Enter New Password', class: 'form-control' %>
58
60
  </div>
59
61
  <button type="submit" class="btn btn-primary">Save Password</button>
60
62
  <% end %>
@@ -129,7 +131,8 @@
129
131
  },
130
132
  error: function(xhr, status, err) {
131
133
  console.log(err);
132
- showAlert('danger','Login Failed');
134
+ console.log(xhr);
135
+ showAlert('danger', xhr.responseJSON.error);
133
136
  $(".login-form input[type=submit]").removeAttr("disabled");
134
137
  },
135
138
  });
@@ -10,8 +10,20 @@
10
10
  </head>
11
11
 
12
12
  <body>
13
+ <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
14
+ <a class="navbar-brand" href="#">OneLogin Ruby SDK Sample</a>
15
+ <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
16
+ <div class="navbar-nav">
17
+ <a class="nav-item nav-link active" href="/">Login</a>
18
+ <a class="nav-item nav-link" href="/signup">Sign Up</a>
19
+ <a class="nav-item nav-link" href="/onboard">Onboard</a>
20
+ </div>
21
+ </div>
22
+ </nav>
23
+
24
+
13
25
  <% flash.each do |key, value| %>
14
- <div class="alert alert-<%= key %>"><%= value %></div>
26
+ <div class="alert alert-warning"><%= value %></div>
15
27
  <% end %>
16
28
 
17
29
  <%= yield %>
@@ -1,5 +1,60 @@
1
- <h1>New User</h1>
1
+ <div class="jumbotron">
2
+ <p>This is a simple demo of how to sign up a new user and then make them activate their account</p>
3
+ </div>
2
4
 
3
- <%= render 'form', user: @user %>
5
+ <div class="container">
6
+ <div class="row">
7
+ <div class="col-sm">
8
+ </div>
9
+ <div class="col-sm">
4
10
 
5
- <%= link_to 'Back', users_path %>
11
+ <div class="alert alert-danger message" role="alert">
12
+ </div>
13
+
14
+ <%= form_tag("/users", method: "post", class: 'signup-form') do %>
15
+ <div class="form-group">
16
+ <label for="firstname">First Name</label>
17
+ <%= text_field_tag :firstname, nil, placeholder: 'First Name', class: 'form-control' %>
18
+ </div>
19
+ <div class="form-group">
20
+ <label for="lastname">Last Name</label>
21
+ <%= text_field_tag :lastname, nil, placeholder: 'Last Name', class: 'form-control' %>
22
+ </div>
23
+ <div class="form-group">
24
+ <label for="email">Email</label>
25
+ <%= text_field_tag :email, nil, placeholder: 'Email Address', class: 'form-control' %>
26
+ </div>
27
+ <div class="form-group">
28
+ <label for="custom_dob">Date of Birth</label>
29
+ <%= text_field_tag :custom_dob, nil, placeholder: 'mm/dd/yyyy', class: 'form-control' %>
30
+ </div>
31
+ <div class="form-group">
32
+ <label for="custom_ssn">Last 4 of SSN</label>
33
+ <%= text_field_tag :custom_ssn, nil, placeholder: 'Last 4 of SSN', class: 'form-control' %>
34
+ </div>
35
+ <button type="submit" class="btn btn-primary">Sign Up</button>
36
+ <hr/>
37
+ <a href="/">Login</a>
38
+ <% end %>
39
+
40
+ </div>
41
+ <div class="col-sm">
42
+ </div>
43
+ </div>
44
+ </div>
45
+
46
+
47
+ <script type="text/javascript">
48
+ function showAlert(type, message){
49
+ $(".message").removeClass("alert-danger").removeClass("alert-success");
50
+ $(".message").addClass("alert-" + type).text(message).show();
51
+ $(".message").show();
52
+ }
53
+ function hideAlert(){
54
+ $(".message").hide();
55
+ }
56
+
57
+ $(function(){
58
+ hideAlert();
59
+ })
60
+ </script>
@@ -0,0 +1,54 @@
1
+ <div class="jumbotron">
2
+ <p>This shows how an unactivated user could supply infomation to complete a sign up flow</p>
3
+ </div>
4
+
5
+ <div class="container">
6
+ <div class="row">
7
+ <div class="col-sm">
8
+ </div>
9
+ <div class="col-sm">
10
+
11
+ <div class="alert alert-danger message" role="alert">
12
+ </div>
13
+
14
+ <%= form_tag("/activate", method: "post", class: 'signup-form') do %>
15
+ <div class="form-group">
16
+ <label for="email">Email</label>
17
+ <%= text_field_tag :email, nil, placeholder: 'Email Address', class: 'form-control' %>
18
+ </div>
19
+ <div class="form-group">
20
+ <label for="custom_dob">Date of Birth</label>
21
+ <%= text_field_tag :custom_dob, nil, placeholder: 'mm/dd/yyyy', class: 'form-control' %>
22
+ </div>
23
+ <div class="form-group">
24
+ <label for="custom_ssn">Last 4 of SSN</label>
25
+ <%= text_field_tag :custom_ssn, nil, placeholder: 'Last 4 of SSN', class: 'form-control' %>
26
+ </div>
27
+ <div class="form-group">
28
+ <label for="password">Password</label>
29
+ <%= password_field_tag :password, nil, placeholder: 'Make up a password', class: 'form-control' %>
30
+ </div>
31
+ <button type="submit" class="btn btn-primary">Activate Account</button>
32
+ <% end %>
33
+
34
+ </div>
35
+ <div class="col-sm">
36
+ </div>
37
+ </div>
38
+ </div>
39
+
40
+
41
+ <script type="text/javascript">
42
+ function showAlert(type, message){
43
+ $(".message").removeClass("alert-danger").removeClass("alert-success");
44
+ $(".message").addClass("alert-" + type).text(message).show();
45
+ $(".message").show();
46
+ }
47
+ function hideAlert(){
48
+ $(".message").hide();
49
+ }
50
+
51
+ $(function(){
52
+ hideAlert();
53
+ })
54
+ </script>
@@ -11,6 +11,10 @@ Rails.application.routes.draw do
11
11
 
12
12
  get 'users', to: 'users#index'
13
13
  get 'users/:id', to: 'users#show', as: 'user'
14
+ get 'signup', to: 'users#new'
15
+ get 'onboard', to: 'users#onboard'
16
+ post 'users', to: 'users#create'
17
+ post 'activate', to: 'users#activate'
14
18
  get 'users/:id/edit', to: 'users#edit', as: 'edit_user'
15
19
  patch 'users/:id', to: 'users#update', as: 'update_user'
16
20
 
@@ -941,6 +941,52 @@ module OneLogin
941
941
  false
942
942
  end
943
943
 
944
+ # Use to generate a temporary MFA token that can be used in place of other MFA tokens for a set time period.
945
+ # For example, use this token for account recovery.
946
+ #
947
+ # @param user_id [Integer] Id of the user
948
+ # @param expires_in [Integer] Set the duration of the token in seconds.
949
+ # (default: 259200 seconds = 72h) 72 hours is the max value.
950
+ # @param reusable [Boolean] Defines if the token reusable. (default: false) If set to true, token can be used for multiple apps, until it expires.
951
+ #
952
+ # @return [MFAToken] if the action succeed
953
+ #
954
+ # @see {https://developers.onelogin.com/api-docs/1/multi-factor-authentication/generate-mfa-token Generate MFA Token documentation}
955
+ def generate_mfa_token(user_id, expires_in=259200, reusable=False)
956
+ clean_error
957
+ prepare_token
958
+
959
+ begin
960
+ url = url_for(GENERATE_MFA_TOKEN_URL, user_id)
961
+
962
+ data = {
963
+ 'expires_in' => expires_in,
964
+ 'reusable' => reusable
965
+ }
966
+
967
+ response = self.class.post(
968
+ url,
969
+ headers: authorized_headers,
970
+ body: data.to_json
971
+ )
972
+
973
+ if response.code == 201
974
+ json_data = JSON.parse(response.body)
975
+ if !json_data.empty?
976
+ return OneLogin::Api::Models::MFAToken.new(json_data)
977
+ end
978
+ else
979
+ @error = extract_status_code_from_response(response)
980
+ @error_description = extract_error_message_from_response(response)
981
+ end
982
+ rescue Exception => e
983
+ @error = '500'
984
+ @error_description = e.message
985
+ end
986
+
987
+ nil
988
+ end
989
+
944
990
  # Generates a session login token in scenarios in which MFA may or may not be required.
945
991
  # A session login token expires two minutes after creation.
946
992
  #
@@ -6,6 +6,7 @@ require 'onelogin/api/models/event_type'
6
6
  require 'onelogin/api/models/factor_enrollment_response'
7
7
  require 'onelogin/api/models/group'
8
8
  require 'onelogin/api/models/mfa'
9
+ require 'onelogin/api/models/mfa_token'
9
10
  require 'onelogin/api/models/onelogin_token'
10
11
  require 'onelogin/api/models/otp_device'
11
12
  require 'onelogin/api/models/privilege'
@@ -0,0 +1,18 @@
1
+ module OneLogin
2
+ module Api
3
+ module Models
4
+
5
+ class MFAToken
6
+
7
+ attr_accessor :value, :expires_at, :reusable
8
+
9
+ def initialize(data)
10
+ @value = data['mfa_token']
11
+ @expires_at = data['expires_at']
12
+ @reusable = data['reusable']
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -32,6 +32,7 @@ module OneLogin
32
32
  SET_USER_STATE_URL = "https://api.%s.onelogin.com/api/1/users/%s/set_state"
33
33
  LOG_USER_OUT_URL = "https://api.%s.onelogin.com/api/1/users/%s/logout"
34
34
  LOCK_USER_URL = "https://api.%s.onelogin.com/api/1/users/%s/lock_user"
35
+ GENERATE_MFA_TOKEN_URL = "https://api.%s.onelogin.com/api/1/users/%s/mfa_token"
35
36
 
36
37
  # Role URLs
37
38
  GET_ROLES_URL = "https://api.%s.onelogin.com/api/1/roles"
@@ -1,3 +1,3 @@
1
1
  module OneLogin
2
- VERSION = "1.3.1"
2
+ VERSION = "1.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onelogin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OneLogin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-29 00:00:00.000000000 Z
11
+ date: 2019-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -153,6 +153,7 @@ files:
153
153
  - examples/rails-custom-login-page/app/views/users/index.html.erb
154
154
  - examples/rails-custom-login-page/app/views/users/index.json.jbuilder
155
155
  - examples/rails-custom-login-page/app/views/users/new.html.erb
156
+ - examples/rails-custom-login-page/app/views/users/onboard.html.erb
156
157
  - examples/rails-custom-login-page/app/views/users/show.html.erb
157
158
  - examples/rails-custom-login-page/app/views/users/show.json.jbuilder
158
159
  - examples/rails-custom-login-page/bin/bundle
@@ -226,6 +227,7 @@ files:
226
227
  - lib/onelogin/api/models/factor_enrollment_response.rb
227
228
  - lib/onelogin/api/models/group.rb
228
229
  - lib/onelogin/api/models/mfa.rb
230
+ - lib/onelogin/api/models/mfa_token.rb
229
231
  - lib/onelogin/api/models/onelogin_token.rb
230
232
  - lib/onelogin/api/models/otp_device.rb
231
233
  - lib/onelogin/api/models/privilege.rb
@@ -265,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
265
267
  version: '0'
266
268
  requirements: []
267
269
  rubyforge_project: http://www.rubygems.org/gems/onelogin-ruby-sdk
268
- rubygems_version: 2.2.2
270
+ rubygems_version: 2.4.8
269
271
  signing_key:
270
272
  specification_version: 4
271
273
  summary: OneLogin's Ruby SDK.