class OAuth2::AccessToken
Constants
- TOKEN_KEYS_STR
- TOKEN_KEYS_SYM
- TOKEN_KEY_LOOKUP
Attributes
Public Class Methods
Source
# File lib/oauth2/access_token.rb 57 def from_hash(client, hash) 58 fresh = hash.dup 59 # If token_name is present, then use that key name 60 key = 61 if fresh.key?(:token_name) 62 t_key = fresh[:token_name] 63 no_tokens_warning(fresh, t_key) 64 t_key 65 else 66 # Otherwise, if one of the supported default keys is present, use whichever has precedence 67 supported_keys = TOKEN_KEY_LOOKUP & fresh.keys 68 t_key = supported_keys[0] 69 extra_tokens_warning(supported_keys, t_key) 70 t_key 71 end 72 # :nocov: 73 # TODO: Get rid of this branching logic when dropping Hashie < v3.2 74 token = if !defined?(Hashie::VERSION) # i.e. <= "1.1.0"; the first Hashie to ship with a VERSION constant 75 warn("snaky_hash and oauth2 will drop support for Hashie v0 in the next major version. Please upgrade to a modern Hashie.") 76 # There is a bug in Hashie v0, which is accounts for. 77 fresh.delete(key) || fresh[key] || "" 78 else 79 fresh.delete(key) || "" 80 end 81 # :nocov: 82 new(client, token, fresh) 83 end
Initializes an AccessToken
from a Hash
@param [OAuth2::Client] client the OAuth2::Client
instance @param [Hash] hash a hash containing the token and other properties @option hash [String] ‘access_token’ the access token value @option hash [String] ‘id_token’ alternative key for the access token value @option hash [String] ‘token’ alternative key for the access token value @option hash [String] ‘refresh_token’ (optional) the refresh token value @option hash [Integer, String] ‘expires_in’ (optional) number of seconds until token expires @option hash [Integer, String] ‘expires_at’ (optional) epoch time in seconds when token expires @option hash [Integer, String] ‘expires_latency’ (optional) seconds to reduce token validity by
@return [OAuth2::AccessToken] the initialized AccessToken
@note The method will use the first found token key in the following order:
'access_token', 'id_token', 'token' (or their symbolic versions)
@note If multiple token keys are present, a warning will be issued unless
OAuth2.config.silence_extra_tokens_warning is true
@note If no token keys are present, a warning will be issued unless
OAuth2.config.silence_no_tokens_warning is true
@note For “soon-to-expire”/“clock-skew” functionality see the ‘:expires_latency` option. @note If snaky key conversion is being used, token_name needs to match the converted key.
@example
hash = { 'access_token' => 'token_value', 'refresh_token' => 'refresh_value' } access_token = OAuth2::AccessToken.from_hash(client, hash)
Source
# File lib/oauth2/access_token.rb 90 def from_kvform(client, kvform) 91 from_hash(client, Rack::Utils.parse_query(kvform)) 92 end
Initializes an AccessToken
from a key/value application/x-www-form-urlencoded string
@param [Client] client the OAuth2::Client
instance @param [String] kvform the application/x-www-form-urlencoded string @return [AccessToken] the initialized AccessToken
Source
# File lib/oauth2/access_token.rb 142 def initialize(client, token, opts = {}) 143 @client = client 144 @token = token.to_s 145 opts = opts.dup 146 %i[refresh_token expires_in expires_at expires_latency].each do |arg| 147 instance_variable_set("@#{arg}", opts.delete(arg) || opts.delete(arg.to_s)) 148 end 149 no_tokens = (@token.nil? || @token.empty?) && (@refresh_token.nil? || @refresh_token.empty?) 150 if no_tokens 151 if @client.options[:raise_errors] 152 raise Error.new({ 153 error: "OAuth2::AccessToken has no token", 154 error_description: "Options are: #{opts.inspect}", 155 }) 156 elsif !OAuth2.config.silence_no_tokens_warning 157 warn("OAuth2::AccessToken has no token") 158 end 159 end 160 # @option opts [Fixnum, String] :expires is deprecated 161 @expires_in ||= opts.delete("expires") 162 @expires_in &&= @expires_in.to_i 163 @expires_at &&= convert_expires_at(@expires_at) 164 @expires_latency &&= @expires_latency.to_i 165 @expires_at ||= Time.now.to_i + @expires_in if @expires_in && !@expires_in.zero? 166 @expires_at -= @expires_latency if @expires_latency 167 @options = { 168 mode: opts.delete(:mode) || :header, 169 header_format: opts.delete(:header_format) || "Bearer %s", 170 param_name: opts.delete(:param_name) || "access_token", 171 } 172 @options[:token_name] = opts.delete(:token_name) if opts.key?(:token_name) 173 174 @params = opts 175 end
Initialize an AccessToken
@note For “soon-to-expire”/“clock-skew” functionality see the ‘:expires_latency` option. @note If no token is provided, the AccessToken
will be considered invalid.
This is to prevent the possibility of a token being accidentally created with no token value. If you want to create an AccessToken with no token value, you can pass in an empty string or nil for the token value. If you want to create an AccessToken with no token value and no refresh token, you can pass in an empty string or nil for the token value and nil for the refresh token, and `raise_errors: false`.
@param [Client] client the OAuth2::Client
instance @param [String] token the Access Token value (optional, may not be used in refresh flows) @param [Hash] opts the options to create the Access Token with @option opts [String] :refresh_token (nil) the refresh_token
value @option opts [FixNum, String] :expires_in (nil) the number of seconds in which the AccessToken
will expire @option opts [FixNum, String] :expires_at (nil) the epoch time in seconds in which AccessToken
will expire @option opts [FixNum, String] :expires_latency (nil) the number of seconds by which AccessToken
validity will be reduced to offset latency, @version 2.0+ @option opts [Symbol] :mode (:header) the transmission mode of the Access Token parameter value
one of :header, :body or :query
@option opts [String] :header_format (‘Bearer %s’) the string format to use for the Authorization header @option opts [String] :param_name (‘access_token’) the parameter name to use for transmission of the
Access Token value in :body or :query transmission mode
@option opts [String] :token_name (nil) the name of the response parameter that identifies the access token
When nil one of TOKEN_KEY_LOOKUP will be used
Private Class Methods
Source
# File lib/oauth2/access_token.rb 97 def extra_tokens_warning(supported_keys, key) 98 return if OAuth2.config.silence_extra_tokens_warning 99 return if supported_keys.length <= 1 100 101 warn("OAuth2::AccessToken.from_hash: `hash` contained more than one 'token' key (#{supported_keys}); using #{key.inspect}.") 102 end
Having too many is sus, and may lead to bugs. Having none is fine (e.g. refresh flow doesn’t need a token).
Source
# File lib/oauth2/access_token.rb 104 def no_tokens_warning(hash, key) 105 return if OAuth2.config.silence_no_tokens_warning 106 return if key && hash.key?(key) 107 108 warn(%[ 109 OAuth2::AccessToken#from_hash key mismatch. 110 Custom token_name (#{key}) is not found in (#{hash.keys}) 111 You may need to set `snaky: false`. See inline documentation for more info. 112 ]) 113 end
Public Instance Methods
Source
# File lib/oauth2/access_token.rb 180 def [](key) 181 @params[key] 182 end
Indexer to additional params present in token response
@param [String] key entry key to Hash
Source
# File lib/oauth2/access_token.rb 362 def delete(path, opts = {}, &block) 363 request(:delete, path, opts, &block) 364 end
Make a DELETE request with the Access Token
@see AccessToken#request
Source
# File lib/oauth2/access_token.rb 194 def expired? 195 expires? && (expires_at <= Time.now.to_i) 196 end
Check if token is expired
@return [Boolean] true if the token is expired, false otherwise
Source
# File lib/oauth2/access_token.rb 187 def expires? 188 !!@expires_at 189 end
Whether the token expires
@return [Boolean]
Source
# File lib/oauth2/access_token.rb 334 def get(path, opts = {}, &block) 335 request(:get, path, opts, &block) 336 end
Make a GET request with the Access Token
@see AccessToken#request
Source
# File lib/oauth2/access_token.rb 367 def headers 368 {"Authorization" => options[:header_format] % token} 369 end
Get the headers hash (includes Authorization token)
Source
# File lib/oauth2/access_token.rb 355 def patch(path, opts = {}, &block) 356 request(:patch, path, opts, &block) 357 end
Make a PATCH request with the Access Token
@see AccessToken#request
Source
# File lib/oauth2/access_token.rb 341 def post(path, opts = {}, &block) 342 request(:post, path, opts, &block) 343 end
Make a POST request with the Access Token
@see AccessToken#request
Source
# File lib/oauth2/access_token.rb 348 def put(path, opts = {}, &block) 349 request(:put, path, opts, &block) 350 end
Make a PUT request with the Access Token
@see AccessToken#request
Source
# File lib/oauth2/access_token.rb 209 def refresh(params = {}, access_token_opts = {}, &block) 210 raise OAuth2::Error.new({error: "A refresh_token is not available"}) unless refresh_token 211 212 params[:grant_type] = "refresh_token" 213 params[:refresh_token] = refresh_token 214 new_token = @client.get_token(params, access_token_opts, &block) 215 new_token.options = options 216 if new_token.refresh_token 217 # Keep it if there is one 218 else 219 new_token.refresh_token = refresh_token 220 end 221 new_token 222 end
Refreshes the current Access Token
@param [Hash] params additional params to pass to the refresh token request @param [Hash] access_token_opts options that will be passed to the AccessToken
initialization
@yield [opts] The block to modify the refresh token request options @yieldparam [Hash] opts The options hash that can be modified
@return [OAuth2::AccessToken] a new AccessToken
instance
@note current token’s options are carried over to the new AccessToken
A compatibility alias @note does not modify the receiver, so bang is not the default method
Source
# File lib/oauth2/access_token.rb 326 def request(verb, path, opts = {}, &block) 327 configure_authentication!(opts) 328 @client.request(verb, path, opts, &block) 329 end
Make a request with the Access Token
@param [Symbol] verb the HTTP request method @param [String] path the HTTP URL path of the request @param [Hash] opts the options to make the request with @option opts [Hash] :params additional URL parameters @option opts [Hash, String] :body the request body @option opts [Hash] :headers request headers
@yield [req] The block to modify the request @yieldparam [Faraday::Request] req The request object that can be modified
@return [OAuth2::Response] the response from the request
Source
# File lib/oauth2/access_token.rb 258 def revoke(params = {}, &block) 259 token_type_hint_orig = params.delete(:token_type_hint) 260 token_type_hint = nil 261 revoke_token = case token_type_hint_orig 262 when "access_token", :access_token 263 token_type_hint = "access_token" 264 token 265 when "refresh_token", :refresh_token 266 token_type_hint = "refresh_token" 267 refresh_token 268 when nil 269 if token 270 token_type_hint = "access_token" 271 token 272 elsif refresh_token 273 token_type_hint = "refresh_token" 274 refresh_token 275 end 276 else 277 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."}) 278 end 279 raise OAuth2::Error.new({error: "#{token_type_hint || "unknown token type"} is not available for revoking"}) unless revoke_token && !revoke_token.empty? 280 281 @client.revoke_token(revoke_token, token_type_hint, params, &block) 282 end
Revokes the token at the authorization server
@param [Hash] params additional parameters to be sent during revocation @option params [String, Symbol, nil] :token_type_hint (‘access_token’ or ‘refresh_token’) hint about which token to revoke @option params [Symbol] :token_method (:post_with_query_string) overrides OAuth2::Client#options[:token_method]
@yield [req] The block is passed the request being made, allowing customization @yieldparam [Faraday::Request] req The request object that can be modified
@return [OAuth2::Response] OAuth2::Response
instance
@api public
@raise [OAuth2::Error] if token_type_hint is invalid or the specified token is not available
@note If the token passed to the request
is an access token, the server MAY revoke the respective refresh token as well.
@note If the token passed to the request
is a refresh token and the authorization server supports the revocation of access tokens, then the authorization server SHOULD also invalidate all access tokens based on the same authorization grant
@note If the server responds with HTTP status code 503, your code must
assume the token still exists and may retry after a reasonable delay. The server may include a "Retry-After" header in the response to indicate how long the service is expected to be unavailable to the requesting client.
@see datatracker.ietf.org/doc/html/rfc7009 @see datatracker.ietf.org/doc/html/rfc7009#section-2.1
A compatibility alias @note does not modify the receiver, so bang is not the default method
Source
# File lib/oauth2/access_token.rb 292 def to_hash 293 hsh = { 294 access_token: token, 295 refresh_token: refresh_token, 296 expires_at: expires_at, 297 mode: options[:mode], 298 header_format: options[:header_format], 299 param_name: options[:param_name], 300 } 301 hsh[:token_name] = options[:token_name] if options.key?(:token_name) 302 # TODO: Switch when dropping Ruby < 2.5 support 303 # params.transform_keys(&:to_sym) # Ruby 2.5 only 304 # Old Ruby transform_keys alternative: 305 sheesh = @params.each_with_object({}) { |(k, v), memo| 306 memo[k.to_sym] = v 307 } 308 sheesh.merge(hsh) 309 end
Convert AccessToken
to a hash which can be used to rebuild itself with AccessToken.from_hash
@note Don’t return expires_latency
because it has already been deducted from expires_at
@return [Hash] a hash of AccessToken
property values
Private Instance Methods
Source
# File lib/oauth2/access_token.rb 373 def configure_authentication!(opts) 374 case options[:mode] 375 when :header 376 opts[:headers] ||= {} 377 opts[:headers].merge!(headers) 378 when :query 379 opts[:params] ||= {} 380 opts[:params][options[:param_name]] = token 381 when :body 382 opts[:body] ||= {} 383 if opts[:body].is_a?(Hash) 384 opts[:body][options[:param_name]] = token 385 else 386 opts[:body] += "&#{options[:param_name]}=#{token}" 387 end 388 # @todo support for multi-part (file uploads) 389 else 390 raise("invalid :mode option of #{options[:mode]}") 391 end 392 end
Source
# File lib/oauth2/access_token.rb 394 def convert_expires_at(expires_at) 395 Time.iso8601(expires_at.to_s).to_i 396 rescue ArgumentError 397 expires_at.to_i 398 end