oktakit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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