oktakit 0.1.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,99 @@
1
+ module Oktakit
2
+ class Client
3
+ module Templates
4
+ # Add SMS Template
5
+ #
6
+ # @param options[:query] [Hash] Optional. Query params for request
7
+ # @param options[:headers] [Hash] Optional. Header params for the request.
8
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
9
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
10
+ # @param options [Hash] Optional. Body params for request.
11
+ # @return [Hash<Sawyer::Resource>] The created SMS Template.
12
+ # @see http://developer.okta.com/docs/api/resources/templates.html#add-sms-template
13
+ # @example
14
+ # Oktakit.add_sms_template
15
+ def add_sms_template(options = {})
16
+ post('/templates/sms', options)
17
+ end
18
+
19
+ # Get SMS Template
20
+ #
21
+ # @params id [string] Template ID
22
+ # @param options[:query] [Hash] Optional. Query params for request
23
+ # @param options[:headers] [Hash] Optional. Header params for the request.
24
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
25
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
26
+ # @param options [Hash] Optional. Body params for request.
27
+ # @return [Hash<Sawyer::Resource>] Fetched SMS Template
28
+ # @see http://developer.okta.com/docs/api/resources/templates.html#get-sms-template
29
+ # @example
30
+ # Oktakit.get_sms_template('id')
31
+ def get_sms_template(id, options = {})
32
+ get("/templates/sms/#{id}", options)
33
+ end
34
+
35
+ # List SMS Templates
36
+ #
37
+ # @param options[:query] [Hash] Optional. Query params for request
38
+ # @param options[:headers] [Hash] Optional. Header params for the request.
39
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
40
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
41
+ # @param options [Hash] Optional. Body params for request.
42
+ # @return [Array<Sawyer::Resource>] Array of SMS Template
43
+ # @see http://developer.okta.com/docs/api/resources/templates.html#list-sms-templates
44
+ # @example
45
+ # Oktakit.list_sms_templates
46
+ def list_sms_templates(options = {})
47
+ get('/templates/sms', options)
48
+ end
49
+
50
+ # Update Sms Template
51
+ #
52
+ # @params id [string] Template ID
53
+ # @param options[:query] [Hash] Optional. Query params for request
54
+ # @param options[:headers] [Hash] Optional. Header params for the request.
55
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
56
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
57
+ # @param options [Hash] Optional. Body params for request.
58
+ # @return [Hash<Sawyer::Resource>] Updated SMS Template
59
+ # @see http://developer.okta.com/docs/api/resources/templates.html#update-sms-template
60
+ # @example
61
+ # Oktakit.update_sms_template('id')
62
+ def update_sms_template(id, options = {})
63
+ put("/templates/sms/#{id}", options)
64
+ end
65
+
66
+ # Partial SMS Template Update
67
+ #
68
+ # @params id [string] Template ID
69
+ # @param options[:query] [Hash] Optional. Query params for request
70
+ # @param options[:headers] [Hash] Optional. Header params for the request.
71
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
72
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
73
+ # @param options [Hash] Optional. Body params for request.
74
+ # @return [Hash<Sawyer::Resource>] Updated Sms Template
75
+ # @see http://developer.okta.com/docs/api/resources/templates.html#partial-sms-template-update
76
+ # @example
77
+ # Oktakit.partial_sms_template_update('id')
78
+ def partial_sms_template_update(id, options = {})
79
+ post("/templates/sms/#{id}", options)
80
+ end
81
+
82
+ # Remove SMS Template
83
+ #
84
+ # @params id [string] Template ID
85
+ # @param options[:query] [Hash] Optional. Query params for request
86
+ # @param options[:headers] [Hash] Optional. Header params for the request.
87
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
88
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
89
+ # @param options [Hash] Optional. Body params for request.
90
+ # @return [Hash<Sawyer::Resource>] There is no content in the response.
91
+ # @see http://developer.okta.com/docs/api/resources/templates.html#remove-sms-template
92
+ # @example
93
+ # Oktakit.remove_sms_template('id')
94
+ def remove_sms_template(id, options = {})
95
+ delete("/templates/sms/#{id}", options)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,290 @@
1
+ module Oktakit
2
+ class Client
3
+ module Users
4
+ # Create User
5
+ #
6
+ # @param options[:query] [Hash] Optional. Query params for request
7
+ # @param options[:headers] [Hash] Optional. Header params for the request.
8
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
9
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
10
+ # @param options [Hash] Optional. Body params for request.
11
+ # @return [Hash<Sawyer::Resource>] Returns the created User.
12
+ # @see http://developer.okta.com/docs/api/resources/users.html#create-user
13
+ # @example
14
+ # Oktakit.create_user
15
+ def create_user(options = {})
16
+ post('/users', options)
17
+ end
18
+
19
+ # Get User
20
+ #
21
+ # @params id [string] User ID
22
+ # @param options[:query] [Hash] Optional. Query params for request
23
+ # @param options[:headers] [Hash] Optional. Header params for the request.
24
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
25
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
26
+ # @param options [Hash] Optional. Body params for request.
27
+ # @return [Hash<Sawyer::Resource>] Fetched User
28
+ # @see http://developer.okta.com/docs/api/resources/users.html#get-user
29
+ # @example
30
+ # Oktakit.get_user('id')
31
+ def get_user(id, options = {})
32
+ get("/users/#{id}", options)
33
+ end
34
+
35
+ # List Users
36
+ #
37
+ # @param options[:query] [Hash] Optional. Query params for request
38
+ # @param options[:headers] [Hash] Optional. Header params for the request.
39
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
40
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
41
+ # @param options [Hash] Optional. Body params for request.
42
+ # @return [Array<Sawyer::Resource>] Array of User
43
+ # @see http://developer.okta.com/docs/api/resources/users.html#list-users
44
+ # @example
45
+ # Oktakit.list_users
46
+ def list_users(options = {})
47
+ get('/users', options)
48
+ end
49
+
50
+ # Update User
51
+ #
52
+ # @params id [string] User ID
53
+ # @param options[:query] [Hash] Optional. Query params for request
54
+ # @param options[:headers] [Hash] Optional. Header params for the request.
55
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
56
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
57
+ # @param options [Hash] Optional. Body params for request.
58
+ # @return [Hash<Sawyer::Resource>] Updated User
59
+ # @see http://developer.okta.com/docs/api/resources/users.html#update-user
60
+ # @example
61
+ # Oktakit.update_user('id')
62
+ def update_user(id, options = {})
63
+ put("/users/#{id}", options)
64
+ end
65
+
66
+ # Update Profile
67
+ #
68
+ # @params id [string] User ID
69
+ # @param options[:query] [Hash] Optional. Query params for request
70
+ # @param options[:headers] [Hash] Optional. Header params for the request.
71
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
72
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
73
+ # @param options [Hash] Optional. Body params for request.
74
+ # @return [Hash<Sawyer::Resource>] Updated User
75
+ # @see http://developer.okta.com/docs/api/resources/users.html#update-profile
76
+ # @example
77
+ # Oktakit.update_profile('id')
78
+ def update_profile(id, options = {})
79
+ post("/users/#{id}", options)
80
+ end
81
+
82
+ # Get Assigned App Links
83
+ #
84
+ # @param options[:query] [Hash] Optional. Query params for request
85
+ # @param options[:headers] [Hash] Optional. Header params for the request.
86
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
87
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
88
+ # @param options [Hash] Optional. Body params for request.
89
+ # @return [Array<Sawyer::Resource>] Array of App Links
90
+ # @see http://developer.okta.com/docs/api/resources/users.html#get-assigned-app-links
91
+ # @example
92
+ # Oktakit.get_assigned_app_links('id')
93
+ def get_assigned_app_links(id, options = {})
94
+ get("/users/#{id}/appLinks", options)
95
+ end
96
+
97
+ # Get Member Groups
98
+ #
99
+ # @params id [string] User ID
100
+ # @param options[:query] [Hash] Optional. Query params for request
101
+ # @param options[:headers] [Hash] Optional. Header params for the request.
102
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
103
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
104
+ # @param options [Hash] Optional. Body params for request.
105
+ # @return [Array<Sawyer::Resource>] Array of Groups
106
+ # @see http://developer.okta.com/docs/api/resources/users.html#get-member-groups
107
+ # @example
108
+ # Oktakit.get_member_groups('id')
109
+ def get_member_groups(id, options = {})
110
+ get("/users/#{id}/groups", options)
111
+ end
112
+
113
+ # Activate User
114
+ #
115
+ # @params id [string] User ID
116
+ # @param options[:query] [Hash] Optional. Query params for request
117
+ # @param options[:headers] [Hash] Optional. Header params for the request.
118
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
119
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
120
+ # @param options [Hash] Optional. Body params for request.
121
+ # @return [Hash<Sawyer::Resource>] Returns empty object by default. When sendEmail is false, returns an activation link for the user to set up their account.
122
+ # @see http://developer.okta.com/docs/api/resources/users.html#activate-user
123
+ # @example
124
+ # Oktakit.activate_user('id')
125
+ def activate_user(id, options = {})
126
+ post("/users/#{id}/lifecycle/activate", options)
127
+ end
128
+
129
+ # Deactivate User
130
+ #
131
+ # @params id [string] User ID
132
+ # @param options[:query] [Hash] Optional. Query params for request
133
+ # @param options[:headers] [Hash] Optional. Header params for the request.
134
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
135
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
136
+ # @param options [Hash] Optional. Body params for request.
137
+ # @return [Hash<Sawyer::Resource>] Returns an empty object.
138
+ # @see http://developer.okta.com/docs/api/resources/users.html#deactivate-user
139
+ # @example
140
+ # Oktakit.deactivate_user('id')
141
+ def deactivate_user(id, options = {})
142
+ post("/users/#{id}/lifecycle/deactivate", options)
143
+ end
144
+
145
+ # Suspend User
146
+ #
147
+ # @params id [string] User ID
148
+ # @param options[:query] [Hash] Optional. Query params for request
149
+ # @param options[:headers] [Hash] Optional. Header params for the request.
150
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
151
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
152
+ # @param options [Hash] Optional. Body params for request.
153
+ # @return [Hash<Sawyer::Resource>] Returns an empty object.
154
+ # @see http://developer.okta.com/docs/api/resources/users.html#suspend-user
155
+ # @example
156
+ # Oktakit.suspend_user('id')
157
+ def suspend_user(id, options = {})
158
+ post("/users/#{id}/lifecycle/suspend", options)
159
+ end
160
+
161
+ # Unsuspend User
162
+ #
163
+ # @params id [string] User ID
164
+ # @param options[:query] [Hash] Optional. Query params for request
165
+ # @param options[:headers] [Hash] Optional. Header params for the request.
166
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
167
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
168
+ # @param options [Hash] Optional. Body params for request.
169
+ # @return [Hash<Sawyer::Resource>] Returns an empty object. Returns an empty object.
170
+ # @see http://developer.okta.com/docs/api/resources/users.html#unsuspend-user
171
+ # @example
172
+ # Oktakit.unsuspend_user('id')
173
+ def unsuspend_user(id, options = {})
174
+ post("/users/#{id}/lifecycle/unsuspend", options)
175
+ end
176
+
177
+ # Unlock User
178
+ #
179
+ # @params id [string] User ID
180
+ # @param options[:query] [Hash] Optional. Query params for request
181
+ # @param options[:headers] [Hash] Optional. Header params for the request.
182
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
183
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
184
+ # @param options [Hash] Optional. Body params for request.
185
+ # @return [Hash<Sawyer::Resource>] Returns an empty object
186
+ # @see http://developer.okta.com/docs/api/resources/users.html#unlock-user
187
+ # @example
188
+ # Oktakit.unlock_user('id')
189
+ def unlock_user(id, options = {})
190
+ post("/users/#{id}/lifecycle/unlock", options)
191
+ end
192
+
193
+ # Reset Password
194
+ #
195
+ # @params id [string] User ID
196
+ # @param options[:query] [Hash] Optional. Query params for request
197
+ # @param options[:headers] [Hash] Optional. Header params for the request.
198
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
199
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
200
+ # @param options [Hash] Optional. Body params for request.
201
+ # @return [Hash<Sawyer::Resource>] Returns an empty object by default. When sendEmail is false, returns a link for the user to reset their password.
202
+ # @see http://developer.okta.com/docs/api/resources/users.html#reset-password
203
+ # @example
204
+ # Oktakit.reset_password('id')
205
+ def reset_password(id, options = {})
206
+ post("/users/#{id}/lifecycle/reset_password", options)
207
+ end
208
+
209
+ # Expire Password
210
+ #
211
+ # @params id [string] User ID
212
+ # @param options[:query] [Hash] Optional. Query params for request
213
+ # @param options[:headers] [Hash] Optional. Header params for the request.
214
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
215
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
216
+ # @param options [Hash] Optional. Body params for request.
217
+ # @return [Hash<Sawyer::Resource>] Returns the complete user object by default. When tempPassword is true, returns the temporary password.
218
+ # @see http://developer.okta.com/docs/api/resources/users.html#expire-password
219
+ # @example
220
+ # Oktakit.expire_password('id')
221
+ def expire_password(id, options = {})
222
+ post("/users/#{id}/lifecycle/expire_password", options)
223
+ end
224
+
225
+ # Reset Factors
226
+ #
227
+ # @params id [string] User ID
228
+ # @param options[:query] [Hash] Optional. Query params for request
229
+ # @param options[:headers] [Hash] Optional. Header params for the request.
230
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
231
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
232
+ # @param options [Hash] Optional. Body params for request.
233
+ # @return [Hash<Sawyer::Resource>] Returns an empty object by default.
234
+ # @see http://developer.okta.com/docs/api/resources/users.html#reset-factors
235
+ # @example
236
+ # Oktakit.reset_factors('id')
237
+ def reset_factors(id, options = {})
238
+ post("/users/#{id}/lifecycle/reset_factors", options)
239
+ end
240
+
241
+ # Forgot Password
242
+ #
243
+ # @params id [string] User ID
244
+ # @param options[:query] [Hash] Optional. Query params for request
245
+ # @param options[:headers] [Hash] Optional. Header params for the request.
246
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
247
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
248
+ # @param options [Hash] Optional. Body params for request.
249
+ # @return [Hash<Sawyer::Resource>] Returns an empty object by default. When sendEmail is false, returns a link for the user to reset their password.
250
+ # @see http://developer.okta.com/docs/api/resources/users.html#forgot-password
251
+ # @example
252
+ # Oktakit.forgot_password('id')
253
+ def forgot_password(id, options = {})
254
+ post("/users/#{id}/credentials/forgot_password", options)
255
+ end
256
+
257
+ # Change Password
258
+ #
259
+ # @params id [string] User ID
260
+ # @param options[:query] [Hash] Optional. Query params for request
261
+ # @param options[:headers] [Hash] Optional. Header params for the request.
262
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
263
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
264
+ # @param options [Hash] Optional. Body params for request.
265
+ # @return [Hash<Sawyer::Resource>] Credentials of the user
266
+ # @see http://developer.okta.com/docs/api/resources/users.html#change-password
267
+ # @example
268
+ # Oktakit.change_password('id')
269
+ def change_password(id, options = {})
270
+ post("/users/#{id}/credentials/change_password", options)
271
+ end
272
+
273
+ # Change Recovery Question
274
+ #
275
+ # @params id [string] User ID
276
+ # @param options[:query] [Hash] Optional. Query params for request
277
+ # @param options[:headers] [Hash] Optional. Header params for the request.
278
+ # @param options[:accept] [String] Optional. The content type to accept. Default application/json
279
+ # @param options[:content_type] [String] Optional. The content type for the request. Default application/json
280
+ # @param options [Hash] Optional. Body params for request.
281
+ # @return [Hash<Sawyer::Resource>] Credentials of the user
282
+ # @see http://developer.okta.com/docs/api/resources/users.html#change-recovery-question
283
+ # @example
284
+ # Oktakit.change_recovery_question('id')
285
+ def change_recovery_question(id, options = {})
286
+ post("/users/#{id}/credentials/change_recovery_question", options)
287
+ end
288
+ end
289
+ end
290
+ end
@@ -0,0 +1,166 @@
1
+ module Oktakit
2
+ # Custom error class for rescuing from all Okta errors
3
+ class Error < StandardError
4
+ # Returns the appropriate Oktakit::Error subclass based
5
+ # on status and response message
6
+ #
7
+ # @param [Hash] response HTTP response
8
+ # @return [Oktakit::Error]
9
+ def self.from_response(response)
10
+ status = response[:status].to_i
11
+ if klass = case status
12
+ when 400 then Oktakit::BadRequest
13
+ when 401 then Oktakit::Unauthorized
14
+ when 403 then Oktakit::Forbidden
15
+ when 404 then Oktakit::NotFound
16
+ when 405 then Oktakit::MethodNotAllowed
17
+ when 406 then Oktakit::NotAcceptable
18
+ when 409 then Oktakit::Conflict
19
+ when 415 then Oktakit::UnsupportedMediaType
20
+ when 422 then Oktakit::UnprocessableEntity
21
+ when 400..499 then Oktakit::ClientError
22
+ when 500 then Oktakit::InternalServerError
23
+ when 501 then Oktakit::NotImplemented
24
+ when 502 then Oktakit::BadGateway
25
+ when 503 then Oktakit::ServiceUnavailable
26
+ when 500..599 then Oktakit::ServerError
27
+ end
28
+ klass.new(response)
29
+ end
30
+ end
31
+
32
+ def initialize(response = nil)
33
+ @response = response
34
+ super(build_error_message)
35
+ end
36
+
37
+ # Documentation URL returned by the API for some errors
38
+ #
39
+ # @return [String]
40
+ def documentation_url
41
+ data[:documentation_url] if data.is_a? Hash
42
+ end
43
+
44
+ # Array of validation errors
45
+ # @return [Array<Hash>] Error info
46
+ def errors
47
+ if data && data.is_a?(Hash)
48
+ data[:errors] || []
49
+ else
50
+ []
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def data
57
+ @data ||= parse_data
58
+ end
59
+
60
+ def parse_data
61
+ body = @response[:body]
62
+ return if body.empty?
63
+ return body unless body.is_a?(String)
64
+
65
+ headers = @response[:response_headers]
66
+ content_type = headers && headers[:content_type] || ''
67
+ if content_type =~ /json/
68
+ Sawyer::Agent.serializer.decode(body)
69
+ else
70
+ body
71
+ end
72
+ end
73
+
74
+ def response_message
75
+ case data
76
+ when Hash
77
+ data[:message]
78
+ when String
79
+ data
80
+ end
81
+ end
82
+
83
+ def response_error
84
+ "Error: #{data[:error]}" if data.is_a?(Hash) && data[:error]
85
+ end
86
+
87
+ def response_error_summary
88
+ return nil unless data.is_a?(Hash) && !Array(data[:errors]).empty?
89
+
90
+ summary = "\nError summary:\n"
91
+ summary << data[:errors].map do |hash|
92
+ hash.map { |k, v| " #{k}: #{v}" }
93
+ end.join("\n")
94
+
95
+ summary
96
+ end
97
+
98
+ def build_error_message
99
+ return nil if @response.nil?
100
+
101
+ message = "#{@response[:method].to_s.upcase} "
102
+ message << redact_url(@response[:url].to_s) + ': '
103
+ message << "#{@response[:status]} - "
104
+ message << response_message.to_s unless response_message.nil?
105
+ message << response_error.to_s unless response_error.nil?
106
+ message << response_error_summary.to_s unless response_error_summary.nil?
107
+ message << " // See: #{documentation_url}" unless documentation_url.nil?
108
+ message
109
+ end
110
+
111
+ def redact_url(url_string)
112
+ %w(client_secret access_token).each do |token|
113
+ url_string.gsub!(/#{token}=\S+/, "#{token}=(redacted)") if url_string.include? token
114
+ end
115
+ url_string
116
+ end
117
+ end
118
+
119
+ # Raised on errors in the 400-499 range
120
+ class ClientError < Error; end
121
+
122
+ # Raised when Okta returns a 400 HTTP status code
123
+ class BadRequest < ClientError; end
124
+
125
+ # Raised when Okta returns a 401 HTTP status code
126
+ class Unauthorized < ClientError; end
127
+
128
+ # Raised when Okta returns a 403 HTTP status code
129
+ class Forbidden < ClientError; end
130
+
131
+ # Raised when Okta returns a 404 HTTP status code
132
+ class NotFound < ClientError; end
133
+
134
+ # Raised when Okta returns a 405 HTTP status code
135
+ class MethodNotAllowed < ClientError; end
136
+
137
+ # Raised when Okta returns a 406 HTTP status code
138
+ class NotAcceptable < ClientError; end
139
+
140
+ # Raised when Okta returns a 409 HTTP status code
141
+ class Conflict < ClientError; end
142
+
143
+ # Raised when Okta returns a 414 HTTP status code
144
+ class UnsupportedMediaType < ClientError; end
145
+
146
+ # Raised when Okta returns a 422 HTTP status code
147
+ class UnprocessableEntity < ClientError; end
148
+
149
+ # Raised on errors in the 500-599 range
150
+ class ServerError < Error; end
151
+
152
+ # Raised when Okta returns a 500 HTTP status code
153
+ class InternalServerError < ServerError; end
154
+
155
+ # Raised when Okta returns a 501 HTTP status code
156
+ class NotImplemented < ServerError; end
157
+
158
+ # Raised when Okta returns a 502 HTTP status code
159
+ class BadGateway < ServerError; end
160
+
161
+ # Raised when Okta returns a 503 HTTP status code
162
+ class ServiceUnavailable < ServerError; end
163
+
164
+ # Raised when client fails to provide valid Content-Type
165
+ class MissingContentType < ArgumentError; end
166
+ end