class OAuth2::AccessToken

rubocop:disable Metrics/ClassLength

def [](key)

Parameters:
  • key (String) -- entry key to Hash
def [](key)
  @params[key]
end

def configure_authentication!(opts, verb)

def configure_authentication!(opts, verb)
  mode_opt = options[:mode]
  mode =
    if mode_opt.respond_to?(:call)
      mode_opt.call(verb)
    elsif mode_opt.is_a?(Hash)
      key = verb.to_sym
      # Try symbol key first, then string key; default to :header when missing
      mode_opt[key] || mode_opt[key.to_s] || :header
    else
      mode_opt
    end
  case mode
  when :header
    opts[:headers] ||= {}
    opts[:headers].merge!(headers)
  when :query
    # OAuth 2.1 note: Bearer tokens in the query string are omitted from the spec due to security risks.
    # Prefer the default :header mode whenever possible.
    opts[:params] ||= {}
    opts[:params][options[:param_name]] = token
  when :body
    opts[:body] ||= {}
    if opts[:body].is_a?(Hash)
      opts[:body][options[:param_name]] = token
    else
      opts[:body] += "&#{options[:param_name]}=#{token}"
    end
    # @todo support for multi-part (file uploads)
  else
    raise("invalid :mode option of #{mode}")
  end
end

def convert_expires_at(expires_at)

def convert_expires_at(expires_at)
  Time.iso8601(expires_at.to_s).to_i
rescue ArgumentError
  expires_at.to_i
end

def delete(path, opts = {}, &block)

Other tags:
    See: AccessToken#request -
def delete(path, opts = {}, &block)
  request(:delete, path, opts, &block)
end

def expired?

Returns:
  • (Boolean) - true if the token is expired, false otherwise
def expired?
  expires? && (expires_at <= Time.now.to_i)
end

def expires?

Returns:
  • (Boolean) -
def expires?
  !!@expires_at
end

def extra_tokens_warning(supported_keys, key)

