oauth2 1.4.3 → 2.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +188 -16
  3. data/CODE_OF_CONDUCT.md +105 -46
  4. data/CONTRIBUTING.md +27 -1
  5. data/LICENSE +1 -1
  6. data/README.md +428 -131
  7. data/SECURITY.md +26 -0
  8. data/lib/oauth2/access_token.rb +73 -25
  9. data/lib/oauth2/authenticator.rb +12 -5
  10. data/lib/oauth2/client.rb +208 -65
  11. data/lib/oauth2/error.rb +43 -24
  12. data/lib/oauth2/response.rb +81 -22
  13. data/lib/oauth2/strategy/assertion.rb +66 -39
  14. data/lib/oauth2/strategy/auth_code.rb +16 -3
  15. data/lib/oauth2/strategy/base.rb +2 -0
  16. data/lib/oauth2/strategy/client_credentials.rb +4 -2
  17. data/lib/oauth2/strategy/implicit.rb +10 -1
  18. data/lib/oauth2/strategy/password.rb +5 -3
  19. data/lib/oauth2/version.rb +3 -55
  20. data/lib/oauth2.rb +29 -1
  21. metadata +80 -100
  22. data/.document +0 -5
  23. data/.gitignore +0 -19
  24. data/.jrubyrc +0 -1
  25. data/.rspec +0 -2
  26. data/.rubocop.yml +0 -80
  27. data/.rubocop_rspec.yml +0 -26
  28. data/.rubocop_todo.yml +0 -15
  29. data/.ruby-version +0 -1
  30. data/.travis.yml +0 -87
  31. data/Gemfile +0 -40
  32. data/Rakefile +0 -45
  33. data/gemfiles/jruby_1.7.gemfile +0 -11
  34. data/gemfiles/jruby_9.0.gemfile +0 -7
  35. data/gemfiles/jruby_9.1.gemfile +0 -3
  36. data/gemfiles/jruby_9.2.gemfile +0 -3
  37. data/gemfiles/jruby_head.gemfile +0 -3
  38. data/gemfiles/ruby_1.9.gemfile +0 -11
  39. data/gemfiles/ruby_2.0.gemfile +0 -6
  40. data/gemfiles/ruby_2.1.gemfile +0 -6
  41. data/gemfiles/ruby_2.2.gemfile +0 -3
  42. data/gemfiles/ruby_2.3.gemfile +0 -3
  43. data/gemfiles/ruby_2.4.gemfile +0 -3
  44. data/gemfiles/ruby_2.5.gemfile +0 -3
  45. data/gemfiles/ruby_2.6.gemfile +0 -9
  46. data/gemfiles/ruby_2.7.gemfile +0 -9
  47. data/gemfiles/ruby_head.gemfile +0 -9
  48. data/gemfiles/truffleruby.gemfile +0 -3
  49. data/lib/oauth2/mac_token.rb +0 -122
  50. data/oauth2.gemspec +0 -52
data/lib/oauth2/error.rb CHANGED
@@ -1,40 +1,59 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  class Error < StandardError
3
- attr_reader :response, :code, :description
5
+ attr_reader :response, :body, :code, :description
4
6
 
5
- # standard error values include:
6
- # :invalid_request, :invalid_client, :invalid_token, :invalid_grant, :unsupported_grant_type, :invalid_scope
7
+ # standard error codes include:
8
+ # 'invalid_request', 'invalid_client', 'invalid_token', 'invalid_grant', 'unsupported_grant_type', 'invalid_scope'
9
+ # response might be a Response object, or the response.parsed hash
7
10
  def initialize(response)
8
- response.error = self
9
11
  @response = response
10
-
11
- if response.parsed.is_a?(Hash)
12
- @code = response.parsed['error']
13
- @description = response.parsed['error_description']
14
- error_description = "#{@code}: #{@description}"
12
+ if response.respond_to?(:parsed)
13
+ if response.parsed.is_a?(Hash)
14
+ @code = response.parsed['error']
15
+ @description = response.parsed['error_description']
16
+ end
17
+ elsif response.is_a?(Hash)
18
+ @code = response['error']
19
+ @description = response['error_description']
15
20
  end
