soauth 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Matthew Riley MacPherson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1 @@
1
+ Use this library to create OAuth Authorization Headers using previously-obtained OAuth keys/secrets. Useful if you want to make your own HTTP request objects instead of using the ones created for you using the commonly-used OAuth gem.
@@ -0,0 +1,12 @@
1
+ require 'rake/rdoctask'
2
+
3
+ # Make me some RDoc (use Allison, because it's pretty)
4
+ Rake::RDocTask.new do |rdoc|
5
+ files = ['README.markdown', 'LICENSE', 'lib/*.rb', 'test/*.rb']
6
+ rdoc.rdoc_files.add(files)
7
+ rdoc.main = 'README.markdown'
8
+ rdoc.title = 'SOAuth'
9
+ #rdoc.template = ''
10
+ rdoc.rdoc_dir = './doc'
11
+ rdoc.options << '--line-numbers' << '--inline-source'
12
+ end
@@ -0,0 +1,81 @@
1
+ require 'base64'
2
+ require 'openssl'
3
+ require 'uri'
4
+
5
+ class SOAuth
6
+
7
+ # Exception raised if signature signing method isn't supported
8
+ # by SOAuth
9
+ class UnsupportedSignatureMethod < Exception; end
10
+ # Exception raised when attempting to create a signature without
11
+ # required OAuth params
12
+ class MissingOAuthParams < Exception; end
13
+
14
+ # Digest key for HMAC-SHA1 signing
15
+ DIGEST = OpenSSL::Digest::Digest.new('sha1')
16
+ # Supported {signature methods}[http://oauth.net/core/1.0/#signing_process];
17
+ # currently, only HMAC-SHA1 is supported
18
+ SUPPORTED_SIGNATURE_METHODS = ["HMAC-SHA1"]
19
+
20
+ # Return an {OAuth "Authorization" HTTP header}[http://oauth.net/core/1.0/#auth_header] from request data
21
+ def header(uri, oauth, params = {}, http_method = :get)
22
+ # Raise an exception if we're missing required OAuth params
23
+ raise MissingOAuthParams if !oauth.is_a?(Hash) || !oauth.has_key?(:consumer_key) || !oauth.has_key?(:consumer_secret) || !oauth.has_key?(:access_key) || !oauth.has_key?(:access_secret)
24
+ # Make sure we support the signature signing method specified
25
+ raise UnsupportedSignatureMethod unless !oauth[:signature_method] || SUPPORTED_SIGNATURE_METHODS.include?(oauth[:signature_method].to_s)
26
+
27
+ oauth[:signature_method] ||= "HMAC-SHA1" # HMAC-SHA1 seems popular, so it's the default
28
+ oauth[:version] ||= "1.0" # Assumed version, according to the spec
29
+ oauth[:nonce] ||= Base64.encode64(OpenSSL::Random.random_bytes(32)).gsub(/\W/, '')
30
+ oauth[:timestamp] ||= Time.now.to_i
31
+
32
+ # Make a copy of the params hash so we don't add in OAuth stuff
33
+ sig_params = params.dup
34
+
35
+ oauth.each { |k, v|
36
+ # OAuth wants this to be "token"; change the hash key
37
+ if k == :access_key
38
+ sig_params['oauth_token'] = v
39
+ # Only use certain OAuth values for the base string
40
+ elsif [:consumer_key, :signature_method, :version, :nonce, :timestamp].include?(k)
41
+ sig_params['oauth_' + k.to_s] = v
42
+ end
43
+ }
44
+
45
+ secret = "#{escape(oauth[:consumer_secret])}&#{escape(oauth[:access_secret])}"
46
+ sig_base = (http_method||'get').to_s.upcase + '&' + escape(uri) + '&' + normalize(sig_params)
47
+ oauth_signature = Base64.encode64(OpenSSL::HMAC.digest(DIGEST, secret, sig_base)).chomp.gsub(/\n/,'')
48
+
49
+ %{OAuth } + (%{oauth_realm="#{oauth[:realm]}", } unless !oauth[:realm]).to_s + %{oauth_consumer_key="#{oauth[:consumer_key]}", oauth_token="#{oauth[:access_key]}", oauth_signature_method="#{oauth[:signature_method]}", oauth_signature="#{escape(oauth_signature)}", oauth_timestamp="#{oauth[:timestamp]}", oauth_nonce="#{oauth[:nonce]}", oauth_version="#{oauth[:version]}"}
50
+ end
51
+
52
+ # Utility class used to sign a request and return an
53
+ # {OAuth "Authorization" HTTP header}[http://oauth.net/core/1.0/#auth_header]
54
+ def self.header(uri, oauth, params = {}, http_method = :get)
55
+ new.header(uri, oauth, params, http_method)
56
+ end
57
+
58
+ protected
59
+
60
+ # Escape characters in a string according to the {OAuth spec}[http://oauth.net/core/1.0/]
61
+ def escape(value)
62
+ URI::escape(value.to_s, /[^a-zA-Z0-9\-\.\_\~]/) # Unreserved characters -- must not be encoded
63
+ end
64
+
65
+ # Normalize a string of parameters based on the {OAuth spec}[http://oauth.net/core/1.0/#rfc.section.9.1.1]
66
+ def normalize(params)
67
+ params.sort.map do |k, values|
68
+
69
+ if values.is_a?(Array)
70
+ # Multiple values were provided for a single key
71
+ # in a hash
72
+ values.sort.collect do |v|
73
+ [escape(k), escape(v)] * "%3D"
74
+ end
75
+ else
76
+ [escape(k), escape(values)] * "%3D"
77
+ end
78
+ end * "%26"
79
+ end
80
+
81
+ end
@@ -0,0 +1,16 @@
1
+ require 'rake'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "soauth"
5
+ s.version = "0.1"
6
+ #s.date = Time.now.to_s
7
+ s.authors = ["Matthew Riley MacPherson"]
8
+ s.email = "matt@lonelyvegan.com"
9
+ s.has_rdoc = true
10
+ s.rdoc_options << '--title' << "SOAuth -- Ruby Library that creates HTTP headers for OAuth Authorization" << '--main' << 'README.markdown' << '--line-numbers'
11
+ s.summary = "Create OAuth \"Authorization\" HTTP Header using previously-obtained OAuth data"
12
+ s.homepage = "http://github.com/tofumatt/soauth"
13
+ s.files = FileList['lib/*.rb', '[A-Z]*', 'soauth.gemspec', 'test/*.rb'].to_a
14
+ s.test_file = 'test/soauth_test.rb'
15
+ s.add_development_dependency('mocha') # Used to run the tests, that's all...
16
+ end
@@ -0,0 +1,56 @@
1
+ $LOAD_PATH << File.expand_path("#{File.dirname(__FILE__)}/../lib")
2
+ require 'soauth'
3
+
4
+ require 'rubygems'
5
+ require 'test/unit'
6
+ require 'mocha'
7
+
8
+ class SOAuthTest < Test::Unit::TestCase
9
+
10
+ # Required OAuth parameters with dummy values -- these
11
+ # keys are the minimum number of keys required to generate
12
+ # an {OAuth "Authorization" HTTP header}[http://oauth.net/core/1.0/#auth_header]
13
+ OAUTH_REQ_PARAMS = {
14
+ :consumer_key => "consumer_key",
15
+ :consumer_secret => "consumer_secret",
16
+ :access_key => "access_key",
17
+ :access_secret => "access_secret"
18
+ }
19
+
20
+ # Make sure the custom nonce is used
21
+ def test_custom_nonce
22
+ nonce = Base64.encode64(OpenSSL::Random.random_bytes(32)).gsub(/\W/, '')
23
+
24
+ oauth_params = OAUTH_REQ_PARAMS.merge(:nonce => nonce)
25
+ assert_equal %{oauth_nonce="#{nonce}"}, %{oauth_nonce="#{SOAuth.header('http://lonelyvegan.com/', oauth_params).match(nonce)[0]}"}
26
+ end
27
+
28
+ # Make sure the custom timestamp is used
29
+ def test_custom_nonce
30
+ now = Time.now.to_i
31
+
32
+ oauth_params = OAUTH_REQ_PARAMS.merge(:timestamp => now)
33
+ assert_equal %{oauth_timestamp="#{now}"}, %{oauth_timestamp="#{SOAuth.header('http://lonelyvegan.com/', oauth_params).match(now.to_s)[0]}"}
34
+ end
35
+
36
+ # Generate a header without an explicit OAuth version (assumes {version 1.0}[http://oauth.net/core/1.0/])
37
+ def test_no_version_specified
38
+ # No OAuth version specified
39
+ oauth_params = OAUTH_REQ_PARAMS
40
+ assert SOAuth.header('http://lonelyvegan.com/', OAUTH_REQ_PARAMS)
41
+ end
42
+
43
+ # Generate a header without a {signature method}[http://oauth.net/core/1.0/#signing_process] (assumes "HMAC-SHA1")
44
+ def test_no_signature_method_specified
45
+ # No signature method specified
46
+ oauth_params = OAUTH_REQ_PARAMS
47
+ assert SOAuth.header('http://lonelyvegan.com/', OAUTH_REQ_PARAMS)
48
+ end
49
+
50
+ # Only certain {signature methods}[http://oauth.net/core/1.0/#signing_process] are supported
51
+ def test_unsupported_signature_method
52
+ oauth_params = OAUTH_REQ_PARAMS.merge(:signature_method => "MD5")
53
+ assert_raises(SOAuth::UnsupportedSignatureMethod) { SOAuth.header('http://lonelyvegan.com/', oauth_params) }
54
+ end
55
+
56
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: soauth
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Matthew Riley MacPherson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-04 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mocha
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: matt@lonelyvegan.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - lib/soauth.rb
35
+ - LICENSE
36
+ - Rakefile
37
+ - README.markdown
38
+ - soauth.gemspec
39
+ - test/soauth_test.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/tofumatt/soauth
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --title
47
+ - SOAuth -- Ruby Library that creates HTTP headers for OAuth Authorization
48
+ - --main
49
+ - README.markdown
50
+ - --line-numbers
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.5
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Create OAuth "Authorization" HTTP Header using previously-obtained OAuth data
72
+ test_files:
73
+ - test/soauth_test.rb