class OAuth2::Client
Experimental RBS support (using type sampling data from the type_fusion
project).
# sig/oauth2/client.rbs class OAuth2::Client def authorize_url: (?Hash params) -> untyped end
rubocop:disable Metrics/ClassLength
The OAuth2::Client class
def assertion
def assertion @assertion ||= OAuth2::Strategy::Assertion.new(self) end
def auth_code
- See: http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.1 -
def auth_code @auth_code ||= OAuth2::Strategy::AuthCode.new(self) end
def authenticator
-
(Authenticator)
- the initialized Authenticator
def authenticator Authenticator.new(id, secret, options[:auth_scheme]) end
def authorize_url(params = {})
Experimental RBS support (using type sampling data from the type_fusion
project).
def authorize_url: (?response_type | String | client_id | String | redirect_uri | String | state | String | prompt | String | scope | String | include_granted_scopes | String | access_type | String params) -> untyped
This signature was generated using 1 sample from 1 application.
-
params
(Hash
) -- additional query parameters
def authorize_url(params = {}) params = (params || {}).merge(redirection_params) connection.build_url(options[:authorize_url], params).to_s end
def build_access_token(response, access_token_opts, access_token_class)
-
(AccessToken)
- the initialized AccessToken
def build_access_token(response, access_token_opts, access_token_class) access_token_class.from_hash(self, response.parsed.merge(access_token_opts)).tap do |access_token| access_token.response = response if access_token.respond_to?(:response=) end end
def build_access_token_legacy(response, access_token_opts, extract_access_token)
-
(AccessToken)
- the initialized AccessToken
def build_access_token_legacy(response, access_token_opts, extract_access_token) extract_access_token.call(self, response.parsed.merge(access_token_opts)) rescue StandardError nil end
def client_credentials
- See: http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.4 -
def client_credentials @client_credentials ||= OAuth2::Strategy::ClientCredentials.new(self) end
def connection
def connection @connection ||= Faraday.new(site, options[:connection_opts]) do |builder| oauth_debug_logging(builder) if options[:connection_build] options[:connection_build].call(builder) else builder.request :url_encoded # form-encode POST params builder.adapter Faraday.default_adapter # make requests with Net::HTTP end end end
def execute_request(verb, url, opts = {})
def execute_request(verb, url, opts = {}) url = connection.build_url(url).to_s begin response = connection.run_request(verb, url, opts[:body], opts[:headers]) do |req| req.params.update(opts[:params]) if opts[:params] yield(req) if block_given? end rescue Faraday::ConnectionFailed => e raise ConnectionError, e rescue Faraday::TimeoutError => e raise TimeoutError, e end parse = opts.key?(:parse) ? opts.delete(:parse) : Response::DEFAULT_OPTIONS[:parse] snaky = opts.key?(:snaky) ? opts.delete(:snaky) : Response::DEFAULT_OPTIONS[:snaky] Response.new(response, parse: parse, snaky: snaky) end
def get_token(params, access_token_opts = {}, extract_access_token = nil, &block)
-
(AccessToken)
- the initialized AccessToken
Other tags:
- Yield: - @see Faraday::Connection#run_request
Parameters:
-
extract_access_token
(Proc
) -- proc that extracts the access token from the response (DEPRECATED) -
access_token_opts
(Hash
) -- access token options, to pass to the AccessToken object -
params
(Hash
) -- a Hash of params for the token endpoint, except:
Options Hash:
(**params)
-
:snaky
(true, false
) -- @see Response#initialize -
:parse
(Symbol
) -- @see Response#initialize
def get_token(params, access_token_opts = {}, extract_access_token = nil, &block) warn('OAuth2::Client#get_token argument `extract_access_token` will be removed in oauth2 v3. Refactor to use `access_token_class` on #initialize.') if extract_access_token extract_access_token ||= options[:extract_access_token] parse, snaky, params, headers = parse_snaky_params_headers(params) request_opts = { raise_errors: options[:raise_errors], parse: parse, snaky: snaky, } if options[:token_method] == :post # NOTE: If proliferation of request types continues we should implement a parser solution for Request, # just like we have with Response. request_opts[:body] = if headers['Content-Type'] == 'application/json' params.to_json else params end request_opts[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'} else request_opts[:params] = params request_opts[:headers] = {} end request_opts[:headers].merge!(headers) response = request(http_method, token_url, request_opts, &block) # In v1.4.x, the deprecated extract_access_token option retrieves the token from the response. # We preserve this behavior here, but a custom access_token_class that implements #from_hash # should be used instead. if extract_access_token parse_response_legacy(response, access_token_opts, extract_access_token) else parse_response(response, access_token_opts) end end
def http_method
-
(Symbol)
- HTTP verb, one of :get, :post, :put, :delete
def http_method http_meth = options[:token_method].to_sym return :post if http_meth == :post_with_query_string http_meth end
def implicit
- See: http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26#section-4.2 -
def implicit @implicit ||= OAuth2::Strategy::Implicit.new(self) end
def initialize(client_id, client_secret, options = {}, &block)
- Yield: - The Faraday connection builder
Options Hash:
(**options)
-
:access_token_class
(Class
) -- [Class] class of access token for easier subclassing OAuth2::AccessToken, @version 2.0+ -
:extract_access_token
(Proc
) -- proc that takes the client and the response Hash and extracts the access token from the response (DEPRECATED) -
:logger
(Logger
) -- which logger to use when OAUTH_DEBUG is enabled -
:raise_errors
(Boolean
) -- whether or not to raise an OAuth2::Error on responses with 400+ status codes -
:max_redirects
(FixNum
) -- maximum number of redirects to follow -
:connection_opts
(Hash
) -- Hash of connection options to pass to initialize Faraday with -
:auth_scheme
(Symbol
) -- HTTP method to use to authorize request (:basic_auth or :request_body) -
:token_method
(Symbol
) -- HTTP method to use to request token (:get, :post, :post_with_query_string) -
:token_url
(String
) -- absolute or relative URL path to the Token endpoint -
:authorize_url
(String
) -- absolute or relative URL path to the Authorization endpoint -
:redirect_uri
(String
) -- the absolute URI to the Redirection Endpoint for use in authorization grants and token exchange -
:site
(String
) -- the OAuth2 provider site host
Parameters:
-
options
(Hash
) -- the options to create the client with -
client_secret
(String
) -- the client_secret value -
client_id
(String
) -- the client_id value
def initialize(client_id, client_secret, options = {}, &block) opts = options.dup @id = client_id @secret = client_secret @site = opts.delete(:site) ssl = opts.delete(:ssl) warn('OAuth2::Client#initialize argument `extract_access_token` will be removed in oauth2 v3. Refactor to use `access_token_class`.') if opts[:extract_access_token] @options = { authorize_url: 'oauth/authorize', token_url: 'oauth/token', token_method: :post, auth_scheme: :basic_auth, connection_opts: {}, connection_build: block, max_redirects: 5, raise_errors: true, logger: ::Logger.new($stdout), access_token_class: AccessToken, }.merge(opts) @options[:connection_opts][:ssl] = ssl if ssl end
def oauth_debug_logging(builder)
def oauth_debug_logging(builder) builder.response :logger, options[:logger], bodies: true if ENV['OAUTH_DEBUG'] == 'true' end
def parse_response(response, access_token_opts)
def parse_response(response, access_token_opts) access_token_class = options[:access_token_class] data = response.parsed unless data.is_a?(Hash) && !data.empty? return unless options[:raise_errors] error = Error.new(response) raise(error) end build_access_token(response, access_token_opts, access_token_class) end
def parse_response_legacy(response, access_token_opts, extract_access_token)
def parse_response_legacy(response, access_token_opts, extract_access_token) access_token = build_access_token_legacy(response, access_token_opts, extract_access_token) return access_token if access_token if options[:raise_errors] error = Error.new(response) raise(error) end nil end
def parse_snaky_params_headers(params)
def parse_snaky_params_headers(params) params = params.map do |key, value| if RESERVED_PARAM_KEYS.include?(key) [key.to_sym, value] else [key, value] end end.to_h parse = params.key?(:parse) ? params.delete(:parse) : Response::DEFAULT_OPTIONS[:parse] snaky = params.key?(:snaky) ? params.delete(:snaky) : Response::DEFAULT_OPTIONS[:snaky] params = authenticator.apply(params) # authenticator may add :headers, and we remove them here headers = params.delete(:headers) || {} [parse, snaky, params, headers] end
def password
- See: http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.3 -
def password @password ||= OAuth2::Strategy::Password.new(self) end
def redirection_params
-
(Hash)
- the params to add to a request or URL
Other tags:
- See: https://datatracker.ietf.org/doc/html/rfc6749#section-10.6 -
See: https://datatracker.ietf.org/doc/html/rfc6749#section-4.2.1 -
See: https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3 -
See: https://datatracker.ietf.org/doc/html/rfc6749#section-4.1 -
Other tags:
- Api: - semipublic
def redirection_params if options[:redirect_uri] {'redirect_uri' => options[:redirect_uri]} else {} end end
def request(verb, url, opts = {}, &block)
- Yield: - @see Faraday::Connection#run_request
Options Hash:
(**opts)
-
:snaky
(true, false
) -- @see Response::initialize -
:parse
(Symbol
) -- @see Response::initialize -
:raise_errors
(Boolean
) -- whether or not to raise an OAuth2::Error on 400+ status -
:headers
(Hash
) -- http request headers -
:body
(Hash, String
) -- the body of the request -
:params
(Hash
) -- additional query parameters for the URL of the request
Parameters:
-
opts
(Hash
) -- the options to make the request with -
url
(String
) -- URL path of request -
verb
(Symbol
) -- one of :get, :post, :put, :delete
Other tags:
- See: https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.2 -
def request(verb, url, opts = {}, &block) response = execute_request(verb, url, opts, &block) case response.status when 301, 302, 303, 307 opts[:redirect_count] ||= 0 opts[:redirect_count] += 1 return response if opts[:redirect_count] > options[:max_redirects] if response.status == 303 verb = :get opts.delete(:body) end location = response.headers['location'] if location full_location = response.response.env.url.merge(location) request(verb, full_location, opts) else error = Error.new(response) raise(error, "Got #{response.status} status code, but no Location header was present") end when 200..299, 300..399 # on non-redirecting 3xx statuses, just return the response response when 400..599 error = Error.new(response) raise(error) if opts.fetch(:raise_errors, options[:raise_errors]) response else error = Error.new(response) raise(error, "Unhandled status code value of #{response.status}") end end
def site=(value)
-
value
(String
) -- the OAuth2 provider site host
def site=(value) @connection = nil @site = value end
def token_url(params = nil)
-
params
(Hash
) -- additional query parameters
def token_url(params = nil) connection.build_url(options[:token_url], params).to_s end