Class: OAuth2::Client

Inherits:
Object
  • Object
show all
Includes:
FilteredAttributes
Defined in:
lib/oauth2/client.rb

Overview

The OAuth2::Client class

Constant Summary collapse

RESERVED_REQ_KEYS =

rubocop:disable Metrics/ClassLength

%w[body headers params redirect_count].freeze
RESERVED_PARAM_KEYS =
(RESERVED_REQ_KEYS + %w[parse snaky snaky_hash_klass token_method]).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client_id, client_secret, options = {}) {|builder| ... } ⇒ Client

Initializes a new OAuth2::Client instance using the Client ID and Client Secret registered to your application.

Parameters:

  • client_id (String) —

    the client_id value

  • client_secret (String) —

    the client_secret value

  • options (Hash) (defaults to: {}) —

    the options to configure the client

Options Hash (options):

  • :site (String) —

    the OAuth2 provider site host

  • :authorize_url (String) — default: '/oauth/authorize' —

    absolute or relative URL path to the Authorization endpoint

  • :revoke_url (String) — default: '/oauth/revoke' —

    absolute or relative URL path to the Revoke endpoint

  • :token_url (String) — default: '/oauth/token' —

    absolute or relative URL path to the Token endpoint

  • :token_method (Symbol) — default: :post —

    HTTP method to use to request token (:get, :post, :post_with_query_string)

  • :auth_scheme (Symbol) — default: :basic_auth —

    the authentication scheme (:basic_auth, :request_body, :tls_client_auth, :private_key_jwt)

  • :connection_opts (Hash) — default: {} —

    Hash of connection options to pass to initialize Faraday

  • :raise_errors (Boolean) — default: true —

    whether to raise an OAuth2::Error on responses with 400+ status codes

  • :max_redirects (Integer) — default: 5 —

    maximum number of redirects to follow

  • :logger (Logger) — default: ::Logger.new($stdout) —

    Logger instance for HTTP request/response output; requires OAUTH_DEBUG to be true. When debug logging is enabled, sensitive values are filtered using {OAuth2::AUTH_SANITIZER::SanitizedLogger} initialized from OAuth2.config[:filtered_label] and the key names in OAuth2.config[:filtered_debug_keys].

  • :access_token_class (Class) — default: AccessToken —

    class to use for access tokens; you can subclass OAuth2::AccessToken, @version 2.0+

  • :ssl (Hash) —

    SSL options for Faraday

Yields:

  • (builder) —

    The Faraday connection builder



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/oauth2/client.rb', line 50

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",
    revoke_url: "oauth/revoke",
    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,
    # Default changed from true to false in 2.1.0 for security.
    # Cross-origin redirects are now rejected before credentials are replayed.
    allow_cross_origin_redirects: false,
  }.merge(opts)
  @options[:connection_opts][:ssl] = ssl if ssl
end

Instance Attribute Details

#connection ⇒ Faraday::Connection

The Faraday connection object

Returns:

  • (Faraday::Connection) —

    the initialized Faraday connection



88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/oauth2/client.rb', line 88

def connection
  @connection ||=
    Faraday.new(site, options[:connection_opts]) do |builder|
      oauth_debug_logging(builder)
      connection_build = options[:connection_build]
      if connection_build
        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

#id ⇒ Object (readonly)

Returns the value of attribute id.



26
27
28
# File 'lib/oauth2/client.rb', line 26

def id
  @id
end

#options ⇒ Object

Returns the value of attribute options.



27
28
29
# File 'lib/oauth2/client.rb', line 27

def options
  @options
end

#secret ⇒ Object (readonly)

Returns the value of attribute secret.



26
27
28
# File 'lib/oauth2/client.rb', line 26

def secret
  @secret
end

#site ⇒ Object

Returns the value of attribute site.



26
27
28
# File 'lib/oauth2/client.rb', line 26

def site
  @site
end

Instance Method Details

#assertion ⇒ OAuth2::Strategy::Assertion

The Assertion strategy

This allows for assertion-based authentication where an identity provider
asserts the identity of the user or client application seeking access.



319
320
321
# File 'lib/oauth2/client.rb', line 319

def assertion
  @assertion ||= OAuth2::Strategy::Assertion.new(self)
