Class: Windoo::Connection::Token

Inherits:
Object
  • Object
show all
Defined in:
lib/windoo/connection/token.rb

Overview

A token used for a connection to the Title Editor API

Constant Summary collapse

AUTH_RSRC =
'auth'
NEW_TOKEN_RSRC =
"#{AUTH_RSRC}/tokens"
REFRESH_RSRC =
"#{AUTH_RSRC}/keepalive"
CURRENT_STATUS_RSRC =
"#{AUTH_RSRC}/current"
REFRESH_BUFFER =

Seconds before expiration that the token will automatically refresh

300
REFRESH_RESULTS =

Used bu the last_refresh_result method

{
  refreshed: 'Refreshed',
  refreshed_pw: 'Refresh failed, but new token created with cached pw',
  refresh_failed: 'Refresh failed, could not create new token with cached pw',
  refresh_failed_no_pw_fallback: 'Refresh failed, but pw_fallback was false',
  expired_refreshed: 'Expired, but new token created with cached pw',
  expired_failed: 'Expired, could not create new token with cached pw',
  expired_no_pw_fallback: 'Expired, but pw_fallback was false'
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**params) ⇒ Token

Returns a new instance of Token.

Parameters:

  • params (Hash)

    The data for creating and maintaining the token

Options Hash (**params):

  • base_url: (String, URI)

    The url for the Jamf Pro server including host and port, e.g. ‘yourserver.appcatalog.jamfcloud.com

  • user: (String) — default: see Connection#initialize
  • token_string: (String)

    An existing valid token string. If provided, no need to provide ‘user’, which will be read from the server. If pw_fallback is true (the default) you will also need to provide the password for the user who created the token in the pw: parameter. If you don’t, pw_fallback will be false even if you set it to true explicitly.

  • pw: (String) — default: see Connection#initialize
  • timeout: (Integer)

    The http timeout for communication with the server. This is only used for token-related communication, not general API usage, and so need not be the same as that for the connection that uses this token.

  • keep_alive: (Boolean) — default: see Connection#connect
  • pw_fallback: (Boolean) — default: see Connection#connect
  • ssl_version: (String, Symbol) — default: see Connection#connect
  • verify_cert: (Boolean) — default: see Connection#connect


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/windoo/connection/token.rb', line 133

def initialize(**params)
  @valid = false
  parse_params(**params)

  if params[:token_string]
    @pw_fallback = false unless @pw
    @creation_http_response = init_from_token_string params[:token_string]

  elsif @user && @pw
    @creation_http_response = init_from_pw

  else
    raise ArgumentError, 'Must provide either user: & pw: or token_string:'
  end

  start_keep_alive if @keep_alive
  @creation_time = Time.now
end

Instance Attribute Details

#base_urlURI (readonly)

Returns The base API url, e.g. yourserver.appcatalog.jamfcloud.com.

Returns:



64
65
66
# File 'lib/windoo/connection/token.rb', line 64

def base_url
  @base_url
end

#creation_http_responseFaraday::Response (readonly)

Returns The response object from instantiating a new Token object by creating a new token or validating a token string. This is not updated when refreshing a token, only when calling Token.new.

Returns:

  • (Faraday::Response)

    The response object from instantiating a new Token object by creating a new token or validating a token string. This is not updated when refreshing a token, only when calling Token.new



91
92
93
# File 'lib/windoo/connection/token.rb', line 91

def creation_http_response
  @creation_http_response
end

#creation_timeTime (readonly) Also known as: login_time

Returns when was this Windoo::TitleServer::Connection::Token originally created?.

Returns:

  • (Time)

    when was this Windoo::TitleServer::Connection::Token originally created?



67
68
69
# File 'lib/windoo/connection/token.rb', line 67

def creation_time
  @creation_time
end

#domainString (readonly)

Returns The fully qualified hostname of the server that generated this token.

Returns:

  • (String)

    The fully qualified hostname of the server that generated this token



102
103
104
# File 'lib/windoo/connection/token.rb', line 102

def domain
  @domain
end

#expiresTime (readonly) Also known as: expiration

Returns:

  • (Time)


74
75
76
# File 'lib/windoo/connection/token.rb', line 74

def expires
  @expires
end

#keep_aliveBoolean (readonly) Also known as: keep_alive?

Returns does this token automatically refresh itself before expiring?.

Returns:

  • (Boolean)

    does this token automatically refresh itself before expiring?



79
80
81
# File 'lib/windoo/connection/token.rb', line 79

def keep_alive
  @keep_alive
end

#last_refreshTime (readonly)

Returns when was this token last refreshed?.

Returns:

  • (Time)

    when was this token last refreshed?



71
72
73
# File 'lib/windoo/connection/token.rb', line 71

def last_refresh
  @last_refresh
end

#pw_fallbackBoolean (readonly) Also known as: pw_fallback?

Returns Should the provided passwd be cached in memory, to be used to generate a new token, if a normal refresh fails?.