16
-
17
- super(error_message(response.body, :error_description => error_description))
21
+ @body = if response.respond_to?(:body)
22
+ response.body
23
+ else
24
+ @response
25
+ end
26
+ message_opts = parse_error_description(@code, @description)
27
+ super(error_message(@body, message_opts))
18
28
  end
19
29
 
20
- # Makes a error message
21
- # @param [String] response_body response body of request
22
- # @param [String] opts :error_description error description to show first line
30
+ private
31
+
23
32
  def error_message(response_body, opts = {})
24
- message = []
33
+ lines = []
25
34
 
26
- opts[:error_description] && message << opts[:error_description]
35
+ lines << opts[:error_description] if opts[:error_description]
36
+
37
+ error_string = if response_body.respond_to?(:encode) && opts[:error_description].respond_to?(:encoding)
38
+ script_encoding = opts[:error_description].encoding
39
+ response_body.encode(script_encoding, invalid: :replace, undef: :replace)
40
+ else
41
+ response_body
42
+ end
43
+
44
+ lines << error_string
45
+
46
+ lines.join("\n")
47
+ end
27
48
 
28
- error_message = if opts[:error_description] && opts[:error_description].respond_to?(:encoding)
29
- script_encoding = opts[:error_description].encoding
30
- response_body.encode(script_encoding, :invalid => :replace, :undef => :replace)
31
- else
32
- response_body
33
- end
49
+ def parse_error_description(code, description)
50
+ return {} unless code || description
34
51
 
35
- message << error_message
52
+ error_description = ''
53
+ error_description += "#{code}: " if code
54
+ error_description += description if description
36
55
 
37
- message.join("\n")
56
+ {error_description: error_description}
38
57
  end
39
58
  end
40
59
  end
@@ -1,25 +1,28 @@
1
- require 'multi_json'
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
2
4
  require 'multi_xml'
3
5
  require 'rack'
4
6
 
5
7
  module OAuth2
6
8
  # OAuth2::Response class
7
9
  class Response
10
+ DEFAULT_OPTIONS = {
11
+ parse: :automatic,
12
+ snaky: true,
13
+ }.freeze
8
14
  attr_reader :response
9
- attr_accessor :error, :options
15
+ attr_accessor :options
10
16
 
11
17
  # Procs that, when called, will parse a response body according
12
18
  # to the specified format.
13
19
  @@parsers = {
14
- :json => lambda { |body| MultiJson.load(body) rescue body }, # rubocop:disable RescueModifier
15
- :query => lambda { |body| Rack::Utils.parse_query(body) },
16
- :text => lambda { |body| body },
20
+ query: ->(body) { Rack::Utils.parse_query(body) },
21
+ text: ->(body) { body },
17
22
  }
18
23
 
19
24
  # Content type assignments for various potential HTTP content types.
20
25
  @@content_types = {
21
- 'application/json' => :json,
22
- 'text/javascript' => :json,
23
26
  'application/x-www-form-urlencoded' => :query,
24
27
  'text/plain' => :text,
25
28
  }
@@ -40,12 +43,17 @@ module OAuth2
40
43
  # Initializes a Response instance
41
44
  #
42
45
  # @param [Faraday::Response] response The Faraday response instance
43
- # @param [Hash] opts options in which to initialize the instance
44
- # @option opts [Symbol] :parse (:automatic) how to parse the response body. one of :query (for x-www-form-urlencoded),
46
+ # @param [Symbol] parse (:automatic) how to parse the response body. one of :query (for x-www-form-urlencoded),
45
47
  # :json, or :automatic (determined by Content-Type response header)
46
- def initialize(response, opts = {})
48
+ # @param [true, false] snaky (true) Convert @parsed to a snake-case,
49
+ # indifferent-access SnakyHash::StringKeyed, which is a subclass of Hashie::Mash (from hashie gem)?
50
+ # @param [Hash] options all other options for initializing the instance
51
+ def initialize(response, parse: :automatic, snaky: true, **options)
47
52
  @response = response
48
- @options = {:parse => :automatic}.merge(opts)
53
+ @options = {
54
+ parse: parse,
55
+ snaky: snaky,
56
+ }.merge(options)
49
57
  end
50
58
 