end

#auth_code ⇒ Object

The Authorization Code strategy



285
286
287
# File 'lib/oauth2/client.rb', line 285

def auth_code
  @auth_code ||= OAuth2::Strategy::AuthCode.new(self)
end

#authorize_url(params = {}) ⇒ String

The authorize endpoint URL of the OAuth2 provider

Parameters:

  • params (Hash) (defaults to: {}) —

    additional query parameters

Returns:

  • (String) —

    the constructed authorize URL



106
107
108
109
# File 'lib/oauth2/client.rb', line 106

def authorize_url(params = {})
  params = (params || {}).merge(redirection_params)
  connection.build_url(options[:authorize_url], params).to_s
end

#client_credentials ⇒ Object

The Client Credentials strategy



306
307
308
# File 'lib/oauth2/client.rb', line 306

def client_credentials
  @client_credentials ||= OAuth2::Strategy::ClientCredentials.new(self)
end

#get_token(params, access_token_opts = {}, extract_access_token = nil) {|opts| ... } ⇒ AccessToken?

Note:

The extract_access_token parameter is deprecated and will be removed in oauth2 v3.
Use access_token_class on initialization instead.

Retrieves an access token from the token endpoint using the specified parameters

Examples:

client.get_token(
  'grant_type' => 'authorization_code',
  'code' => 'auth_code_value',
  'headers' => {'Authorization' => 'Basic ...'}
)

Parameters:

  • params (Hash) —

    a Hash of params for the token endpoint

    • params can include a ‘headers’ key with a Hash of request headers
    • params can include a ‘parse’ key with the Symbol name of response parsing strategy (default: :automatic)
    • params can include a ‘snaky’ key to control snake_case conversion (default: false)
  • access_token_opts (Hash) (defaults to: {}) —

    options that will be passed to the AccessToken initialization

  • extract_access_token (Proc) (defaults to: nil) —

    (deprecated) a proc that can extract the access token from the response

Yields:

  • (opts) —

    The block is passed the options being used to make the request

Yield Parameters:

  • opts (Hash) —

    options being passed to the http library

