manually import 0.5.3

parent c204a87f
---
engines:
duplication:
enabled: true
config:
languages:
- ruby
fixme:
enabled: true
rubocop:
enabled: true
ratings:
paths:
- "**.rb"
exclude_paths:
- test/
.bundle
Gemfile.lock
coverage
*.gem
This diff is collapsed.
language: ruby
rvm:
- "ruby-head"
- "2.4.0"
- "2.3"
- "2.2"
- "2.1"
- "2.0"
addons:
code_climate:
repo_token: 8f697ca756250f0c2c54170ae27e8a9c459d18a0236903b11291c88291b3aac9
after_success:
- bundle exec codeclimate-test-reporter
This diff is collapsed.
= Ruby OAuth
== Status
{<img src="https://travis-ci.org/oauth-xx/oauth-ruby.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/oauth-xx/oauth-ruby]
== What
This is a RubyGem for implementing both OAuth clients and servers in Ruby applications.
......@@ -16,7 +22,7 @@ The source code is now hosted on the OAuth GitHub Project http://github.com/oaut
This is a ruby library which is intended to be used in creating Ruby Consumer and Service Provider applications. It is NOT a Rails plugin, but could easily be used for the foundation for such a Rails plugin.
As a matter of fact it has been pulled out from an OAuth Rails Plugin http://code.google.com/p/oauth-plugin/ which now requires this GEM.
As a matter of fact it has been pulled out from an OAuth Rails GEM (https://rubygems.org/gems/oauth-plugin https://github.com/pelle/oauth-plugin) which now uses this gem as a dependency.
== Demonstration of usage
......@@ -31,11 +37,15 @@ Create a new consumer instance by passing it a configuration hash:
Start the process by requesting a token
@request_token = @consumer.get_request_token(:oauth_callback => @callback_url)
session[:request_token] = @request_token
session[:token] = request_token.token
session[:token_secret] = request_token.secret
redirect_to @request_token.authorize_url(:oauth_callback => @callback_url)
When user returns create an access_token
hash = { oauth_token: session[:token], oauth_token_secret: session[:token_secret]}
request_token = OAuth::RequestToken.from_hash(@consumer, hash)
@access_token = @request_token.get_access_token
@photos = @access_token.get('/photos.xml')
......
%w[rubygems rake rake/clean rake/testtask fileutils bundler].each { |f| require f }
Bundler::GemHelper.install_tasks
Rake::TestTask.new do |t|
t.libs << "test"
t.test_files = FileList['test/**/*test*.rb']
t.verbose = true
end
Dir['tasks/**/*.rake'].each { |t| load t }
task :default => :test
#!/usr/bin/env ruby
require "oauth/cli"
require_relative "../lib/oauth"
require 'oauth/cli'
OAuth::CLI.execute(STDOUT, STDIN, STDERR, ARGV)
\ No newline at end of file
Signal.trap("INT") { puts; exit(1) } # don't dump a backtrace on a ^C
ARGV << 'help' if ARGV.empty?
command = ARGV.shift
OAuth::CLI.new(STDOUT, STDIN, STDERR, command, ARGV).run
#!/usr/bin/env ruby -rubygems
# Sample queries:
# ./yql.rb --consumer-key <key> --consumer-secret <secret> "show tables"
# ./yql.rb --consumer-key <key> --consumer-secret <secret> "select * from flickr.photos.search where text='Cat' limit 10"
require 'oauth'
require 'optparse'
require 'json'
require 'pp'
options = {}
option_parser = OptionParser.new do |opts|
opts.banner = "Usage: #{$0} [options] <query>"
opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
options[:consumer_key] = v
end
opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
options[:consumer_secret] = v
end
end
option_parser.parse!
query = ARGV.pop
query = STDIN.read if query == "-"
if options[:consumer_key].nil? || options[:consumer_secret].nil? || query.nil?
puts option_parser.help
exit 1
end
consumer = OAuth::Consumer.new \
options[:consumer_key],
options[:consumer_secret],
:site => "http://query.yahooapis.com"
access_token = OAuth::AccessToken.new(consumer)
response = access_token.request(:get, "/v1/yql?q=#{OAuth::Helper.escape(query)}&format=json")
rsp = JSON.parse(response.body)
pp rsp
$LOAD_PATH << File.dirname(__FILE__) unless $LOAD_PATH.include?(File.dirname(__FILE__))
root = File.dirname(__FILE__)
$LOAD_PATH << root unless $LOAD_PATH.include?(root)
require 'oauth/version'
......
This diff is collapsed.
class OAuth::CLI
class AuthorizeCommand < BaseCommand
def required_options
[:uri]
end
def _run
request_token = get_request_token
if request_token.callback_confirmed?
puts "Server appears to support OAuth 1.0a; enabling support."
options[:version] = "1.0a"
end
puts "Please visit this url to authorize:"
puts request_token.authorize_url
# parameters for OAuth 1.0a
oauth_verifier = ask_user_for_verifier
verbosely_get_access_token(request_token, oauth_verifier)
end
def get_request_token
consumer = get_consumer
scope_options = options[:scope] ? { "scope" => options[:scope] } : {}
consumer.get_request_token({ :oauth_callback => options[:oauth_callback] }, scope_options)
rescue OAuth::Unauthorized => e
alert "A problem occurred while attempting to authorize:"
alert e
alert e.request.body
end
def get_consumer
OAuth::Consumer.new \
options[:oauth_consumer_key],
options[:oauth_consumer_secret],
:access_token_url => options[:access_token_url],
:authorize_url => options[:authorize_url],
:request_token_url => options[:request_token_url],
:scheme => options[:scheme],
:http_method => options[:method].to_s.downcase.to_sym
end
def ask_user_for_verifier
if options[:version] == "1.0a"
puts "Please enter the verification code provided by the SP (oauth_verifier):"
@stdin.gets.chomp
else
puts "Press return to continue..."
@stdin.gets
nil
end
end
def verbosely_get_access_token(request_token, oauth_verifier)
access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
puts "Response:"
access_token.params.each do |k,v|
puts " #{k}: #{v}" unless k.is_a?(Symbol)
end
rescue OAuth::Unauthorized => e
alert "A problem occurred while attempting to obtain an access token:"
alert e
alert e.request.body
end
end
end
class OAuth::CLI
class BaseCommand
def initialize(stdout, stdin, stderr, arguments)
@stdout, @stdin, @stderr = stdout, stdin, stderr
@options = {}
option_parser.parse!(arguments)
end
def run
missing = required_options - options.keys
if missing.empty?
_run
else
show_missing(missing)
puts option_parser.help
end
end
def required_options
[]
end
protected
attr_reader :options
def show_missing(array)
array = array.map { |s| "--#{s}" }.join(' ')
OAuth::CLI.puts_red "Options missing to OAuth CLI: #{array}"
end
def xmpp?
options[:xmpp]
end
def verbose?
options[:verbose]
end
def puts(string=nil)
@stdout.puts(string)
end
def alert(string=nil)
@stderr.puts(string)
end
def parameters
@parameters ||= begin
escaped_pairs = options[:params].collect do |pair|
if pair =~ /:/
Hash[*pair.split(":", 2)].collect do |k,v|
[CGI.escape(k.strip), CGI.escape(v.strip)] * "="
end
else
pair
end
end
querystring = escaped_pairs * "&"
cli_params = CGI.parse(querystring)
{
"oauth_consumer_key" => options[:oauth_consumer_key],
"oauth_nonce" => options[:oauth_nonce],
"oauth_timestamp" => options[:oauth_timestamp],
"oauth_token" => options[:oauth_token],
"oauth_signature_method" => options[:oauth_signature_method],
"oauth_version" => options[:oauth_version]
}.reject { |_k,v| v.nil? || v == "" }.merge(cli_params)
end
end
def option_parser
@option_parser ||= OptionParser.new do |opts|
opts.banner = "Usage: oauth <command> [ARGS]"
_option_parser_defaults
_option_parser_common(opts)
_option_parser_sign_and_query(opts)
_option_parser_authorization(opts)
end
end
def _option_parser_defaults
options[:oauth_nonce] = OAuth::Helper.generate_key
options[:oauth_signature_method] = "HMAC-SHA1"
options[:oauth_timestamp] = OAuth::Helper.generate_timestamp
options[:oauth_version] = "1.0"
options[:method] = :post
options[:params] = []
options[:scheme] = :header
options[:version] = "1.0"
end
def _option_parser_common(opts)
## Common Options
opts.on("-B", "--body", "Use the request body for OAuth parameters.") do
options[:scheme] = :body
end
opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
options[:oauth_consumer_key] = v
end
opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
options[:oauth_consumer_secret] = v
end
opts.on("-H", "--header", "Use the 'Authorization' header for OAuth parameters (default).") do
options[:scheme] = :header
end
opts.on("-Q", "--query-string", "Use the query string for OAuth parameters.") do
options[:scheme] = :query_string
end
opts.on("-O", "--options FILE", "Read options from a file") do |v|
arguments = open(v).readlines.map { |l| l.chomp.split(" ") }.flatten
options2 = parse_options(arguments)
options.merge!(options2)
end
end
def _option_parser_sign_and_query(opts)
opts.separator("\n options for signing and querying")
opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
options[:method] = v
end
opts.on("--nonce NONCE", "Specifies the none to use.") do |v|
options[:oauth_nonce] = v
end
opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
options[:params] << v
end
opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
options[:oauth_signature_method] = v
end
opts.on("--token TOKEN", "Specifies the token to use.") do |v|
options[:oauth_token] = v
end
opts.on("--secret SECRET", "Specifies the token secret to use.") do |v|
options[:oauth_token_secret] = v
end
opts.on("--timestamp TIMESTAMP", "Specifies the timestamp to use.") do |v|
options[:oauth_timestamp] = v
end
opts.on("--realm REALM", "Specifies the realm to use.") do |v|
options[:realm] = v
end
opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
options[:uri] = v
end
opts.on("--version [VERSION]", "Specifies the OAuth version to use.") do |v|
options[:oauth_version] = v
end
opts.on("--no-version", "Omit oauth_version.") do
options[:oauth_version] = nil
end
opts.on("--xmpp", "Generate XMPP stanzas.") do
options[:xmpp] = true
options[:method] ||= "iq"
end
opts.on("-v", "--verbose", "Be verbose.") do
options[:verbose] = true
end
end
def _option_parser_authorization(opts)
opts.separator("\n options for authorization")
opts.on("--access-token-url URL", "Specifies the access token URL.") do |v|
options[:access_token_url] = v
end
opts.on("--authorize-url URL", "Specifies the authorization URL.") do |v|
options[:authorize_url] = v
end
opts.on("--callback-url URL", "Specifies a callback URL.") do |v|
options[:oauth_callback] = v
end
opts.on("--request-token-url URL", "Specifies the request token URL.") do |v|
options[:request_token_url] = v
end
opts.on("--scope SCOPE", "Specifies the scope (Google-specific).") do |v|
options[:scope] = v
end
end
end
end
class OAuth::CLI
class HelpCommand < BaseCommand
def run
puts <<-EOT
Usage: oauth COMMAND [ARGS]
Available oauth commands are:
a, authorize Obtain an access token and secret for a user
q, query Query a protected resource
s, sign Generate an OAuth signature
In addition to those, there are:
v, version Displays the current version of the library (or --version, -v)
h, help Displays this help (or --help, -h)
Tip: All commands can be run without args for specific help.
EOT
end
end
end
class OAuth::CLI
class QueryCommand < BaseCommand
extend OAuth::Helper
def required_options
[:oauth_consumer_key, :oauth_consumer_secret, :oauth_token, :oauth_token_secret]
end
def _run
consumer = OAuth::Consumer.new(options[:oauth_consumer_key], options[:oauth_consumer_secret], scheme: options[:scheme])
access_token = OAuth::AccessToken.new(consumer, options[:oauth_token], options[:oauth_token_secret])
# append params to the URL
uri = URI.parse(options[:uri])
params = parameters.map { |k,v| Array(v).map { |v2| "#{OAuth::Helper.escape(k)}=#{OAuth::Helper.escape(v2)}" } * "&" }
uri.query = [uri.query, *params].reject { |x| x.nil? } * "&"
puts uri.to_s
response = access_token.request(options[:method].to_s.downcase.to_sym, uri.to_s)
puts "#{response.code} #{response.message}"
puts response.body
end
end
end
class OAuth::CLI
class SignCommand < BaseCommand
def required_options
[:oauth_consumer_key, :oauth_consumer_secret, :oauth_token, :oauth_token_secret]
end
def _run
request = OAuth::RequestProxy.proxy \
"method" => options[:method],
"uri" => options[:uri],
"parameters" => parameters
if verbose?
puts_verbose_parameters(request)
end
request.sign! \
:consumer_secret => options[:oauth_consumer_secret],
:token_secret => options[:oauth_token_secret]
if verbose?
puts_verbose_request(request)
else
puts request.oauth_signature
end
end
def puts_verbose_parameters(request)
puts "OAuth parameters:"
request.oauth_parameters.each do |k,v|
puts " " + [k, v] * ": "
end
puts
if request.non_oauth_parameters.any?
puts "Parameters:"
request.non_oauth_parameters.each do |k,v|
puts " " + [k, v] * ": "
end
puts
end
end
def puts_verbose_request(request)
puts "Method: #{request.method}"
puts "URI: #{request.uri}"
puts "Normalized params: #{request.normalized_parameters}" unless options[:xmpp]
puts "Signature base string: #{request.signature_base_string}"
if xmpp?
puts
puts "XMPP Stanza:"
puts xmpp_output(request)
puts
puts "Note: You may want to use bare JIDs in your URI."
puts
else
puts "OAuth Request URI: #{request.signed_uri}"
puts "Request URI: #{request.signed_uri(false)}"
puts "Authorization header: #{request.oauth_header(:realm => options[:realm])}"
end
puts "Signature: #{request.oauth_signature}"
puts "Escaped signature: #{OAuth::Helper.escape(request.oauth_signature)}"
end
def xmpp_output(request)
<<-EOS
<oauth xmlns='urn:xmpp:oauth:0'>
<oauth_consumer_key>#{request.oauth_consumer_key}</oauth_consumer_key>
<oauth_token>#{request.oauth_token}</oauth_token>
<oauth_signature_method>#{request.oauth_signature_method}</oauth_signature_method>
<oauth_signature>#{request.oauth_signature}</oauth_signature>
<oauth_timestamp>#{request.oauth_timestamp}</oauth_timestamp>
<oauth_nonce>#{request.oauth_nonce}</oauth_nonce>
<oauth_version>#{request.oauth_version}</oauth_version>
</oauth>
EOS
end
end
end
class OAuth::CLI
class VersionCommand < BaseCommand
def run
puts "OAuth Gem #{OAuth::VERSION}"
end
end
end
require 'oauth/client/helper'
if defined? ActionDispatch
require 'oauth/request_proxy/rack_request'
require 'action_dispatch/testing/test_process'
......
require 'em-http'
require 'oauth/helper'
require 'oauth/client/helper'
require 'oauth/request_proxy/em_http_request'
# Extensions for em-http so that we can use consumer.sign! with an EventMachine::HttpClient
......
require 'oauth/helper'
require 'oauth/client/helper'
require 'oauth/request_proxy/net_http'
class Net::HTTPGenericRequest
......
......@@ -43,6 +43,13 @@ module OAuth
# Add a custom ca_file for consumer
# :ca_file => '/etc/certs.pem'
# Possible values:
#
# nil, false - no debug output
# true - uses $stdout
# some_value - uses some_value
:debug_output => nil,
:oauth_version => "1.0"
}
......@@ -87,6 +94,18 @@ module OAuth
@http_method ||= @options[:http_method] || :post
end
def debug_output
@debug_output ||= begin
case @options[:debug_output]
when nil, false
when true
$stdout
else
@options[:debug_output]
end
end
end
# The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
def http
@http ||= create_http
......@@ -210,7 +229,7 @@ module OAuth
end
when (300..399)
# this is a redirect
uri = URI.parse(response.header['location'])
uri = URI.parse(response['location'])
response.error! if uri.path == path # careful of those infinite redirects
self.token_request(http_method, uri.path, token, request_options, arguments)
when (400..499)
......@@ -321,6 +340,8 @@ module OAuth
http_object.read_timeout = http_object.open_timeout = @options[:timeout] || 30
http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
http_object.set_debug_output(debug_output) if debug_output
http_object
end
......@@ -334,8 +355,10 @@ module OAuth
end
# if the base site contains a path, add it now
# only add if the site host matches the current http object's host
# (in case we've specified a full url for token requests)
uri = URI.parse(site)
path = uri.path + path if uri.path && uri.path != '/'
path = uri.path + path if uri.path && uri.path != '/' && uri.host == http.address
headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
......
......@@ -13,8 +13,6 @@ end
class String
unless method_defined?(:bytesize)
def bytesize
self.size
......@@ -29,3 +27,27 @@ class String
end
end
# TODO: Work around URI.escape obsolete method
#
# 21/May/2016 - We are silencing a warning introduced in 2009
# https://github.com/ruby/ruby/commit/238b979f1789f95262a267d8df6239806f2859cc
#
# The only clear alternative to this problem is to invoke CGI.escape instead
# but that one does not take a secondary argument so we can pass OAuth::RESERVED_CHARACTERS
# As of today, ignoring this secondary argument would introduce 44 errors on our tests
# 181 runs, 511 assertions, 44 failures, 0 errors, 0 skips
#
# If you have a proper way to work around this so we don't need to override ruby core code
# Please send us a Pull Request
module URI
module Escape
def escape(*arg)
DEFAULT_PARSER.escape(*arg)
end
def unescape(*arg)
DEFAULT_PARSER.unescape(*arg)
end
end
end
......@@ -9,9 +9,17 @@ module OAuth
#
# See Also: {OAuth core spec version 1.0, section 5.1}[http://oauth.net/core/1.0#rfc.section.5.1]
def escape(value)
URI::escape(value.to_s.to_str, OAuth::RESERVED_CHARACTERS)
_escape(value.to_s.to_str)
rescue ArgumentError
URI::escape(value.to_s.to_str.force_encoding(Encoding::UTF_8), OAuth::RESERVED_CHARACTERS)
_escape(value.to_s.to_str.force_encoding(Encoding::UTF_8))
end
def _escape(string)
URI.escape(string, OAuth::RESERVED_CHARACTERS)
end