51
59
  # The HTTP response headers
@@ -63,27 +71,78 @@ module OAuth2
63
71
  response.body || ''
64
72
  end
65
73
 
66
- # The parsed response body.
67
- # Will attempt to parse application/x-www-form-urlencoded and
68
- # application/json Content-Type response bodies
74
+ # The {#response} {#body} as parsed by {#parser}.
75
+ #
76
+ # @return [Object] As returned by {#parser} if it is #call-able.
77
+ # @return [nil] If the {#parser} is not #call-able.
69
78
  def parsed
70
- return nil unless @@parsers.key?(parser)
71
- @parsed ||= @@parsers[parser].call(body)
79
+ return @parsed if defined?(@parsed)
80
+
81
+ @parsed =
82
+ if parser.respond_to?(:call)
83
+ case parser.arity
84
+ when 0
85
+ parser.call
86
+ when 1
87
+ parser.call(body)
88
+ else
89
+ parser.call(body, response)
90
+ end
91
+ end
92
+
93
+ @parsed = SnakyHash::StringKeyed.new(@parsed) if options[:snaky] && @parsed.is_a?(Hash)
94
+
95
+ @parsed
72
96
  end
73
97
 
74
98
  # Attempts to determine the content type of the response.
75
99
  def content_type
76
- ((response.headers.values_at('content-type', 'Content-Type').compact.first || '').split(';').first || '').strip
100
+ return nil unless response.headers
101
+
102
+ ((response.headers.values_at('content-type', 'Content-Type').compact.first || '').split(';').first || '').strip.downcase
77
103
  end
78
104
 
79
- # Determines the parser that will be used to supply the content of #parsed
105
+ # Determines the parser (a Proc or other Object which responds to #call)
106
+ # that will be passed the {#body} (and optional {#response}) to supply
107
+ # {#parsed}.
108
+ #
109
+ # The parser can be supplied as the +:parse+ option in the form of a Proc
110
+ # (or other Object responding to #call) or a Symbol. In the latter case,
111
+ # the actual parser will be looked up in {@@parsers} by the supplied Symbol.
112
+ #
113
+ # If no +:parse+ option is supplied, the lookup Symbol will be determined
114
+ # by looking up {#content_type} in {@@content_types}.
115
+ #
116
+ # If {#parser} is a Proc, it will be called with no arguments, just
117
+ # {#body}, or {#body} and {#response}, depending on the Proc's arity.
118
+ #
119
+ # @return [Proc, #call] If a parser was found.
120
+ # @return [nil] If no parser was found.
80
121
  def parser
81
- return options[:parse].to_sym if @@parsers.key?(options[:parse])
82
- @@content_types[content_type]
122
+ return @parser if defined?(@parser)
123
+
124
+ @parser =
125
+ if options[:parse].respond_to?(:call)
126
+ options[:parse]
127
+ elsif options[:parse]
128
+ @@parsers[options[:parse].to_sym]
129
+ end
130
+
131
+ @parser ||= @@parsers[@@content_types[content_type]]
83
132
  end
84
133
  end
85
134
  end
86
135
 
87
- OAuth2::Response.register_parser(:xml, ['text/xml', 'application/rss+xml', 'application/rdf+xml', 'application/atom+xml']) do |body|
88
- MultiXml.parse(body) rescue body # rubocop:disable RescueModifier
136
+ OAuth2::Response.register_parser(:xml, ['text/xml', 'application/rss+xml', 'application/rdf+xml', 'application/atom+xml', 'application/xml']) do |body|
137
+ next body unless body.respond_to?(:to_str)
138
+
139
+ MultiXml.parse(body)
140
+ end
141
+
142
+ OAuth2::Response.register_parser(:json, ['application/json', 'text/javascript', 'application/hal+json', 'application/vnd.collection+json', 'application/vnd.api+json', 'application/problem+json']) do |body|
143
+ next body unless body.respond_to?(:to_str)
144
+
145
+ body = body.dup.force_encoding(::Encoding::ASCII_8BIT) if body.respond_to?(:force_encoding)
146
+
147
+ ::JSON.parse(body)
89
148
  end
@@ -1,22 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'jwt'
2
4
 