Returns:

  • (Boolean)

    Should the provided passwd be cached in memory, to be used to generate a new token, if a normal refresh fails?



84
85
86
# File 'lib/windoo/connection/token.rb', line 84

def pw_fallback
  @pw_fallback
end

#scopeArray<String> (readonly) Also known as: permissions

Returns The permissions of the @user.

Returns:

  • (Array<String>)

    The permissions of the @user



45
46
47
# File 'lib/windoo/connection/token.rb', line 45

def scope
  @scope
end

#server_creation_timeTime (readonly)

Returns The time the server created the token.

Returns:

  • (Time)

    The time the server created the token



94
95
96
# File 'lib/windoo/connection/token.rb', line 94

def server_creation_time
  @server_creation_time
end

#ssl_optionsHash (readonly)

Returns the ssl version and verify cert, to pass into faraday connections.

Returns:

  • (Hash)

    the ssl version and verify cert, to pass into faraday connections



56
57
58
# File 'lib/windoo/connection/token.rb', line 56

def ssl_options
  @ssl_options
end

#ssl_versionString (readonly)

Returns the SSL version being used.

Returns:

  • (String)

    the SSL version being used



49
50
51
# File 'lib/windoo/connection/token.rb', line 49

def ssl_version
  @ssl_version
end

#tenantIdString (readonly) Also known as: tenant_id

Returns The tenantID of this server connection.

Returns:

  • (String)

    The tenantID of this server connection



97
98
99
# File 'lib/windoo/connection/token.rb', line 97

def tenantId
  @tenantId
end

#tokenString (readonly) Also known as: token_string, auth_token

Returns The token data.

Returns:

  • (String)

    The token data



59
60
61
# File 'lib/windoo/connection/token.rb', line 59

def token
  @token
end

#userString (readonly)

Returns The user who generated this token.

Returns:

  • (String)

    The user who generated this token



39
40
41
# File 'lib/windoo/connection/token.rb', line 39

def user
  @user
end

#user_idInteger (readonly)

Returns The user id of the @user on the server.

Returns:

  • (Integer)

    The user id of the @user on the server



42
43
44
# File 'lib/windoo/connection/token.rb', line 42

def user_id
  @user_id
end

#verify_certBoolean (readonly) Also known as: verify_cert?

Returns are we verifying SSL certs?.

Returns:

  • (Boolean)

    are we verifying SSL certs?



52
53
54
# File 'lib/windoo/connection/token.rb', line 52

def verify_cert
  @verify_cert
end

Instance Method Details

#disconnectvoid

This method returns an undefined value.

Invalidate this token by stopping any keepalive thread and setting most values to nil or :disconnected



380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/windoo/connection/token.rb', line 380

def disconnect
  stop_keep_alive
  @token = nil
  @pw = nil
  @pw_fallback = nil
  @keep_alive = nil
  @creation_http_response = nil
  @expires = Time.now
  @scope = nil
  @user = :disconnected
  @user_id = 0
  @valid = false
  @domain = :disconnected
  @tenantId = :disconnected
end

#expired?Boolean

Returns:

  • (Boolean)


209
210
211
212
213
# File 'lib/windoo/connection/token.rb', line 209

def expired?
  return unless @expires

  Time.now >= @expires
end

#hostObject



197
198
199
# File 'lib/windoo/connection/token.rb', line 197

def host
  base_url.host
end

#init_from_pwFaraday::Response

Initialize from password

Returns:

  • (Faraday::Response)

    the response from checking the status, which might be used to set @creation_http_response



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/windoo/connection/token.rb', line 156

def init_from_pw
  resp = token_connection(NEW_TOKEN_RSRC).post

  if resp.success?
    @token = resp.body[:token]
    parse_token_status
    @last_refresh = Time.now
    resp
  elsif resp.status == 401
    raise Windoo::AuthenticationError, 'Incorrect user name or password'
  else
    # TODO: better error reporting here
    puts
    puts resp.status
    puts resp.body
    puts
    raise Windoo::ConnectionError, "An error occurred while authenticating: #{resp.body}"
  end
ensure
  @pw = nil unless @pw_fallback
end

#init_from_token_string(str) ⇒ Faraday::Response

Initialize from token string

Returns:

  • (Faraday::Response)

    the response from checking the status, which might be used to set @creation_http_response



182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/windoo/connection/token.rb', line 182

def init_from_token_string(str)
  @token = str
  parse_token_status

  # we now know the @user who created the token string.
  # if we were given a pw and expect to use it, call init_from_pw
  # to validate it by getting a fresh token
  return init_from_pw if @pw && @pw_fallback

  # use this token to get a fresh one with the full
  # 15 min lifespan
  refresh
end

#invalidateObject Also known as: destroy

Make this token invalid



324
325
326
327
328
329
# File 'lib/windoo/connection/token.rb', line 324

def invalidate
  stop_keep_alive
  @valid = false
  @token = nil
  @pw = nil
end

#last_refresh_resultString?

What happened the last time we tried to refresh? See REFRESH_RESULTS