Having too many is sus, and may lead to bugs. Having none is fine (e.g. refresh flow doesn't need a token).
def extra_tokens_warning(supported_keys, key)
  return if OAuth2.config.silence_extra_tokens_warning
  return if supported_keys.length <= 1
  warn("OAuth2::AccessToken.from_hash: `hash` contained more than one 'token' key (#{supported_keys}); using #{key.inspect}.")
end

def from_hash(client, hash)

Other tags:
    Note: - If snaky key conversion is being used, token_name needs to match the converted key.
    Note: - For "soon-to-expire"/"clock-skew" functionality see the `:expires_latency` option.
    Note: - If no token keys are present, a warning will be issued unless
    Note: - If multiple token keys are present, a warning will be issued unless
    Note: - The method will use the first found token key in the following order:

Returns:
  • (OAuth2::AccessToken) - the initialized AccessToken

Options Hash: (**hash)
  • 'expires_latency' (Integer, String) -- seconds to reduce token validity by
  • 'expires_at' (Integer, String) -- epoch time in seconds when token expires
  • 'expires_in' (Integer, String) -- number of seconds until token expires
  • 'refresh_token' (String) -- the refresh token value
  • 'token' (String) -- alternative key for the access token value
  • 'id_token' (String) -- alternative key for the access token value
  • 'access_token' (String) -- the access token value

Parameters:
  • hash (Hash) -- a hash containing the token and other properties
  • client (OAuth2::Client) -- the OAuth2::Client instance
def from_hash(client, hash)
  fresh = hash.dup
  # If token_name is present, then use that key name
  if fresh.key?(:token_name)
    t_key = fresh[:token_name]
    no_tokens_warning(fresh, t_key)
  else
    # Otherwise, if one of the supported default keys is present, use whichever has precedence
    supported_keys = TOKEN_KEY_LOOKUP & fresh.keys
    t_key = supported_keys[0]
    extra_tokens_warning(supported_keys, t_key)
  end
  # :nocov:
  # TODO: Get rid of this branching logic when dropping Hashie < v3.2
  token = if !defined?(Hashie::VERSION) # i.e. <= "1.1.0"; the first Hashie to ship with a VERSION constant
    warn("snaky_hash and oauth2 will drop support for Hashie v0 in the next major version. Please upgrade to a modern Hashie.")
    # There is a bug in Hashie v0, which is accounts for.
    fresh.delete(t_key) || fresh[t_key] || ""
  else
    fresh.delete(t_key) || ""
  end
  # :nocov:
  new(client, token, fresh)
end

def from_kvform(client, kvform)

Returns:
  • (AccessToken) - the initialized AccessToken

Parameters:
  • kvform (String) -- the application/x-www-form-urlencoded string
  • client (Client) -- the OAuth2::Client instance
def from_kvform(client, kvform)
  from_hash(client, Rack::Utils.parse_query(kvform))
end

def get(path, opts = {}, &block)

Other tags:
    See: AccessToken#request -
def get(path, opts = {}, &block)
  request(:get, path, opts, &block)
end

def headers

Get the headers hash (includes Authorization token)
def headers
  {"Authorization" => options[:header_format] % token}
end

def initialize(client, token, opts = {})

Options Hash: (**opts)
  • :token_name (String) -- the name of the response parameter that identifies the access token
  • :param_name (String) -- the parameter name to use for transmission of the
  • :header_format (String) -- the string format to use for the Authorization header
  • :mode (Symbol, Hash, or callable) -- the transmission mode of the Access Token parameter value:
  • :expires_latency (FixNum, String) -- the number of seconds by which AccessToken validity will be reduced to offset latency, @version 2.0+
  • :expires_at (FixNum, String) -- the epoch time in seconds in which AccessToken will expire
  • :expires_in (FixNum, String) -- the number of seconds in which the AccessToken will expire
  • :refresh_token (String) -- the refresh_token value

Other tags:
    Example: Verb-dependent Hash mode -

Parameters:
  • opts (Hash) -- the options to create the Access Token with
  • token (String) -- the Access Token value (optional, may not be used in refresh flows)
  • client (Client) -- the OAuth2::Client instance

Other tags:
    Note: - If no token is provided, the AccessToken will be considered invalid.
    Note: - For "soon-to-expire"/"clock-skew" functionality see the `:expires_latency` option.
def initialize(client, token, opts = {})
  @client = client
  @token = token.to_s
  opts = opts.dup
  %i[refresh_token expires_in expires_at expires_latency].each do |arg|
    instance_variable_set("@#{arg}", opts.delete(arg) || opts.delete(arg.to_s))
  end
  no_tokens = (@token.nil? || @token.empty?) && (@refresh_token.nil? || @refresh_token.empty?)
  if no_tokens
    if @client.options[:raise_errors]
      raise Error.new({
        error: "OAuth2::AccessToken has no token",
        error_description: "Options are: #{opts.inspect}",
      })
    elsif !OAuth2.config.silence_no_tokens_warning
      warn("OAuth2::AccessToken has no token")
    end
  end
  # @option opts [Fixnum, String] :expires is deprecated
  @expires_in ||= opts.delete("expires")
  @expires_in &&= @expires_in.to_i
  @expires_at &&= convert_expires_at(@expires_at)
  @expires_latency &&= @expires_latency.to_i
  @expires_at ||= Time.now.to_i + @expires_in if @expires_in && !@expires_in.zero?
  @expires_at -= @expires_latency if @expires_latency
  @options = {
    mode: opts.delete(:mode) || :header,
    header_format: opts.delete(:header_format) || "Bearer %s",
    param_name: opts.delete(:param_name) || "access_token",
  }
  @options[:token_name] = opts.delete(:token_name) if opts.key?(:token_name)
  @params = opts
end

def no_tokens_warning(hash, key)

def no_tokens_warning(hash, key)
  return if OAuth2.config.silence_no_tokens_warning
  return if key && hash.key?(key)
  warn(%[
::AccessToken#from_hash key mismatch.
 token_name (#{key}) is not found in (#{hash.keys})
y need to set `snaky: false`. See inline documentation for more info.
  ])
end

def patch(path, opts = {}, &block)

Other tags:
    See: AccessToken#request -
def patch(path, opts = {}, &block)
  request(:patch, path, opts, &block)
end

def post(path, opts = {}, &block)

Other tags:
    See: AccessToken#request -
def post(path, opts = {}, &block)
  request(:post, path, opts, &block)
end

def put(path, opts = {}, &block)

Other tags:
    See: AccessToken#request -
def put(path, opts = {}, &block)
  request(:put, path, opts, &block)
end

def refresh(params = {}, access_token_opts = {}, &block)

Other tags:
    Note: - current token's options are carried over to the new AccessToken

Returns:
  • (OAuth2::AccessToken) - a new AccessToken instance

Other tags:
    Yieldparam: opts - The options hash that can be modified

Other tags:
    Yield: - The block to modify the refresh token request options

Parameters:
  • access_token_opts (Hash) -- options that will be passed to the AccessToken initialization
  • params (Hash) -- additional params to pass to the refresh token request
def refresh(params = {}, access_token_opts = {}, &block)
  raise OAuth2::Error.new({error: "A refresh_token is not available"}) unless refresh_token
  params[:grant_type] = "refresh_token"
  params[:refresh_token] = refresh_token
  new_token = @client.get_token(params, access_token_opts, &block)
  new_token.options = options
  if new_token.refresh_token
    # Keep it if there is one
  else
    new_token.refresh_token = refresh_token
  end
  new_token
end

def request(verb, path, opts = {}, &block)

Other tags:
    See: OAuth2::Client#request -

Returns:
  • (OAuth2::Response) - the response from the request

Other tags:
    Yieldparam: req - The request object that can be modified

Other tags:
    Yield: - The block to modify the request

Options Hash: (**opts)
  • :headers (Hash) -- request headers
  • :body (Hash, String) -- the request body
  • :params (Hash) -- additional URL parameters

Parameters:
  • opts (Hash) -- the options to make the request with
  • path (String) -- the HTTP URL path of the request
  • verb (Symbol) -- the HTTP request method
def request(verb, path, opts = {}, &block)
  configure_authentication!(opts, verb)
  @client.request(verb, path, opts, &block)
end

def revoke(params = {}, &block)

Other tags:
    See: https://datatracker.ietf.org/doc/html/rfc7009#section-2.1 -
    See: https://datatracker.ietf.org/doc/html/rfc7009 -

Other tags:
    Note: - If the server responds with HTTP status code 503, your code must
    Note: - If the token passed to the request
    Note: - If the token passed to the request

Raises:
  • (OAuth2::Error) - if token_type_hint is invalid or the specified token is not available

Other tags:
    Api: - public

Returns:
  • (OAuth2::Response) - OAuth2::Response instance

Other tags:
    Yieldparam: req - The request object that can be modified

Other tags:
    Yield: - The block is passed the request being made, allowing customization

Options Hash: (**params)
  • :token_method (Symbol) -- overrides OAuth2::Client#options[:token_method]
  • :token_type_hint (String, Symbol, nil) -- hint about which token to revoke

Parameters:
  • params (Hash) -- additional parameters to be sent during revocation
def revoke(params = {}, &block)
  token_type_hint_orig = params.delete(:token_type_hint)
  token_type_hint = nil
  revoke_token = case token_type_hint_orig
  when "access_token", :access_token
    token_type_hint = "access_token"
    token
  when "refresh_token", :refresh_token
    token_type_hint = "refresh_token"
    refresh_token
  when nil
    if token
      token_type_hint = "access_token"
      token
    elsif refresh_token
      token_type_hint = "refresh_token"
      refresh_token
    end
  else
    raise OAuth2::Error.new({error: "token_type_hint must be one of [nil, :refresh_token, :access_token], so if you need something else consider using a subclass or entirely custom AccessToken class."})
  end
  raise OAuth2::Error.new({error: "#{token_type_hint || "unknown token type"} is not available for revoking"}) unless revoke_token && !revoke_token.empty?
  @client.revoke_token(revoke_token, token_type_hint, params, &block)
end

def to_hash

Returns:
  • (Hash) - a hash of AccessToken property values

Other tags:
    Note: - Don't return expires_latency because it has already been deducted from expires_at
def to_hash
  hsh = {
    access_token: token,
    refresh_token: refresh_token,
    expires_at: expires_at,
    mode: options[:mode],
    header_format: options[:header_format],
    param_name: options[:param_name],
  }
  hsh[:token_name] = options[:token_name] if options.key?(:token_name)
  # TODO: Switch when dropping Ruby < 2.5 support
  # params.transform_keys(&:to_sym) # Ruby 2.5 only
  # Old Ruby transform_keys alternative:
  sheesh = @params.each_with_object({}) { |(k, v), memo|
    memo[k.to_sym] = v
  }
  sheesh.merge(hsh)
end