3
5
  module OAuth2
4
6
  module Strategy
5
7
  # The Client Assertion Strategy
6
8
  #
7
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.3
9
+ # @see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-10#section-4.1.3
8
10
  #
9
11
  # Sample usage:
10
12
  # client = OAuth2::Client.new(client_id, client_secret,
11
- # :site => 'http://localhost:8080')
13
+ # :site => 'http://localhost:8080',
14
+ # :auth_scheme => :request_body)
15
+ #
16
+ # claim_set = {
17
+ # :iss => "http://localhost:3001",
18
+ # :aud => "http://localhost:8080/oauth2/token",
19
+ # :sub => "me@example.com",
20
+ # :exp => Time.now.utc.to_i + 3600,
21
+ # }
12
22
  #
13
- # params = {:hmac_secret => "some secret",
14
- # # or :private_key => "private key string",
15
- # :iss => "http://localhost:3001",
16
- # :prn => "me@here.com",
17
- # :exp => Time.now.utc.to_i + 3600}
23
+ # encoding = {
24
+ # :algorithm => 'HS256',
25
+ # :key => 'secret_key',
26
+ # }
18
27
  #
19
- # access = client.assertion.get_token(params)
28
+ # access = client.assertion.get_token(claim_set, encoding)
20
29
  # access.token # actual access_token string
21
30
  # access.get("/api/stuff") # making api calls with access token in header
22
31
  #
@@ -30,45 +39,63 @@ module OAuth2
30
39
 
31
40
  # Retrieve an access token given the specified client.
32
41
  #
33
- # @param [Hash] params assertion params
34
- # pass either :hmac_secret or :private_key, but not both.
42
+ # @param [Hash] claims the hash representation of the claims that should be encoded as a JWT (JSON Web Token)
43
+ #
44
+ # For reading on JWT and claim keys:
45
+ # @see https://github.com/jwt/ruby-jwt
46
+ # @see https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
47
+ # @see https://datatracker.ietf.org/doc/html/rfc7523#section-3
48
+ # @see https://www.iana.org/assignments/jwt/jwt.xhtml
49
+ #
50
+ # There are many possible claim keys, and applications may ask for their own custom keys.
51
+ # Some typically required ones:
52
+ # :iss (issuer)
53
+ # :aud (audience)
54
+ # :sub (subject) -- formerly :prn https://datatracker.ietf.org/doc/html/draft-ietf-oauth-json-web-token-06#appendix-F
55
+ # :exp, (expiration time) -- in seconds, e.g. Time.now.utc.to_i + 3600
56
+ #
57
+ # Note that this method does *not* validate presence of those four claim keys indicated as required by RFC 7523.
58
+ # There are endpoints that may not conform with this RFC, and this gem should still work for those use cases.
59
+ #
60
+ # @param [Hash] encoding_opts a hash containing instructions on how the JWT should be encoded
61
+ # @option algorithm [String] the algorithm with which you would like the JWT to be encoded
62
+ # @option key [Object] the key with which you would like to encode the JWT
35
63
  #
36
- # params :hmac_secret, secret string.
37
- # params :private_key, private key string.
64
+ # These two options are passed directly to `JWT.encode`. For supported encoding arguments:
65
+ # @see https://github.com/jwt/ruby-jwt#algorithms-and-usage
66
+ # @see https://datatracker.ietf.org/doc/html/rfc7518#section-3.1
38
67
  #
39
- # params :iss, issuer
40
- # params :aud, audience, optional
41
- # params :prn, principal, current user
42
- # params :exp, expired at, in seconds, like Time.now.utc.to_i + 3600
68
+ # The object type of `:key` may depend on the value of `:algorithm`. Sample arguments:
69
+ # get_token(claim_set, {:algorithm => 'HS256', :key => 'secret_key'})
70
+ # get_token(claim_set, {:algorithm => 'RS256', :key => OpenSSL::PKCS12.new(File.read('my_key.p12'), 'not_secret')})
43
71
  #
