simple_oauth-0.2.0/0000755000004100000410000000000012060312235014224 5ustar www-datawww-datasimple_oauth-0.2.0/.travis.yml0000644000004100000410000000020012060312235016325 0ustar www-datawww-datalanguage: ruby rvm: - rbx-18mode - rbx-19mode - jruby-18mode - jruby-19mode - 1.8.7 - 1.9.2 - 1.9.3 - ruby-head simple_oauth-0.2.0/CONTRIBUTING.md0000644000004100000410000000043312060312235016455 0ustar www-datawww-data## Contributing 1. Fork the project. 2. Create a topic branch. 3. Add failing tests. 4. Add code to pass the failing tests. 5. Run `bundle exec rake`. If failing, repeat step 4. 6. Commit and push your changes. 7. Submit a pull request. Please do not include changes to the gemspec. simple_oauth-0.2.0/simple_oauth.gemspec0000644000004100000410000000130512060312235020261 0ustar www-datawww-data# encoding: utf-8 Gem::Specification.new do |spec| spec.name = 'simple_oauth' spec.version = '0.2.0' spec.authors = ["Steve Richert", "Erik Michaels-Ober"] spec.email = ['steve.richert@gmail.com', 'sferik@gmail.com'] spec.description = 'Simply builds and verifies OAuth headers' spec.summary = spec.description spec.homepage = 'https://github.com/laserlemon/simple_oauth' spec.licenses = ['MIT'] spec.add_development_dependency 'rake' spec.add_development_dependency 'rspec', '>= 2' spec.add_development_dependency 'simplecov' spec.files = `git ls-files`.split($\) spec.test_files = spec.files.grep(/^test\//) spec.require_paths = ["lib"] end simple_oauth-0.2.0/LICENSE0000644000004100000410000000210212060312235015224 0ustar www-datawww-dataCopyright (c) 2010 Steve Richert, Erik Michaels-Ober MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. simple_oauth-0.2.0/README.md0000644000004100000410000000261712060312235015511 0ustar www-datawww-data# simple_oauth [![Build Status](https://secure.travis-ci.org/laserlemon/simple_oauth.png)](http://travis-ci.org/laserlemon/simple_oauth) [![Dependency Status](https://gemnasium.com/laserlemon/simple_oauth.png)](https://gemnasium.com/laserlemon/simple_oauth) Simply builds and verifies OAuth headers ## Supported Rubies This library aims to support and is [tested against](http://travis-ci.org/laserlemon/simple_oauth) the following Ruby implementations: * Ruby 1.8.7 * Ruby 1.9.2 * Ruby 1.9.3 * Ruby head * [JRuby](http://www.jruby.org/) * [Rubinius](http://rubini.us/) If something doesn't work on one of these interpreters, it should be considered a bug. This library may inadvertently work (or seem to work) on other Ruby implementations, however support will only be provided for the versions listed above. If you would like this library to support another Ruby version, you may volunteer to be a maintainer. Being a maintainer entails making sure all tests run and pass on that implementation. When something breaks on your implementation, you will be personally responsible for providing patches in a timely fashion. If critical issues for a particular implementation exist at the time of a major release, support for that Ruby version may be dropped. ## Copyright Copyright (c) 2010 Steve Richert, Erik Michaels-Ober. See [LICENSE](https://github.com/laserlemon/simple_oauth/blob/master/LICENSE) for details. simple_oauth-0.2.0/Rakefile0000644000004100000410000000016512060312235015673 0ustar www-datawww-datarequire 'bundler/gem_tasks' require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) task :default => :spec simple_oauth-0.2.0/spec/0000755000004100000410000000000012060312235015156 5ustar www-datawww-datasimple_oauth-0.2.0/spec/simple_oauth/0000755000004100000410000000000012060312235017647 5ustar www-datawww-datasimple_oauth-0.2.0/spec/simple_oauth/header_spec.rb0000644000004100000410000004015212060312235022440 0ustar www-datawww-data# encoding: utf-8 require 'helper' describe SimpleOAuth::Header do describe ".default_options" do let(:default_options){ SimpleOAuth::Header.default_options } it "is different every time" do expect(SimpleOAuth::Header.default_options).not_to eq default_options end it "is used for new headers" do SimpleOAuth::Header.stub(:default_options => default_options) header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {}) expect(header.options).to eq default_options end it "includes a signature method and an OAuth version" do expect(default_options[:signature_method]).not_to be_nil expect(default_options[:version]).not_to be_nil end end describe ".escape" do it "escapes (most) non-word characters" do [' ', '!', '@', '#', '$', '%', '^', '&'].each do |character| escaped = SimpleOAuth::Header.escape(character) expect(escaped).not_to eq character expect(escaped).to eq uri_parser.escape(character, /.*/) end end it "does not escape - . or ~" do ['-', '.', '~'].each do |character| escaped = SimpleOAuth::Header.escape(character) expect(escaped).to eq character end end def self.test_special_characters it "escapes non-ASCII characters" do expect(SimpleOAuth::Header.escape('é')).to eq '%C3%A9' end it "escapes multibyte characters" do expect(SimpleOAuth::Header.escape('あ')).to eq '%E3%81%82' end end if RUBY_VERSION >= '1.9' test_special_characters else %w(n N e E s S u U).each do |kcode| describe %(when $KCODE = "#{kcode}") do original_kcode = $KCODE begin $KCODE = kcode test_special_characters ensure $KCODE = original_kcode end end end end end describe ".unescape" do pending end describe ".parse" do let(:header){ SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}) } let(:parsed_options){ SimpleOAuth::Header.parse(header) } it "returns a hash" do expect(parsed_options).to be_a(Hash) end it "includes the options used to build the header" do expect(parsed_options.reject{|k,_| k == :signature }).to eq header.options end it "includes a signature" do expect(header.options).not_to have_key(:signature) expect(parsed_options).to have_key(:signature) expect(parsed_options[:signature]).not_to be_nil end it "handles optional 'linear white space'" do parsed_header_with_spaces = SimpleOAuth::Header.parse 'OAuth oauth_consumer_key="abcd", oauth_nonce="oLKtec51GQy", oauth_signature="efgh%26mnop", oauth_signature_method="PLAINTEXT", oauth_timestamp="1286977095", oauth_token="ijkl", oauth_version="1.0"' expect(parsed_header_with_spaces).to be_a_kind_of(Hash) expect(parsed_header_with_spaces.keys.size).to eq 7 parsed_header_with_tabs = SimpleOAuth::Header.parse 'OAuth oauth_consumer_key="abcd", oauth_nonce="oLKtec51GQy", oauth_signature="efgh%26mnop", oauth_signature_method="PLAINTEXT", oauth_timestamp="1286977095", oauth_token="ijkl", oauth_version="1.0"' expect(parsed_header_with_tabs).to be_a_kind_of(Hash) expect(parsed_header_with_tabs.keys.size).to eq 7 parsed_header_with_spaces_and_tabs = SimpleOAuth::Header.parse 'OAuth oauth_consumer_key="abcd", oauth_nonce="oLKtec51GQy", oauth_signature="efgh%26mnop", oauth_signature_method="PLAINTEXT", oauth_timestamp="1286977095", oauth_token="ijkl", oauth_version="1.0"' expect(parsed_header_with_spaces_and_tabs).to be_a_kind_of(Hash) expect(parsed_header_with_spaces_and_tabs.keys.size).to eq 7 parsed_header_without_spaces = SimpleOAuth::Header.parse 'OAuth oauth_consumer_key="abcd",oauth_nonce="oLKtec51GQy",oauth_signature="efgh%26mnop",oauth_signature_method="PLAINTEXT",oauth_timestamp="1286977095",oauth_token="ijkl",oauth_version="1.0"' expect(parsed_header_without_spaces).to be_a_kind_of(Hash) expect(parsed_header_without_spaces.keys.size).to eq 7 end end describe "#initialize" do let(:header){ SimpleOAuth::Header.new(:get, 'HTTPS://api.TWITTER.com:443/1/statuses/friendships.json?foo=bar#anchor', {}) } it "stringifies and uppercases the request method" do expect(header.method).to eq 'GET' end it "downcases the scheme and authority" do expect(header.url).to match %r(^https://api\.twitter\.com/) end it "ignores the query and fragment" do expect(header.url).to match %r(/1/statuses/friendships\.json$) end end describe "#valid?" do context "using the HMAC-SHA1 signature method" do it "requires consumer and token secrets" do secrets = {:consumer_secret => 'CONSUMER_SECRET', :token_secret => 'TOKEN_SECRET'} header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, secrets) parsed_header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, header) expect(parsed_header).not_to be_valid expect(parsed_header).to be_valid(secrets) end end context "using the RSA-SHA1 signature method" do it "requires an identical private key" do secrets = {:consumer_secret => rsa_private_key} header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, secrets.merge(:signature_method => 'RSA-SHA1')) parsed_header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, header) expect{ parsed_header.valid? }.to raise_error(TypeError) expect(parsed_header).to be_valid(secrets) end end context "using the RSA-SHA1 signature method" do it "requires consumer and token secrets" do secrets = {:consumer_secret => 'CONSUMER_SECRET', :token_secret => 'TOKEN_SECRET'} header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, secrets.merge(:signature_method => 'PLAINTEXT')) parsed_header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, header) expect(parsed_header).not_to be_valid expect(parsed_header).to be_valid(secrets) end end end describe "#normalized_attributes" do let(:header){ SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}) } let(:normalized_attributes){ header.send(:normalized_attributes) } it "returns a sorted-key, quoted-value and comma-separated list" do header.stub(:signed_attributes => {:d => 1, :c => 2, :b => 3, :a => 4}) expect(normalized_attributes).to eq 'a="4", b="3", c="2", d="1"' end it "URI encodes its values" do header.stub(:signed_attributes => {1 => '!', 2 => '@', 3 => '#', 4 => '$'}) expect(normalized_attributes).to eq '1="%21", 2="%40", 3="%23", 4="%24"' end end describe "#signed_attributes" do it "includes the OAuth signature" do header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}) expect(header.send(:signed_attributes)).to have_key(:oauth_signature) end end describe "#attributes" do let(:header) do options = {} SimpleOAuth::Header::ATTRIBUTE_KEYS.each{|k| options[k] = k.to_s.upcase } options[:other] = 'OTHER' SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {}, options) end let(:attributes){ header.send(:attributes) } it "prepends keys with 'oauth_'" do expect(attributes.keys).to be_all{|k| k.to_s =~ /^oauth_/ } end it "excludes keys not included in the list of valid attributes" do expect(attributes.keys).to be_all{|k| k.is_a?(Symbol) } expect(attributes).not_to have_key(:oauth_other) end it "preserves values for valid keys" do expect(attributes.size).to eq SimpleOAuth::Header::ATTRIBUTE_KEYS.size expect(attributes).to be_all{|k,v| k.to_s == "oauth_#{v.downcase}" } end end describe "#signature" do context "calls the appropriate signature method" do specify "when using HMAC-SHA1" do header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, :signature_method => 'HMAC-SHA1') header.should_receive(:hmac_sha1_signature).once.and_return('HMAC_SHA1_SIGNATURE') expect(header.send(:signature)).to eq 'HMAC_SHA1_SIGNATURE' end specify "when using RSA-SHA1" do header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, :signature_method => 'RSA-SHA1') header.should_receive(:rsa_sha1_signature).once.and_return('RSA_SHA1_SIGNATURE') expect(header.send(:signature)).to eq 'RSA_SHA1_SIGNATURE' end specify "when using PLAINTEXT" do header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, :signature_method => 'PLAINTEXT') header.should_receive(:plaintext_signature).once.and_return('PLAINTEXT_SIGNATURE') expect(header.send(:signature)).to eq 'PLAINTEXT_SIGNATURE' end end end describe "#hmac_sha1_signature" do it "reproduces a successful Twitter GET" do options = { :consumer_key => '8karQBlMg6gFOwcf8kcoYw', :consumer_secret => '3d0vcHyUiiqADpWxolW8nlDIpSWMlyK7YNgc5Qna2M', :nonce => '547fed103e122eecf84c080843eedfe6', :signature_method => 'HMAC-SHA1', :timestamp => '1286830180', :token => '201425800-Sv4sTcgoffmHGkTCue0JnURT8vrm4DiFAkeFNDkh', :token_secret => 'T5qa1tF57tfDzKmpM89DHsNuhgOY4NT6DlNLsTFcuQ' } header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, options) expect(header.to_s).to eq 'OAuth oauth_consumer_key="8karQBlMg6gFOwcf8kcoYw", oauth_nonce="547fed103e122eecf84c080843eedfe6", oauth_signature="i9CT6ahDRAlfGX3hKYf78QzXsaw%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1286830180", oauth_token="201425800-Sv4sTcgoffmHGkTCue0JnURT8vrm4DiFAkeFNDkh", oauth_version="1.0"' end it "reproduces a successful Twitter POST" do options = { :consumer_key => '8karQBlMg6gFOwcf8kcoYw', :consumer_secret => '3d0vcHyUiiqADpWxolW8nlDIpSWMlyK7YNgc5Qna2M', :nonce => 'b40a3e0f18590ecdcc0e273f7d7c82f8', :signature_method => 'HMAC-SHA1', :timestamp => '1286830181', :token => '201425800-Sv4sTcgoffmHGkTCue0JnURT8vrm4DiFAkeFNDkh', :token_secret => 'T5qa1tF57tfDzKmpM89DHsNuhgOY4NT6DlNLsTFcuQ' } header = SimpleOAuth::Header.new(:post, 'https://api.twitter.com/1/statuses/update.json', {:status => 'hi, again'}, options) expect(header.to_s).to eq 'OAuth oauth_consumer_key="8karQBlMg6gFOwcf8kcoYw", oauth_nonce="b40a3e0f18590ecdcc0e273f7d7c82f8", oauth_signature="mPqSFKejrWWk3ZT9bTQjhO5b2xI%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1286830181", oauth_token="201425800-Sv4sTcgoffmHGkTCue0JnURT8vrm4DiFAkeFNDkh", oauth_version="1.0"' end end describe "#secret" do let(:header){ SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {}) } let(:secret){ header.send(:secret) } it "combines the consumer and token secrets with an ampersand" do header.stub(:options => {:consumer_secret => 'CONSUMER_SECRET', :token_secret => 'TOKEN_SECRET'}) expect(secret).to eq 'CONSUMER_SECRET&TOKEN_SECRET' end it "URI encodes each secret value before combination" do header.stub(:options => {:consumer_secret => 'CONSUM#R_SECRET', :token_secret => 'TOKEN_S#CRET'}) expect(secret).to eq 'CONSUM%23R_SECRET&TOKEN_S%23CRET' end end describe "#signature_base" do let(:header){ SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {}) } let(:signature_base){ header.send(:signature_base) } it "combines the request method, URL and normalized parameters using ampersands" do header.stub(:method => 'METHOD', :url => 'URL', :normalized_params => 'NORMALIZED_PARAMS') expect(signature_base).to eq 'METHOD&URL&NORMALIZED_PARAMS' end it "URI encodes each value before combination" do header.stub(:method => 'ME#HOD', :url => 'U#L', :normalized_params => 'NORMAL#ZED_PARAMS') expect(signature_base).to eq 'ME%23HOD&U%23L&NORMAL%23ZED_PARAMS' end end describe "#normalized_params" do let(:header) do header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {}) header.stub(:signature_params => [['A', '4'], ['B', '3'], ['B', '2'], ['C', '1'], ['D[]', '0 ']]) header end let(:signature_params){ header.send(:signature_params) } let(:normalized_params){ header.send(:normalized_params) } it "joins key/value pairs with equal signs and ampersands" do expect(normalized_params).to be_a(String) parts = normalized_params.split('&') expect(parts.size).to eq signature_params.size pairs = parts.map{|p| p.split('=') } expect(pairs).to be_all{|p| p.size == 2 } end end describe "#signature_params" do let(:header){ SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {}) } let(:signature_params){ header.send(:signature_params) } it "combines OAuth header attributes, body parameters and URL parameters into an flattened array of key/value pairs" do header.stub( :attributes => {:attribute => 'ATTRIBUTE'}, :params => {'param' => 'PARAM'}, :url_params => [['url_param', '1'], ['url_param', '2']] ) expect(signature_params).to eq [ [:attribute, 'ATTRIBUTE'], ['param', 'PARAM'], ['url_param', '1'], ['url_param', '2'] ] end end describe "#url_params" do it "returns an empty array when the URL has no query parameters" do header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {}) expect(header.send(:url_params)).to eq [] end it "returns an array of key/value pairs for each query parameter" do header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json?test=TEST', {}) expect(header.send(:url_params)).to eq [['test', 'TEST']] end it "sorts values for repeated keys" do header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json?test=3&test=1&test=2', {}) expect(header.send(:url_params)).to eq [['test', '1'], ['test', '2'], ['test', '3']] end end describe "#rsa_sha1_signature" do it "reproduces a successful OAuth example GET" do options = { :consumer_key => 'dpf43f3p2l4k3l03', :consumer_secret => rsa_private_key, :nonce => '13917289812797014437', :signature_method => 'RSA-SHA1', :timestamp => '1196666512' } header = SimpleOAuth::Header.new(:get, 'http://photos.example.net/photos', {:file => 'vacaction.jpg', :size => 'original'}, options) expect(header.to_s).to eq 'OAuth oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="13917289812797014437", oauth_signature="jvTp%2FwX1TYtByB1m%2BPbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2%2F9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW%2F%2Fe%2BRinhejgCuzoH26dyF8iY2ZZ%2F5D1ilgeijhV%2FvBka5twt399mXwaYdCwFYE%3D", oauth_signature_method="RSA-SHA1", oauth_timestamp="1196666512", oauth_version="1.0"' end end describe "#private_key" do pending end describe "#plaintext_signature" do it "reproduces a successful OAuth example GET" do options = { :consumer_key => 'abcd', :consumer_secret => 'efgh', :nonce => 'oLKtec51GQy', :signature_method => 'PLAINTEXT', :timestamp => '1286977095', :token => 'ijkl', :token_secret => 'mnop' } header = SimpleOAuth::Header.new(:get, 'http://host.net/resource?name=value', {:name => 'value'}, options) expect(header.to_s).to eq 'OAuth oauth_consumer_key="abcd", oauth_nonce="oLKtec51GQy", oauth_signature="efgh%26mnop", oauth_signature_method="PLAINTEXT", oauth_timestamp="1286977095", oauth_token="ijkl", oauth_version="1.0"' end end end simple_oauth-0.2.0/spec/helper.rb0000644000004100000410000000061312060312235016762 0ustar www-datawww-dataunless ENV['CI'] require 'simplecov' SimpleCov.start do add_filter 'spec' end end require 'simple_oauth' require 'rspec' def uri_parser @uri_parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI end RSpec.configure do |config| config.expect_with :rspec do |c| c.syntax = :expect end end Dir[File.expand_path('../support/**/*.rb', __FILE__)].each{|f| require f } simple_oauth-0.2.0/spec/support/0000755000004100000410000000000012060312235016672 5ustar www-datawww-datasimple_oauth-0.2.0/spec/support/rsa.rb0000644000004100000410000000036412060312235020007 0ustar www-datawww-datamodule RSAHelpers PRIVATE_KEY_PATH = File.expand_path('../fixtures/rsa-private-key', __FILE__) def rsa_private_key @rsa_private_key ||= File.read(PRIVATE_KEY_PATH) end end RSpec.configure do |config| config.include RSAHelpers end simple_oauth-0.2.0/spec/support/fixtures/0000755000004100000410000000000012060312235020543 5ustar www-datawww-datasimple_oauth-0.2.0/spec/support/fixtures/rsa-private-key0000644000004100000410000000162312060312235023513 0ustar www-datawww-data-----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d 7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+ 3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8 AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54 Lw03eHTNQghS0A== -----END PRIVATE KEY-----simple_oauth-0.2.0/.rspec0000644000004100000410000000004312060312235015336 0ustar www-datawww-data--color --fail-fast --order random simple_oauth-0.2.0/.gemtest0000644000004100000410000000000012060312235015663 0ustar www-datawww-datasimple_oauth-0.2.0/metadata.yml0000644000004100000410000000475012060312235016535 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: simple_oauth version: !ruby/object:Gem::Version prerelease: version: 0.2.0 platform: ruby authors: - Steve Richert - Erik Michaels-Ober autorequire: bindir: bin cert_chain: [] date: 2012-12-02 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency version_requirements: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' none: false name: rake type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' none: false - !ruby/object:Gem::Dependency version_requirements: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '2' none: false name: rspec type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '2' none: false - !ruby/object:Gem::Dependency version_requirements: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' none: false name: simplecov type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' none: false description: Simply builds and verifies OAuth headers email: - steve.richert@gmail.com - sferik@gmail.com executables: [] extensions: [] extra_rdoc_files: [] files: - .gemtest - .gitignore - .rspec - .travis.yml - .yardopts - CONTRIBUTING.md - Gemfile - LICENSE - README.md - Rakefile - lib/simple_oauth.rb - lib/simple_oauth/header.rb - simple_oauth.gemspec - spec/helper.rb - spec/simple_oauth/header_spec.rb - spec/support/fixtures/rsa-private-key - spec/support/rsa.rb homepage: https://github.com/laserlemon/simple_oauth licenses: - MIT post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' none: false required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' none: false requirements: [] rubyforge_project: rubygems_version: 1.8.23 signing_key: specification_version: 3 summary: Simply builds and verifies OAuth headers test_files: [] has_rdoc: simple_oauth-0.2.0/.yardopts0000644000004100000410000000005212060312235016067 0ustar www-datawww-data--markup markdown - HISTORY.md LICENSE.md simple_oauth-0.2.0/Gemfile0000644000004100000410000000014012060312235015512 0ustar www-datawww-datasource 'https://rubygems.org' platforms :jruby do gem 'jruby-openssl', '~> 0.7' end gemspec simple_oauth-0.2.0/.gitignore0000644000004100000410000000010312060312235016206 0ustar www-datawww-data*.rbc .bundle .DS_Store .yardoc coverage doc Gemfile.lock pkg rdoc simple_oauth-0.2.0/lib/0000755000004100000410000000000012060312235014772 5ustar www-datawww-datasimple_oauth-0.2.0/lib/simple_oauth/0000755000004100000410000000000012060312235017463 5ustar www-datawww-datasimple_oauth-0.2.0/lib/simple_oauth/header.rb0000644000004100000410000000644112060312235021245 0ustar www-datawww-datarequire 'openssl' require 'uri' require 'base64' require 'cgi' module SimpleOAuth class Header ATTRIBUTE_KEYS = [:callback, :consumer_key, :nonce, :signature_method, :timestamp, :token, :verifier, :version] unless defined? ::SimpleOAuth::Header::ATTRIBUTE_KEYS attr_reader :method, :params, :options class << self def default_options { :nonce => OpenSSL::Random.random_bytes(16).unpack('H*')[0], :signature_method => 'HMAC-SHA1', :timestamp => Time.now.to_i.to_s, :version => '1.0' } end def parse(header) header.to_s.sub(/^OAuth\s/, '').split(/,\s*/).inject({}) do |attributes, pair| match = pair.match(/^(\w+)\=\"([^\"]*)\"$/) attributes.merge(match[1].sub(/^oauth_/, '').to_sym => decode(match[2])) end end def escape(value) uri_parser.escape(value.to_s, /[^a-z0-9\-\.\_\~]/i) end alias encode escape def unescape(value) uri_parser.unescape(value.to_s) end alias decode unescape private def uri_parser @uri_parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI end end def initialize(method, url, params, oauth = {}) @method = method.to_s.upcase @uri = URI.parse(url.to_s) @uri.scheme = @uri.scheme.downcase @uri.normalize! @uri.fragment = nil @params = params @options = oauth.is_a?(Hash) ? self.class.default_options.merge(oauth) : self.class.parse(oauth) end def url uri = @uri.dup uri.query = nil uri.to_s end def to_s "OAuth #{normalized_attributes}" end def valid?(secrets = {}) original_options = options.dup options.merge!(secrets) valid = options[:signature] == signature options.replace(original_options) valid end def signed_attributes attributes.merge(:oauth_signature => signature) end private def normalized_attributes signed_attributes.sort_by{|k,v| k.to_s }.map{|k,v| %(#{k}="#{self.class.encode(v)}") }.join(', ') end def attributes ATTRIBUTE_KEYS.inject({}){|a,k| options[k] ? a.merge(:"oauth_#{k}" => options[k]) : a } end def signature send(options[:signature_method].downcase.tr('-', '_') + '_signature') end def hmac_sha1_signature Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, secret, signature_base)).chomp.gsub(/\n/, '') end def secret options.values_at(:consumer_secret, :token_secret).map{|v| self.class.encode(v) }.join('&') end alias_method :plaintext_signature, :secret def signature_base [method, url, normalized_params].map{|v| self.class.encode(v) }.join('&') end def normalized_params signature_params.map{|p| p.map{|v| self.class.encode(v) } }.sort.map{|p| p.join('=') }.join('&') end def signature_params attributes.to_a + params.to_a + url_params end def url_params CGI.parse(@uri.query || '').inject([]){|p,(k,vs)| p + vs.sort.map{|v| [k, v] } } end def rsa_sha1_signature Base64.encode64(private_key.sign(OpenSSL::Digest::SHA1.new, signature_base)).chomp.gsub(/\n/, '') end def private_key OpenSSL::PKey::RSA.new(options[:consumer_secret]) end end end simple_oauth-0.2.0/lib/simple_oauth.rb0000644000004100000410000000003612060312235020007 0ustar www-datawww-datarequire 'simple_oauth/header'