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` and the key names in `OAuth2.config`.

  • :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
# 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,
  }.merge(opts)
  @options[:connection_opts][:ssl] = ssl if ssl
end

Instance Attribute Details

#connectionFaraday::Connection

The Faraday connection object

Returns:

  • (Faraday::Connection)

    the initialized Faraday connection



85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/oauth2/client.rb', line 85

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

#idObject (readonly)

Returns the value of attribute id.



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

def id
  @id
end

#optionsObject

Returns the value of attribute options.



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

def options
  @options
end

#secretObject (readonly)

Returns the value of attribute secret.



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

def secret
  @secret
end

#siteObject

Returns the value of attribute site.



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

def site
  @site
end

Instance Method Details

#assertionOAuth2::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.



316
317
318
# File 'lib/oauth2/client.rb', line 316

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

#auth_codeObject

The Authorization Code strategy



282
283
284
# File 'lib/oauth2/client.rb', line 282

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



103
104
105
106
# File 'lib/oauth2/client.rb', line 103

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

#client_credentialsObject

The Client Credentials strategy



303
304
305
# File 'lib/oauth2/client.rb', line 303

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



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/oauth2/client.rb', line 210

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_methodSymbol

The HTTP Method of the request

Returns:

  • (Symbol)

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



272
273
274
275
276
277
# File 'lib/oauth2/client.rb', line 272

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

  http_meth
end

#implicitObject

The Implicit strategy



289
290
291
# File 'lib/oauth2/client.rb', line 289

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

#passwordObject

The Resource Owner Password Credentials strategy



296
297
298
# File 'lib/oauth2/client.rb', line 296

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

#redirection_paramsHash

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.



341
342
343
344
345
346
347
348
# File 'lib/oauth2/client.rb', line 341

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:



147
148
149
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
# File 'lib/oauth2/client.rb', line 147

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
  • :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:



259
260
261
262
263
264
265
266
267
# File 'lib/oauth2/client.rb', line 259

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



120
121
122
# File 'lib/oauth2/client.rb', line 120

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



112
113
114
# File 'lib/oauth2/client.rb', line 112

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