Class DeviceAuthorizationClient

java.lang.Object
com.ultikits.ultitools.utils.DeviceAuthorizationClient

class DeviceAuthorizationClient extends Object
The two REST calls of the RFC 8628 device authorization grant against UltiCloud protocol v2: POST /v1/device/authorize and POST /v1/device/token. Both routes are public; no credential travels with them.

Neither the device code nor a granted secret ever appears in a log line, an exception or a toString() produced here: the device code is a bearer for the grant during its lifetime.

Since:
6.3.1
  • Field Details

    • AUTHORIZE_PATH

      static final String AUTHORIZE_PATH
      See Also:
    • TOKEN_PATH

      static final String TOKEN_PATH
      See Also:
    • PROTOCOL_VERSION

      static final int PROTOCOL_VERSION
      The protocol major version this framework speaks.
      See Also:
    • DEFAULT_INTERVAL_SECONDS

      static final long DEFAULT_INTERVAL_SECONDS
      RFC 8628 §3.2: the poll interval to use when the response names none.
      See Also:
    • DEFAULT_EXPIRES_IN_SECONDS

      static final long DEFAULT_EXPIRES_IN_SECONDS
      The device code lifetime to assume when the response names none.
      See Also:
    • MAX_BACKEND_TEXT

      static final int MAX_BACKEND_TEXT
      The longest backend-supplied text (message, reason) this class passes on, in characters.
      See Also:
    • STATUS_BAD_REQUEST

      private static final int STATUS_BAD_REQUEST
      See Also:
    • STATUS_TOO_MANY_REQUESTS

      private static final int STATUS_TOO_MANY_REQUESTS
      See Also:
    • STATUS_SERVER_ERROR

      private static final int STATUS_SERVER_ERROR
      See Also:
    • MAX_RETRY_AFTER_SECONDS

      private static final long MAX_RETRY_AFTER_SECONDS
      The longest error.details.retryAfterSeconds taken from a 429 body.
      See Also:
  • Constructor Details

    • DeviceAuthorizationClient

      DeviceAuthorizationClient()
  • Method Details

    • authorize

      DeviceAuthorizationClient.AuthorizeResult authorize(String frameworkVersion, String suggestedNameOrNull, String legacyServerUuidOrNull)
      Requests a device code.
      Parameters:
      frameworkVersion - the running framework version, sent verbatim
      suggestedNameOrNull - the default server name for the confirmation page, or null to omit the field
      legacyServerUuidOrNull - this server's install id, or null to omit the field; it is sent as legacyServerUuid only in the contract's canonical form (32 lower-case hex digits) and omitted when it has none, so a hyphenated or otherwise unusable value never reaches UltiCloud (plan 22-20, S-64)
      Returns:
      the grant, or the reason it could not be obtained; never null
    • pollToken

      Polls for the outcome of deviceCode once.
      Parameters:
      deviceCode - the device code from authorize(java.lang.String, java.lang.String, java.lang.String)
      Returns:
      the classified outcome; never null
    • detailsRetryAfter

      private static long detailsRetryAfter(String body)
      Parameters:
      body - a 429 body, or null
      Returns:
      error.details.retryAfterSeconds when it is an integer in [1, 86400], or -1
    • readGrant

      private static DeviceAuthorizationClient.PollResult readGrant(String responseBody)
      Maps a 200 to GRANTED, or to TRANSIENT with a WARNING naming what is missing.
    • warnUnusableGrant

      private static void warnUnusableGrant(String defect)
      Names the defect only -- never a value from the response, which may hold the secret.
    • describeFailure

      private static String describeFailure(CloudHttp.Response response)
      Returns:
      UltiCloud answered HTTP <status>, plus the backend error code and message
    • sanitise

      static String sanitise(String text)
      Parameters:
      text - backend-supplied text, or null
      Returns:
      the text with control characters replaced by spaces, trimmed and cut to 200 characters; null when nothing remains
    • dataObject

      static com.google.gson.JsonObject dataObject(String body)
      Returns:
      the data object of a {data: {...}} body, or null
    • errorObject

      static com.google.gson.JsonObject errorObject(String body)
      Returns:
      the error object of a {error: {...}} body, or null
    • parseObject

      private static com.google.gson.JsonObject parseObject(String body)
    • string

      static String string(com.google.gson.JsonObject object, String member)
      Returns:
      the member as a string when it is a JSON string, otherwise null
    • isBlank

      private static boolean isBlank(String value)