oauth2 1.4.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,130 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'base64'
4
- require 'digest'
5
- require 'openssl'
6
- require 'securerandom'
7
-
8
- module OAuth2
9
- class MACToken < AccessToken
10
- # Generates a MACToken from an AccessToken and secret
11
- #
12
- # @param [AccessToken] token the OAuth2::Token instance
13
- # @option [String] secret the secret key value
14
- # @param [Hash] opts the options to create the Access Token with
15
- # @see MACToken#initialize
16
- def self.from_access_token(token, secret, options = {})
17
- new(token.client, token.token, secret, token.params.merge(:refresh_token => token.refresh_token, :expires_in => token.expires_in, :expires_at => token.expires_at).merge(options))
18
- end
19
-
20
- attr_reader :secret, :algorithm
21
-
22
- # Initalize a MACToken
23
- #
24
- # @param [Client] client the OAuth2::Client instance
25
- # @param [String] token the Access Token value
26
- # @option [String] secret the secret key value
27
- # @param [Hash] opts the options to create the Access Token with
28
- # @option opts [String] :refresh_token (nil) the refresh_token value
29
- # @option opts [FixNum, String] :expires_in (nil) the number of seconds in which the AccessToken will expire
30
- # @option opts [FixNum, String] :expires_at (nil) the epoch time in seconds in which AccessToken will expire
31
- # @option opts [FixNum, String] :algorithm (hmac-sha-256) the algorithm to use for the HMAC digest (one of 'hmac-sha-256', 'hmac-sha-1')
32
- def initialize(client, token, secret, opts = {})
33
- @secret = secret
34
- self.algorithm = opts.delete(:algorithm) || 'hmac-sha-256'
35
-
36
- super(client, token, opts)
37
- end
38
-
39
- # Make a request with the MAC Token
40
- #
41
- # @param [Symbol] verb the HTTP request method
42
- # @param [String] path the HTTP URL path of the request
43
- # @param [Hash] opts the options to make the request with
44
- # @see Client#request
45
- def request(verb, path, opts = {}, &block)
46
- url = client.connection.build_url(path, opts[:params]).to_s
47
-
48
- opts[:headers] ||= {}
49
- opts[:headers]['Authorization'] = header(verb, url)
50
-
51
- @client.request(verb, path, opts, &block)
52
- end
53
-
54
- # Get the headers hash (always an empty hash)
55
- def headers
56
- {}
57
- end
58
-
59
- # Generate the MAC header
60
- #
61
- # @param [Symbol] verb the HTTP request method
62
- # @param [String] url the HTTP URL path of the request
63
- def header(verb, url)
64
- timestamp = Time.now.utc.to_i
65
- nonce = Digest::MD5.hexdigest([timestamp, SecureRandom.hex].join(':'))
66
-
67
- uri = URI.parse(url)
68
-
69
- raise(ArgumentError, "could not parse \"#{url}\" into URI") unless uri.is_a?(URI::HTTP)
70
-
71
- mac = signature(timestamp, nonce, verb, uri)
72
-
73
- "MAC id=\"#{token}\", ts=\"#{timestamp}\", nonce=\"#{nonce}\", mac=\"#{mac}\""
74
- end
75
-
76
- # Generate the Base64-encoded HMAC digest signature
77
- #
78
- # @param [Fixnum] timestamp the timestamp of the request in seconds since epoch
79
- # @param [String] nonce the MAC header nonce
80
- # @param [Symbol] verb the HTTP request method
81
- # @param [String] url the HTTP URL path of the request
82
- def signature(timestamp, nonce, verb, uri)
83
- signature = [
84
- timestamp,
85
- nonce,
86
- verb.to_s.upcase,
87
- uri.request_uri,
88
- uri.host,
89
- uri.port,
90
- '', nil
91
- ].join("\n")
92
-
93
- strict_encode64(OpenSSL::HMAC.digest(@algorithm, secret, signature))
94
- end
95
-
96
- # Set the HMAC algorithm
97
- #
98
- # @param [String] alg the algorithm to use (one of 'hmac-sha-1', 'hmac-sha-256')
99
- def algorithm=(alg)
100
- @algorithm = case alg.to_s
101
- when 'hmac-sha-1'
102
- begin
103
- OpenSSL::Digest('SHA1').new
104
- rescue StandardError
105
- OpenSSL::Digest.new('SHA1')
106
- end
107
- when 'hmac-sha-256'
108
- begin
109
- OpenSSL::Digest('SHA256').new
110
- rescue StandardError
111
- OpenSSL::Digest.new('SHA256')
112
- end
113
- else
114
- raise(ArgumentError, 'Unsupported algorithm')
115
- end
116
- end
117
-
118
- private
119
-
120
- # No-op since we need the verb and path
121
- # and the MAC always goes in a header
122
- def token=(_noop)
123
- end
124
-
125
- # Base64.strict_encode64 is not available on Ruby 1.8.7
126
- def strict_encode64(str)
127
- Base64.encode64(str).delete("\n")
128
- end
129
- end
130
- end
@@ -1,11 +0,0 @@
1
- # RS256
2
-
3
- ## How keys were made
4
-
5
- ```shell
6
- # No passphrase
7
- # Generates the public and private keys:
8
- ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key
9
- # Converts the key to PEM format
10
- openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
11
- ```
@@ -1,51 +0,0 @@
1
- -----BEGIN RSA PRIVATE KEY-----
2
- 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
- +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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- AKam28UZaOb0qK+00cQQD8fulY9rKtSL10LvJFWUOa/SJyLvk9vUmfvFn182il1n
12
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 3C1Qz/3iv/S3/ktgmqGhQiqybkkHZcbqTXB2wxrx+aaLS7PEfYiuYCrPbX93160k
48
- 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
- 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
- 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
51
- -----END RSA PRIVATE KEY-----
@@ -1,14 +0,0 @@
1
- -----BEGIN PUBLIC KEY-----
2
- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5hdXV/4YSymY1T9VNvK2
3
- bWRfulwIty1RnAPNINQmfh3aRRkV+PNrbC2Crji9G0AHmQwgW1bZ3kgkkpIm6RVn
4
- 44fHvBvuXkZ9ABgXw0d2cLIHmwOFxSKmWAm/EW//GszUTLLLsMZUe2udtFJW0jxX
5
- B2GRY0WVYuo6Oo58RCeP719lw3Ags0YF9/IobxKkGd4BautUPw6ZszAa3o+j0zR7
6
- 4x7ouPxybZAOuPsMxqanyeYJeH4osJjLMYV9qem9uG2sj7GENJ8UszcpmGbqxBhe
7
- xPEB7mgDeONIF0XJF23zdOf8ANE5mAU2h2v7M6moAfkdUzJ+j48+VT2omHAzAL5y
8
- Ncmrl2xiWdyoxOw1Y1UmfEmJYV5VgGYyZ12JZRKY+szPT+vR+MDuYxbquF40O7kv
9
- kFNBfL1yCpzfSQCLnEs4rX8qRzZXciLeyq4Ht5FLuRFgxjA//XI8LAmp0u7gk+Q7
10
- FUH1UgW3kmJDTG0XaxQxYTBSIO7mcmyjDyBgKVuQmt5E1ycFeteOVdPD/CG/fPYh
11
- thvc4UytEFwsMdNy3iD6/wuUH68tAKam28UZaOb0qK+00cQQD8fulY9rKtSL10Lv
12
- JFWUOa/SJyLvk9vUmfvFn182il1nX6GpyxyMmE/FCnH4CT/DjrSZf08mOO8eL5of
13
- YHMK/oiXr1eODqx+pOwClNsCAwEAAQ==
14
- -----END PUBLIC KEY-----
data/spec/helper.rb DELETED
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- DEBUG = ENV['DEBUG'] == 'true'
4
- RUN_COVERAGE = ENV['CI_CODECOV'] || ENV['CI'].nil?
5
-
6
- ruby_version = Gem::Version.new(RUBY_VERSION)
7
- minimum_version = ->(version) { ruby_version >= Gem::Version.new(version) && RUBY_ENGINE == 'ruby' }
8
- coverage = minimum_version.call('2.7') && RUN_COVERAGE
9
- debug = minimum_version.call('2.5') && DEBUG
10
-
11
- require 'simplecov' if coverage
12
- require 'byebug' if debug
13
-
14
- require 'oauth2'
15
- require 'addressable/uri'
16
- require 'rspec'
17
- require 'rspec/stubbed_env'
18
- require 'rspec/pending_for'
19
- require 'silent_stream'
20
-
21
- RSpec.configure do |config|
22
- config.expect_with :rspec do |c|
23
- c.syntax = :expect
24
- end
25
- end
26
-
27
- Faraday.default_adapter = :test
28
-
29
- RSpec.configure do |conf|
30
- conf.include SilentStream
31
- end
32
-
33
- VERBS = [:get, :post, :put, :delete].freeze
@@ -1,218 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe OAuth2::AccessToken do
4
- subject { described_class.new(client, token) }
5
-
6
- let(:token) { 'monkey' }
7
- let(:refresh_body) { MultiJson.encode(:access_token => 'refreshed_foo', :expires_in => 600, :refresh_token => 'refresh_bar') }
8
- let(:client) do
9
- OAuth2::Client.new('abc', 'def', :site => 'https://api.example.com') do |builder|
10
- builder.request :url_encoded
11
- builder.adapter :test do |stub|
12
- VERBS.each do |verb|
13
- stub.send(verb, '/token/header') { |env| [200, {}, env[:request_headers]['Authorization']] }
14
- stub.send(verb, "/token/query?access_token=#{token}") { |env| [200, {}, Addressable::URI.parse(env[:url]).query_values['access_token']] }
15
- stub.send(verb, '/token/query_string') { |env| [200, {}, CGI.unescape(Addressable::URI.parse(env[:url]).query)] }
16
- stub.send(verb, '/token/body') { |env| [200, {}, env[:body]] }
17
- end
18
- stub.post('/oauth/token') { |env| [200, {'Content-Type' => 'application/json'}, refresh_body] }
19
- end
20
- end
21
- end
22
-
23
- describe '#initialize' do
24
- it 'assigns client and token' do
25
- expect(subject.client).to eq(client)
26
- expect(subject.token).to eq(token)
27
- end
28
-
29
- it 'assigns extra params' do
30
- target = described_class.new(client, token, 'foo' => 'bar')
31
- expect(target.params).to include('foo')
32
- expect(target.params['foo']).to eq('bar')
33
- end
34
-
35
- def assert_initialized_token(target)
36
- expect(target.token).to eq(token)
37
- expect(target).to be_expires
38
- expect(target.params.keys).to include('foo')
39
- expect(target.params['foo']).to eq('bar')
40
- end
41
-
42
- it 'initializes with a Hash' do
43
- hash = {:access_token => token, :expires_at => Time.now.to_i + 200, 'foo' => 'bar'}
44
- target = described_class.from_hash(client, hash)
45
- assert_initialized_token(target)
46
- end
47
-
48
- it 'from_hash does not modify opts hash' do
49
- hash = {:access_token => token, :expires_at => Time.now.to_i}
50
- hash_before = hash.dup
51
- described_class.from_hash(client, hash)
52
- expect(hash).to eq(hash_before)
53
- end
54
-
55
- it 'initializes with a form-urlencoded key/value string' do
56
- kvform = "access_token=#{token}&expires_at=#{Time.now.to_i + 200}&foo=bar"
57
- target = described_class.from_kvform(client, kvform)
58
- assert_initialized_token(target)
59
- end
60
-
61
- it 'sets options' do
62
- target = described_class.new(client, token, :param_name => 'foo', :header_format => 'Bearer %', :mode => :body)
63
- expect(target.options[:param_name]).to eq('foo')
64
- expect(target.options[:header_format]).to eq('Bearer %')
65
- expect(target.options[:mode]).to eq(:body)
66
- end
67
-
68
- it 'does not modify opts hash' do
69
- opts = {:param_name => 'foo', :header_format => 'Bearer %', :mode => :body}
70
- opts_before = opts.dup
71
- described_class.new(client, token, opts)
72
- expect(opts).to eq(opts_before)
73
- end
74
-
75
- describe 'expires_at' do
76
- let(:expires_at) { 1_361_396_829 }
77
- let(:hash) do
78
- {
79
- :access_token => token,
80
- :expires_at => expires_at.to_s,
81
- 'foo' => 'bar',
82
- }
83
- end
84
-
85
- it 'initializes with an integer timestamp expires_at' do
86
- target = described_class.from_hash(client, hash.merge(:expires_at => expires_at))
87
- assert_initialized_token(target)
88
- expect(target.expires_at).to eql(expires_at)
89
- end
90
-
91
- it 'initializes with a string timestamp expires_at' do
92
- target = described_class.from_hash(client, hash)
93
- assert_initialized_token(target)
94
- expect(target.expires_at).to eql(expires_at)
95
- end
96
-
97
- it 'initializes with a string time expires_at' do
98
- target = described_class.from_hash(client, hash.merge(:expires_at => Time.at(expires_at).iso8601))
99
- assert_initialized_token(target)
100
- expect(target.expires_at).to eql(expires_at)
101
- end
102
- end
103
- end
104
-
105
- describe '#request' do
106
- context 'with :mode => :header' do
107
- before do
108
- subject.options[:mode] = :header
109
- end
110
-
111
- VERBS.each do |verb|
112
- it "sends the token in the Authorization header for a #{verb.to_s.upcase} request" do
113
- expect(subject.post('/token/header').body).to include(token)
114
- end
115
- end
116
- end
117
-
118
- context 'with :mode => :query' do
119
- before do
120
- subject.options[:mode] = :query
121
- end
122
-
123
- VERBS.each do |verb|
124
- it "sends the token in the Authorization header for a #{verb.to_s.upcase} request" do
125
- expect(subject.post('/token/query').body).to eq(token)
126
- end
127
-
128
- it "sends a #{verb.to_s.upcase} request and options[:param_name] include [number]." do
129
- subject.options[:param_name] = 'auth[1]'
130
- expect(subject.__send__(verb, '/token/query_string').body).to include("auth[1]=#{token}")
131
- end
132
- end
133
- end
134
-
135
- context 'with :mode => :body' do
136
- before do
137
- subject.options[:mode] = :body
138
- end
139
-
140
- VERBS.each do |verb|
141
- it "sends the token in the Authorization header for a #{verb.to_s.upcase} request" do
142
- expect(subject.post('/token/body').body.split('=').last).to eq(token)
143
- end
144
- end
145
- end
146
-
147
- context 'params include [number]' do
148
- VERBS.each do |verb|
149
- it "sends #{verb.to_s.upcase} correct query" do
150
- expect(subject.__send__(verb, '/token/query_string', :params => {'foo[bar][1]' => 'val'}).body).to include('foo[bar][1]=val')
151
- end
152
- end
153
- end
154
- end
155
-
156
- describe '#expires?' do
157
- it 'is false if there is no expires_at' do
158
- expect(described_class.new(client, token)).not_to be_expires
159
- end
160
-
161
- it 'is true if there is an expires_in' do
162
- expect(described_class.new(client, token, :refresh_token => 'abaca', :expires_in => 600)).to be_expires
163
- end
164
-
165
- it 'is true if there is an expires_at' do
166
- expect(described_class.new(client, token, :refresh_token => 'abaca', :expires_in => Time.now.getutc.to_i + 600)).to be_expires
167
- end
168
- end
169
-
170
- describe '#expired?' do
171
- it 'is false if there is no expires_in or expires_at' do
172
- expect(described_class.new(client, token)).not_to be_expired
173
- end
174
-
175
- it 'is false if expires_in is in the future' do
176
- expect(described_class.new(client, token, :refresh_token => 'abaca', :expires_in => 10_800)).not_to be_expired
177
- end
178
-
179
- it 'is true if expires_at is in the past' do
180
- access = described_class.new(client, token, :refresh_token => 'abaca', :expires_in => 600)
181
- @now = Time.now + 10_800
182
- allow(Time).to receive(:now).and_return(@now)
183
- expect(access).to be_expired
184
- end
185
- end
186
-
187
- describe '#refresh!' do
188
- let(:access) do
189
- described_class.new(client, token, :refresh_token => 'abaca',
190
- :expires_in => 600,
191
- :param_name => 'o_param')
192
- end
193
-
194
- it 'returns a refresh token with appropriate values carried over' do
195
- refreshed = access.refresh!
196
- expect(access.client).to eq(refreshed.client)
197
- expect(access.options[:param_name]).to eq(refreshed.options[:param_name])
198
- end
199
-
200
- context 'with a nil refresh_token in the response' do
201
- let(:refresh_body) { MultiJson.encode(:access_token => 'refreshed_foo', :expires_in => 600, :refresh_token => nil) }
202
-
203
- it 'copies the refresh_token from the original token' do
204
- refreshed = access.refresh!
205
-
206
- expect(refreshed.refresh_token).to eq(access.refresh_token)
207
- end
208
- end
209
- end
210
-
211
- describe '#to_hash' do
212
- it 'return a hash equals to the hash used to initialize access token' do
213
- hash = {:access_token => token, :refresh_token => 'foobar', :expires_at => Time.now.to_i + 200, 'foo' => 'bar'}
214
- access_token = described_class.from_hash(client, hash.clone)
215
- expect(access_token.to_hash).to eq(hash)
216
- end
217
- end
218
- end
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe OAuth2::Authenticator do
4
- subject do
5
- described_class.new(client_id, client_secret, mode)
6
- end
7
-
8
- let(:client_id) { 'foo' }
9
- let(:client_secret) { 'bar' }
10
- let(:mode) { :undefined }
11
-
12
- it 'raises NotImplementedError for unknown authentication mode' do
13
- expect { subject.apply({}) }.to raise_error(NotImplementedError)
14
- end
15
-
16
- describe '#apply' do
17
- context 'with parameter-based authentication' do
18
- let(:mode) { :request_body }
19
-
20
- it 'adds client_id and client_secret to params' do
21
- output = subject.apply({})
22
- expect(output).to eq('client_id' => 'foo', 'client_secret' => 'bar')
23
- end
24
-
25
- it 'does not overwrite existing credentials' do
26
- input = {'client_secret' => 's3cr3t'}
27
- output = subject.apply(input)
28
- expect(output).to eq('client_id' => 'foo', 'client_secret' => 's3cr3t')
29
- end
30
-
31
- it 'preserves other parameters' do
32
- input = {'state' => '42', :headers => {'A' => 'b'}}
33
- output = subject.apply(input)
34
- expect(output).to eq(
35
- 'client_id' => 'foo',
36
- 'client_secret' => 'bar',
37
- 'state' => '42',
38
- :headers => {'A' => 'b'}
39
- )
40
- end
41
-
42
- context 'using tls client authentication' do
43
- let(:mode) { :tls_client_auth }
44
-
45
- it 'does not add client_secret' do
46
- output = subject.apply({})
47
- expect(output).to eq('client_id' => 'foo')
48
- end
49
- end
50
-
51
- context 'using private key jwt authentication' do
52
- let(:mode) { :private_key_jwt }
53
-
54
- it 'does not add client_secret or client_id' do
55
- output = subject.apply({})
56
- expect(output).to eq({})
57
- end
58
- end
59
- end
60
-
61
- context 'with Basic authentication' do
62
- let(:mode) { :basic_auth }
63
- let(:header) { 'Basic ' + Base64.encode64("#{client_id}:#{client_secret}").delete("\n") }
64
-
65
- it 'encodes credentials in headers' do
66
- output = subject.apply({})
67
- expect(output).to eq(:headers => {'Authorization' => header})
68
- end
69
-
70
- it 'does not overwrite existing credentials' do
71
- input = {:headers => {'Authorization' => 'Bearer abc123'}}
72
- output = subject.apply(input)
73
- expect(output).to eq(:headers => {'Authorization' => 'Bearer abc123'})
74
- end
75
-
76
- it 'does not overwrite existing params or headers' do
77
- input = {'state' => '42', :headers => {'A' => 'b'}}
78
- output = subject.apply(input)
79
- expect(output).to eq(
80
- 'state' => '42',
81
- :headers => {'A' => 'b', 'Authorization' => header}
82
- )
83
- end
84
- end
85
- end
86
- end