Returns:

  • (String, nil)

    result or nil if never refreshed



279
280
281
# File 'lib/windoo/connection/token.rb', line 279

def last_refresh_result
  REFRESH_RESULTS[@last_refresh_result]
end

#next_refreshTime?

when is the next rerefresh going to happen, if we are set to keep alive?

Returns:

  • (Time, nil)

    the time of the next scheduled refresh, or nil if not keep_alive?



218
219
220
221
222
# File 'lib/windoo/connection/token.rb', line 218

def next_refresh
  return unless keep_alive?

  @expires - REFRESH_BUFFER
end

#portInteger

Returns:

  • (Integer)


203
204
205
# File 'lib/windoo/connection/token.rb', line 203

def port
  base_url.port
end

#refreshFaraday::Response

Use this token to get a fresh one. If a pw is provided try to use it to get a new token if a proper refresh fails.

Parameters:

  • pw (String)

    Optional password to use if token refresh fails. Must be the correct passwd or the token’s user (obviously)

Returns:

  • (Faraday::Response)

    the response from checking the status, which might be used to set @creation_http_response

Raises:



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/windoo/connection/token.rb', line 293

def refresh
  # already expired?
  if expired?
    # try the passwd if we have it
    return refresh_with_pw(:expired_refreshed, :expired_failed) if @pw

    # no passwd fallback? no chance!
    @last_refresh_result = :expired_no_pw_fallback
    raise Windoo::InvalidTokenError, 'Token has expired'
  end

  # Now try a normal refresh of our non-expired token
  refresh_resp = token_connection(REFRESH_RSRC, token: token).post

  if refresh_resp.success?
    @token = refresh_resp.body[:token]
    parse_token_status
    @last_refresh = Time.now
    return refresh_resp
  end

  # if we're here, the normal refresh failed, so try the pw
  return refresh_with_pw(:refreshed_pw, :refresh_failed) if @pw

  # if we're here, no pw = no chance!
  @last_refresh_result = :refresh_failed_no_pw_fallback
  raise Windoo::InvalidTokenError, 'An error occurred while refreshing the token'
end

#secs_remainingFloat

Returns:

  • (Float)


247
248
249
250
251
# File 'lib/windoo/connection/token.rb', line 247

def secs_remaining
  return unless @expires

  @expires - Time.now
end

#secs_to_refreshFloat?

how many secs until the next refresh? will return 0 during the actual refresh process.

Returns:

  • (Float, nil)

    Seconds until the next scheduled refresh, or nil if not keep_alive?



229
230
231
232
233
234
# File 'lib/windoo/connection/token.rb', line 229

def secs_to_refresh
  return unless keep_alive?

  secs = next_refresh - Time.now
  secs.negative? ? 0 : secs
end

#start_keep_alivevoid

This method returns an undefined value.

creates a thread that loops forever, sleeping most of the time, but waking up every 60 seconds to see if the token is expiring in the next REFRESH_BUFFER seconds.

If so, the token is refreshed, and we keep looping and sleeping.

Sets @keep_alive_thread to the Thread object



342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/windoo/connection/token.rb', line 342

def start_keep_alive
  return if @keep_alive_thread
  raise 'Token expired, cannot refresh' if expired?

  @keep_alive_thread =
    Thread.new do
      loop do
        sleep 60
        begin
          next if secs_remaining > REFRESH_BUFFER

          refresh
        rescue StandardError
          # TODO: Some kind of error reporting
          next
        end
      end # loop
    end # thread
  @keep_alive_thread.name = "Windoo keep_alive #{tenantId} (#{@login_time})"
end

#stop_keep_alivevoid

This method returns an undefined value.

Kills the @keep_alive_thread, if it exists, and sets



368
369
370
371
372
373
# File 'lib/windoo/connection/token.rb', line 368

def stop_keep_alive
  return unless @keep_alive_thread

  @keep_alive_thread.kill if @keep_alive_thread.alive?
  @keep_alive_thread = nil
end

#time_remainingString

Returns e.g. “1 week 6 days 23 hours 49 minutes 56 seconds”.

Returns:

  • (String)

    e.g. “1 week 6 days 23 hours 49 minutes 56 seconds”



255
256
257
258
259
# File 'lib/windoo/connection/token.rb', line 255

def time_remaining
  return unless @expires

  secs_remaining.pix_humanize_secs
end

#time_to_refreshString?

Returns e.g. “1 week 6 days 23 hours 49 minutes 56 seconds”

Returns:

  • (String, nil)


239
240
241
242
243
# File 'lib/windoo/connection/token.rb', line 239

def time_to_refresh
  return unless keep_alive?

  secs_to_refresh.pix_humanize_secs
end

#valid?Boolean

Returns:

  • (Boolean)


263
264
265
266
267
268
269
270
271
272
# File 'lib/windoo/connection/token.rb', line 263

def valid?
  @valid =
    if expired?
      false
    elsif !@token
      false
    else
      token_connection(CURRENT_STATUS_RSRC, token: token).post.success?
    end
end