44
- # @param [Hash] opts options
45
- def get_token(params = {}, opts = {})
46
- hash = build_request(params)
47
- @client.get_token(hash, opts.merge('refresh_token' => nil))
72
+ # @param [Hash] request_opts options that will be used to assemble the request
73
+ # @option request_opts [String] :scope the url parameter `scope` that may be required by some endpoints
74
+ # @see https://datatracker.ietf.org/doc/html/rfc7521#section-4.1
75
+ #
76
+ # @param [Hash] response_opts this will be merged with the token response to create the AccessToken object
77
+ # @see the access_token_opts argument to Client#get_token
78
+
79
+ def get_token(claims, encoding_opts, request_opts = {}, response_opts = {})
80
+ assertion = build_assertion(claims, encoding_opts)
81
+ params = build_request(assertion, request_opts)
82
+
83
+ @client.get_token(params, response_opts)
48
84
  end
49
85
 
50
- def build_request(params)
51
- assertion = build_assertion(params)
86
+ private
87
+
88
+ def build_request(assertion, request_opts = {})
52
89
  {
53
- :grant_type => 'assertion',
54
- :assertion_type => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
55
- :assertion => assertion,
56
- :scope => params[:scope],
57
- }
90
+ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
91
+ assertion: assertion,
92
+ }.merge(request_opts)
58
93
  end
59
94
 
60
- def build_assertion(params)
61
- claims = {
62
- :iss => params[:iss],
63
- :aud => params[:aud],
64
- :prn => params[:prn],
65
- :exp => params[:exp],
66
- }
67
- if params[:hmac_secret]
68
- JWT.encode(claims, params[:hmac_secret], 'HS256')
69
- elsif params[:private_key]
70
- JWT.encode(claims, params[:private_key], 'RS256')
71
- end
95
+ def build_assertion(claims, encoding_opts)
96
+ raise ArgumentError.new(message: 'Please provide an encoding_opts hash with :algorithm and :key') if !encoding_opts.is_a?(Hash) || (%i[algorithm key] - encoding_opts.keys).any?
97
+
98
+ JWT.encode(claims, encoding_opts[:key], encoding_opts[:algorithm])
72
99
  end
73
100
  end
74
101
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  # The Authorization Code Strategy
4
6
  #
5
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.1
7
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.1
6
8
  class AuthCode < Base
7
9
  # The required query parameters for the authorize URL
8
10
  #
@@ -15,6 +17,7 @@ module OAuth2
15
17
  #
16
18
  # @param [Hash] params additional query parameters for the URL
17
19
  def authorize_url(params = {})
20
+ assert_valid_params(params)
18
21
  @client.authorize_url(authorize_params.merge(params))
19
22
  end
20
23
 
@@ -22,12 +25,22 @@ module OAuth2
22
25
  #
23
26
  # @param [String] code The Authorization Code value
24
27
  # @param [Hash] params additional params
25
- # @param [Hash] opts options
28
+ # @param [Hash] opts access_token_opts, @see Client#get_token
26
29
  # @note that you must also provide a :redirect_uri with most OAuth 2.0 providers
27
30
  def get_token(code, params = {}, opts = {})
28
31
  params = {'grant_type' => 'authorization_code', 'code' => code}.merge(@client.redirection_params).merge(params)
32
+ params_dup = params.dup
33
+ params.each_key do |key|
34
+ params_dup[key.to_s] = params_dup.delete(key) if key.is_a?(Symbol)
35
+ end
36
+
37
+ @client.get_token(params_dup, opts)
38
+ end
39
+
40
+ private
29
41
 
30
- @client.get_token(params, opts)
42
+ def assert_valid_params(params)
43
+ raise(ArgumentError, 'client_secret is not allowed in authorize URL query params') if params.key?(:client_secret) || params.key?('client_secret')
31
44
  end
32
45
  end
33
46
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  class Base
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  # The Client Credentials Strategy
4
6
  #
5
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.4
7
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.4
6
8
  class ClientCredentials < Base
7
9
  # Not used for this strategy
8
10
  #
@@ -17,7 +19,7 @@ module OAuth2
17
19
  # @param [Hash] opts options
18
20
  def get_token(params = {}, opts = {})
19
21
  params = params.merge('grant_type' => 'client_credentials')
20
- @client.get_token(params, opts.merge('refresh_token' => nil))
22
+ @client.get_token(params, opts)
21
23
  end