Returns:

  • (AccessToken, nil) —

    the initialized AccessToken instance, or nil if token extraction fails
    and raise_errors is false



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/oauth2/client.rb', line 213

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]
  req_opts = params_to_req_opts(params)
  response = request(http_method, token_url, req_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

#http_method ⇒ Symbol

The HTTP Method of the request

Returns:

  • (Symbol) —

    HTTP verb, one of [:get, :post, :put, :delete]



275
276
277
278
279
280
# File 'lib/oauth2/client.rb', line 275

def http_method
  http_meth = options[:token_method].to_sym
  return :post if http_meth == :post_with_query_string

  http_meth
end

#implicit ⇒ Object

The Implicit strategy



292
293
294
# File 'lib/oauth2/client.rb', line 292

def implicit
  @implicit ||= OAuth2::Strategy::Implicit.new(self)
end

#password ⇒ Object

The Resource Owner Password Credentials strategy



299
300
301
# File 'lib/oauth2/client.rb', line 299

def password
  @password ||= OAuth2::Strategy::Password.new(self)
end

#redirection_params ⇒ Hash

The redirect_uri parameters, if configured

The redirect_uri query parameter is OPTIONAL (though encouraged) when
requesting authorization. If it is provided at authorization time it MUST
also be provided with the token exchange request.

OAuth 2.1 note: Authorization Servers must compare redirect URIs using exact string matching.
This client simply forwards the configured redirect_uri; the exact-match validation happens server-side.

Providing :redirect_uri to the OAuth2::Client instantiation will take
care of managing this.



344
345
346
347
348
349
350
351
# File 'lib/oauth2/client.rb', line 344

def redirection_params
  redirect_uri = options[:redirect_uri]
  if redirect_uri
    {"redirect_uri" => redirect_uri}
  else
    {}
  end
end

#request(verb, url, req_opts = {}) {|req| ... } ⇒ OAuth2::Response

Makes a request relative to the specified site root.

Updated HTTP 1.1 specification (IETF RFC 7231) relaxed the original constraint (IETF RFC 2616),
allowing the use of relative URLs in Location headers.

Parameters:

  • verb (Symbol) —

    one of [:get, :post, :put, :delete]

  • url (String) —

    URL path of request

  • req_opts (Hash) (defaults to: {}) —

    the options to make the request with

Options Hash (req_opts):

  • :params (Hash) —

    additional query parameters for the URL of the request

  • :body (Hash, String) —

    the body of the request

  • :headers (Hash) —

    http request headers

  • :raise_errors (Boolean) —

    whether to raise an OAuth2::Error on 400+ status
    code response for this request. Overrides the client instance setting.

  • :parse (Symbol) —

    @see Response::initialize

  • :snaky (Boolean) — default: true —

    @see Response::initialize

Yields:

  • (req) —

    The block is passed the request being made, allowing customization

Yield Parameters:

  • req (Faraday::Request) —

    The request object that can be modified

Returns:

See Also:



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/oauth2/client.rb', line 150

def request(verb, url, req_opts = {}, &block)
  response = execute_request(verb, url, req_opts, &block)
  status = response.status

  case status
  when 301, 302, 303, 307
    redirect_count = (req_opts[:redirect_count] || 0).to_i + 1
    req_opts[:redirect_count] = redirect_count
    return response if redirect_count > options[:max_redirects]

    if status == 303
      verb = :get
      req_opts.delete(:body)
    end
    location = response.headers["location"]
    if location
      current_location = response.response.env.url
      full_location = resolve_redirect_location(current_location, location)
      request(verb, full_location, sanitize_redirect_options(req_opts, current_location, full_location))
    else
      error = Error.new(response)
      raise(error, "Got #{status} status code, but no Location header was present")
    end
  when 200..299, 300..399
    # on non-redirecting 3xx statuses, return the response
    response
  when 400..599
    if req_opts.fetch(:raise_errors, options[:raise_errors])
      error = Error.new(response)
      raise(error)
    end

    response
  else
    error = Error.new(response)
    raise(error, "Unhandled status code value of #{status}")
  end
end

#revoke_token(token, token_type_hint = nil, params = {}) {|req| ... } ⇒ OAuth2::Response

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.

Makes a request to revoke a token at the authorization server

Parameters:

  • token (String) —

    The token to be revoked

  • token_type_hint (String, nil) (defaults to: nil) —

    A hint about the type of the token being revoked (e.g., ‘access_token’ or ‘refresh_token’)

  • params (Hash) (defaults to: {}) —

    additional parameters for the token revocation

Options Hash (params):

  • :parse (Symbol) — default: :automatic —

    parsing strategy for the response

  • :snaky (Boolean) — default: true —

    whether to convert response keys to snake_case

  • :token_method (Symbol) — default: :post_with_query_string —

    overrides OAuth2::Client#options[:token_method]

  • :headers (Hash) —

    Additional request headers

Yields:

  • (req) —

    The block is passed the request being made, allowing customization

Yield Parameters:

  • req (Faraday::Request) —

    The request object that can be modified

Returns:

See Also:



262
263
264
265
266
267
268
269
270
# File 'lib/oauth2/client.rb', line 262

def revoke_token(token, token_type_hint = nil, params = {}, &block)
  params[:token_method] ||= :post_with_query_string
  params[:token] = token
  params[:token_type_hint] = token_type_hint if token_type_hint

  req_opts = params_to_req_opts(params)

  request(http_method, revoke_url, req_opts, &block)
end

#revoke_url(params = nil) ⇒ String

The revoke endpoint URL of the OAuth2 provider

Parameters:

  • params (Hash, nil) (defaults to: nil) —

    additional query parameters

Returns:

  • (String) —

    the constructed revoke URL



123
124
125
# File 'lib/oauth2/client.rb', line 123

def revoke_url(params = nil)
  connection.build_url(options[:revoke_url], params).to_s
end

#token_url(params = nil) ⇒ String

The token endpoint URL of the OAuth2 provider

Parameters:

  • params (Hash, nil) (defaults to: nil) —

    additional query parameters

Returns:

  • (String) —

    the constructed token URL



115
116
117
# File 'lib/oauth2/client.rb', line 115

def token_url(params = nil)
  connection.build_url(options[:token_url], params).to_s
end