22
24
  end
23
25
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  # The Implicit Strategy
4
6
  #
5
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-26#section-4.2
7
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26#section-4.2
6
8
  class Implicit < Base
7
9
  # The required query parameters for the authorize URL
8
10
  #
@@ -15,6 +17,7 @@ module OAuth2
15
17
  #
16
18
  # @param [Hash] params additional query parameters for the URL
17
19
  def authorize_url(params = {})
20
+ assert_valid_params(params)
18
21
  @client.authorize_url(authorize_params.merge(params))
19
22
  end
20
23
 
@@ -24,6 +27,12 @@ module OAuth2
24
27
  def get_token(*)
25
28
  raise(NotImplementedError, 'The token is accessed differently in this strategy')
26
29
  end
30
+
31
+ private
32
+
33
+ def assert_valid_params(params)
34
+ raise(ArgumentError, 'client_secret is not allowed in authorize URL query params') if params.key?(:client_secret) || params.key?('client_secret')
35
+ end
27
36
  end
28
37
  end
29
38
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  # The Resource Owner Password Credentials Authorization Strategy
4
6
  #
5
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.3
7
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.3
6
8
  class Password < Base
7
9
  # Not used for this strategy
8
10
  #
@@ -18,8 +20,8 @@ module OAuth2
18
20
  # @param [Hash] params additional params
19
21
  def get_token(username, password, params = {}, opts = {})
20
22
  params = {'grant_type' => 'password',
21
- 'username' => username,
22
- 'password' => password}.merge(params)
23
+ 'username' => username,
24
+ 'password' => password}.merge(params)
23
25
  @client.get_token(params, opts)
24
26
  end
25
27
  end
@@ -1,59 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Version
3
- module_function
4
-
5
- # The major version
6
- #
7
- # @return [Integer]
8
- def major
9
- 1
10
- end
11
-
12
- # The minor version
13
- #
14
- # @return [Integer]
15
- def minor
16
- 4
17
- end
18
-
19
- # The patch version
20
- #
21
- # @return [Integer]
22
- def patch
23
- 3
24
- end
25
-
26
- # The pre-release version, if any
27
- #
28
- # @return [Integer, NilClass]
29
- def pre
30
- nil
31
- end
32
-
33
- # The version number as a hash
34
- #
35
- # @return [Hash]
36
- def to_h
37
- {
38
- :major => major,
39
- :minor => minor,
40
- :patch => patch,
41
- :pre => pre,
42
- }
43
- end
44
-
45
- # The version number as an array
46
- #
47
- # @return [Array]
48
- def to_a
49
- [major, minor, patch, pre].compact
50
- end
51
-
52
- # The version number as a string
53
- #
54
- # @return [String]
55
- def to_s
56
- to_a.join('.')
57
- end
5
+ VERSION = '2.0.8'.freeze
58
6
  end
59
7
  end
data/lib/oauth2.rb CHANGED
@@ -1,3 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # includes modules from stdlib
4
+ require 'cgi'
5
+ require 'time'
6
+
7
+ # third party gems
8
+ require 'snaky_hash'
9
+ require 'version_gem'
10
+
11
+ # includes gem files
12
+ require 'oauth2/version'
1
13
  require 'oauth2/error'
2
14
  require 'oauth2/authenticator'
3
15
  require 'oauth2/client'
@@ -8,5 +20,21 @@ require 'oauth2/strategy/password'
8
20
  require 'oauth2/strategy/client_credentials'
9
21
  require 'oauth2/strategy/assertion'
10
22
  require 'oauth2/access_token'
11
- require 'oauth2/mac_token'
12
23
  require 'oauth2/response'
24
+
25
+ # The namespace of this library
26
+ module OAuth2
27
+ DEFAULT_CONFIG = SnakyHash::SymbolKeyed.new(silence_extra_tokens_warning: false)
28
+ @config = DEFAULT_CONFIG.dup
29
+ class << self
30
+ attr_accessor :config
31
+ end
32
+ def configure
33
+ yield @config
34
+ end
35
+ module_function :configure
36
+ end
37
+
38
+ OAuth2::Version.class_eval do
39
+ extend VersionGem::Basic
40
+ end