├── oauth2-core ├── LICENSE ├── README.md ├── .rspec ├── lib │ └── oauth2 │ │ ├── core.rb │ │ ├── headers.rb │ │ ├── headers │ │ ├── authenticate.rb │ │ └── authorization.rb │ │ └── attributes.rb ├── spec │ ├── headers │ │ ├── authenticate_spec.rb │ │ └── authorization_spec.rb │ ├── spec_helper.rb │ └── attributes_spec.rb ├── Rakefile └── oauth2-core.gemspec ├── oauth2-rails ├── LICENSE ├── README.md ├── lib │ ├── oauth2-rails.rb │ └── oauth2 │ │ ├── rails.rb │ │ └── rails │ │ ├── adapters │ │ ├── base.rb │ │ └── active_record.rb │ │ ├── config.rb │ │ └── engine.rb ├── rails │ ├── install.rb │ └── uninstall.rb ├── app │ └── models │ │ └── oauth2 │ │ └── authorization_code_grant.rb ├── Rakefile ├── spec │ ├── rails_spec.rb │ ├── rails │ │ └── config_spec.rb │ └── spec_helper.rb └── oauth2-rails.gemspec ├── oauth2-server ├── README.md ├── .rspec ├── spec │ ├── server_spec.rb │ └── spec_helper.rb ├── lib │ └── oauth2 │ │ └── server.rb ├── Rakefile ├── oauth2-server.gemspec └── LICENSE ├── .gitignore ├── Gemfile ├── MIT-LICENSE └── README.md /oauth2-core/LICENSE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oauth2-core/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oauth2-rails/LICENSE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oauth2-rails/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oauth2-server/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle 2 | **/.DS_Store 3 | -------------------------------------------------------------------------------- /oauth2-core/.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --backtrace 3 | -------------------------------------------------------------------------------- /oauth2-server/.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --backtrace 3 | -------------------------------------------------------------------------------- /oauth2-rails/lib/oauth2-rails.rb: -------------------------------------------------------------------------------- 1 | require 'oauth2/rails' -------------------------------------------------------------------------------- /oauth2-rails/rails/install.rb: -------------------------------------------------------------------------------- 1 | # Install hook code here 2 | -------------------------------------------------------------------------------- /oauth2-rails/rails/uninstall.rb: -------------------------------------------------------------------------------- 1 | # Uninstall hook code here 2 | -------------------------------------------------------------------------------- /oauth2-server/spec/server_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper.rb' 2 | 3 | describe OAuth2::Server do 4 | end -------------------------------------------------------------------------------- /oauth2-core/lib/oauth2/core.rb: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | 3 | autoload :Headers, 'oauth2/headers' 4 | autoload :Signature, 'oauth2/signature' 5 | 6 | end -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source :gemcutter 2 | 3 | gem 'activesupport', '>= 3.0.0.beta' 4 | 5 | group :test do 6 | gem 'ruby-debug19' 7 | gem 'rspec', '>= 2.0.0.beta' 8 | end -------------------------------------------------------------------------------- /oauth2-core/spec/headers/authenticate_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'oauth2/headers/authenticate' 3 | 4 | describe OAuth2::Headers::Authenticate do 5 | 6 | end -------------------------------------------------------------------------------- /oauth2-rails/app/models/oauth2/authorization_code_grant.rb: -------------------------------------------------------------------------------- 1 | class AuthorizationCodeGrant < ActiveRecord::Base 2 | 3 | set_table_name 'oauth2_authorization_code_grants' 4 | 5 | end 6 | -------------------------------------------------------------------------------- /oauth2-core/lib/oauth2/headers.rb: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | 3 | module Headers 4 | 5 | autoload :Authorization, 'oauth2/headers/authorization' 6 | autoload :Authenticate, 'oauth2/headers/authenticate' 7 | 8 | end 9 | 10 | end -------------------------------------------------------------------------------- /oauth2-server/lib/oauth2/server.rb: -------------------------------------------------------------------------------- 1 | require 'oauth2/core' 2 | 3 | module OAuth2 4 | 5 | module Server 6 | # autoload :Flows, 'oauth2/server/flows' 7 | # autoload :Rails, 'oauth2/server/rails' 8 | # autoload :Request, 'oauth2/server/request' 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /oauth2-core/Rakefile: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | 3 | begin 4 | require 'rspec/core/rake_task' 5 | rescue LoadError 6 | raise 'RSpec could not be loaded. Run `bundle install` to get all development dependencies.' 7 | else 8 | RSpec::Core::RakeTask.new(:spec) do |t| 9 | t.warning = false 10 | end 11 | task :default => :spec 12 | end -------------------------------------------------------------------------------- /oauth2-rails/Rakefile: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | 3 | begin 4 | require 'rspec/core/rake_task' 5 | rescue LoadError 6 | raise 'RSpec could not be loaded. Run `bundle install` to get all development dependencies.' 7 | else 8 | RSpec::Core::RakeTask.new(:spec) do |t| 9 | t.warning = false 10 | end 11 | task :default => :spec 12 | end -------------------------------------------------------------------------------- /oauth2-server/Rakefile: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | 3 | begin 4 | require 'rspec/core/rake_task' 5 | rescue LoadError 6 | raise 'RSpec could not be loaded. Run `bundle install` to get all development dependencies.' 7 | else 8 | RSpec::Core::RakeTask.new(:spec) do |t| 9 | t.warning = false 10 | end 11 | task :default => :spec 12 | end -------------------------------------------------------------------------------- /oauth2-rails/spec/rails_spec.rb: -------------------------------------------------------------------------------- 1 | describe OAuth2::Rails do 2 | 3 | it "should initialize a configuration" do 4 | subject.config.should be_a(OAuth2::Rails::Config) 5 | end 6 | 7 | it "should setup its configuration" do 8 | blk = Proc.new { } 9 | subject.config.should_receive(:setup).once.and_yield(blk) 10 | subject.setup(&blk) 11 | end 12 | 13 | end -------------------------------------------------------------------------------- /oauth2-rails/lib/oauth2/rails.rb: -------------------------------------------------------------------------------- 1 | require 'oauth2/rails/engine' if defined?(Rails) 2 | require 'oauth2/rails/config' 3 | require 'active_support/core_ext/module' 4 | 5 | module OAuth2 6 | 7 | module Rails 8 | 9 | class << self 10 | 11 | mattr_accessor :config 12 | self.config = Config.new 13 | 14 | def setup(&block) 15 | config.setup(&block) 16 | end 17 | 18 | end 19 | 20 | end 21 | 22 | end -------------------------------------------------------------------------------- /oauth2-rails/lib/oauth2/rails/adapters/base.rb: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | 3 | module Rails 4 | 5 | module Adapters 6 | 7 | class Base 8 | 9 | def initialize(options) 10 | @options = options 11 | end 12 | 13 | # Must be implemented by subclasses 14 | # Returns true on success, else false. 15 | def create_authorization_code_grant(attributes) 16 | raise NotImplementedError.new 17 | end 18 | 19 | end 20 | 21 | end 22 | 23 | end 24 | 25 | end -------------------------------------------------------------------------------- /oauth2-core/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | require "bundler" 3 | Bundler.setup 4 | 5 | require 'oauth2/core' 6 | require 'rspec' 7 | require 'rspec/autorun' 8 | 9 | Dir.glob(File.dirname(__FILE__) + "/support/**/*.rb").each do |file| 10 | require file 11 | end 12 | 13 | Rspec.configure do |config| 14 | # == Mock Framework 15 | # 16 | # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: 17 | # 18 | # config.mock_with :mocha 19 | # config.mock_with :flexmock 20 | # config.mock_with :rr 21 | # config.mock_with :rspec 22 | end 23 | -------------------------------------------------------------------------------- /oauth2-rails/lib/oauth2/rails/config.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/core_ext/module' 2 | 3 | module OAuth2 4 | 5 | module Rails 6 | 7 | class Config 8 | 9 | class << self 10 | # We alias this method to something shorter. 11 | alias :option :attr_accessor_with_default 12 | end 13 | 14 | option :adapter, :active_record 15 | 16 | option :enforce_scopes, true 17 | 18 | option :models, { 19 | :client => :client, 20 | :authorization_code_grant => :authorization_code_grant 21 | } 22 | 23 | def setup(&block) 24 | yield self if block_given? 25 | end 26 | 27 | end 28 | 29 | end 30 | 31 | end -------------------------------------------------------------------------------- /oauth2-rails/lib/oauth2/rails/engine.rb: -------------------------------------------------------------------------------- 1 | require 'rails' 2 | 3 | module OAuth2 4 | 5 | module Rails 6 | 7 | class Engine < ::Rails::Engine 8 | 9 | class << self 10 | 11 | def root 12 | @root ||= File.expand_path("../../../..", __FILE__) 13 | end 14 | 15 | end 16 | 17 | generators do 18 | pattern = File.join(root, "generators", "oauth2", "*_generator.rb") 19 | Dir.glob(pattern).each { |f| require f } 20 | end 21 | 22 | %w{models controllers}.each do |dir| 23 | path = File.join(root, 'app', dir) 24 | config.load_paths << path 25 | config.load_once_paths.delete(path) 26 | end 27 | 28 | end 29 | 30 | end 31 | 32 | end -------------------------------------------------------------------------------- /oauth2-core/oauth2-core.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib/', __FILE__) 3 | $:.unshift lib unless $:.include?(lib) 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "oauth2-core" 7 | s.version = '0.1.4' 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["Alexander Flatter"] 10 | s.email = ["aflatter@farbenmeer.net"] 11 | s.homepage = "http://github.com/aflatter/oauth2-ruby" 12 | s.summary = "" 13 | s.description = "" 14 | 15 | s.required_rubygems_version = ">= 1.3.6" 16 | 17 | s.add_dependency(%q, [">= 0.0.0"]) 18 | 19 | s.add_development_dependency "rspec" 20 | 21 | s.files = Dir.glob("{bin,lib}/**/*") + %w(LICENSE README.md) 22 | s.require_path = 'lib' 23 | end 24 | -------------------------------------------------------------------------------- /oauth2-rails/oauth2-rails.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib/', __FILE__) 3 | $:.unshift lib unless $:.include?(lib) 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "oauth2-rails" 7 | s.version = '0.1.4' 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["Alexander Flatter"] 10 | s.email = ["aflatter@farbenmeer.net"] 11 | s.homepage = "http://github.com/aflatter/oauth2-ruby" 12 | s.summary = "" 13 | s.description = "" 14 | 15 | s.required_rubygems_version = ">= 1.3.6" 16 | 17 | s.add_dependency(%q, [">= 0.1.4"]) 18 | 19 | s.add_development_dependency "rspec" 20 | 21 | s.files = Dir.glob("{bin,lib}/**/*") + %w(LICENSE README.md) 22 | s.require_path = 'lib' 23 | end 24 | -------------------------------------------------------------------------------- /oauth2-server/oauth2-server.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib/', __FILE__) 3 | $:.unshift lib unless $:.include?(lib) 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "oauth2-server" 7 | s.version = '1.0.0.beta.1' 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["Alexander Flatter", "Diogo Almeida", "Miguel Teixeira"] 10 | s.email = ["aflatter@farbenmeer.net", "diogo.almeida@gnomeslab.com", "miguel.teixeira@gnomeslab.com"] 11 | s.homepage = ["http://github.com/aflatter/oauth2-ruby", "http://gnomeslab.com/"] 12 | s.summary = "" 13 | s.description = "" 14 | 15 | s.required_rubygems_version = ">= 1.3.6" 16 | 17 | s.add_dependency(%q, [">= 0.1.4"]) 18 | 19 | s.add_development_dependency "rspec" 20 | 21 | s.files = Dir.glob("{bin,lib}/**/*") + %w(LICENSE README.md) 22 | s.require_path = 'lib' 23 | end 24 | -------------------------------------------------------------------------------- /oauth2-core/spec/attributes_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'oauth2/attributes' 3 | 4 | describe OAuth2::Attributes do 5 | 6 | subject do 7 | klass = Class.new do 8 | include OAuth2::Attributes 9 | attributes :foo 10 | end 11 | 12 | klass.new 13 | end 14 | 15 | it "should allow to set an attribute to nil" do 16 | subject.foo = nil 17 | subject.foo.should be_nil 18 | end 19 | 20 | it "should call user defined block if it is registered" do 21 | foo = stub("some value") 22 | subject.foo { foo } 23 | subject.foo.should == foo 24 | end 25 | 26 | it "should return user defined value if defined" do 27 | foo = stub("some value") 28 | subject.foo = foo 29 | subject.foo.should == foo 30 | end 31 | 32 | it "should raise exception if no callback or value is defined" do 33 | lambda { subject.foo }.should raise_error(RuntimeError) 34 | end 35 | 36 | end -------------------------------------------------------------------------------- /oauth2-rails/spec/rails/config_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'oauth2/rails/config' 3 | 4 | describe OAuth2::Rails::Config do 5 | 6 | it "has a default of :active_record for adapter" do 7 | subject.adapter.should == :active_record 8 | end 9 | 10 | it "allows to set adapter" do 11 | subject.adapter = :foo_bar 12 | subject.adapter.should == :foo_bar 13 | end 14 | 15 | it "has a default of true for enforce_scopes" do 16 | subject.enforce_scopes.should == true 17 | end 18 | 19 | it "allows to set enforce_scopes" do 20 | subject.enforce_scopes = false 21 | subject.enforce_scopes.should == false 22 | end 23 | 24 | it "has defaults for models" do 25 | subject.models.should == {:client => :client} 26 | end 27 | 28 | it "allows to set models" do 29 | models = {:client => :bar} 30 | subject.models = models 31 | subject.models.should == models 32 | end 33 | 34 | end -------------------------------------------------------------------------------- /oauth2-core/lib/oauth2/headers/authenticate.rb: -------------------------------------------------------------------------------- 1 | require 'oauth2/attributes' 2 | 3 | module OAuth2 4 | 5 | module Headers 6 | 7 | class Authenticate 8 | 9 | Attributes = [ 10 | :realm, :algorithms, :auth_uri, :token_uri, :error 11 | ] 12 | 13 | Attributes.each do |attribute| 14 | attr_accessor attribute 15 | end 16 | 17 | def valid? 18 | raise "Realm not set" unless realm 19 | 20 | end 21 | 22 | def to_hash 23 | Attributes.inject(Hash.new) do |hash, attribute| 24 | value = send(attribute) 25 | hash[attribute] = value unless value.nil? 26 | hash 27 | end 28 | end 29 | 30 | def to_s 31 | to_hash.collect do |key, value| 32 | name = key.to_s.gsub('_', '-') 33 | "#{name}='#{value}'" 34 | end.join(",\n ") 35 | end 36 | 37 | end 38 | 39 | end 40 | 41 | end -------------------------------------------------------------------------------- /oauth2-rails/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | %w{core server}.each do |component| 2 | $LOAD_PATH.unshift(File.expand_path( 3 | File.join('..', '..', "oauth2-#{component}", 'lib'), 4 | File.dirname(__FILE__) 5 | )) 6 | end 7 | 8 | require "rubygems" 9 | 10 | begin 11 | require "bundler" 12 | Bundler.setup 13 | rescue LoadError => e 14 | puts 'Bundler not found. Please install bundler with the command gem install bundler' 15 | end 16 | 17 | begin 18 | require 'rspec' 19 | require 'rspec/autorun' 20 | rescue LoadError => e 21 | puts 'RSpec not found. Please install rspec with command bundle install' 22 | end 23 | 24 | require 'oauth2/rails' 25 | 26 | Dir.glob(File.dirname(__FILE__) + "/support/**/*.rb").each do |file| 27 | require file 28 | end 29 | 30 | Rspec.configure do |config| 31 | # == Mock Framework 32 | # 33 | # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: 34 | # 35 | # config.mock_with :mocha 36 | # config.mock_with :flexmock 37 | # config.mock_with :rr 38 | # config.mock_with :rspec 39 | end -------------------------------------------------------------------------------- /oauth2-server/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift(File.expand_path( 2 | File.join('..', '..', 'oauth2-core', 'lib'), 3 | File.dirname(__FILE__) 4 | )) 5 | 6 | require "rubygems" 7 | 8 | begin 9 | require "bundler" 10 | Bundler.setup 11 | rescue LoadError => e 12 | puts 'Bundler not found. Please install bundler with the command gem install bundler' 13 | end 14 | 15 | begin 16 | require 'rspec' 17 | require 'rspec/autorun' 18 | rescue LoadError => e 19 | puts 'RSpec not found. Please install rspec with command bundle install' 20 | end 21 | 22 | require 'oauth2/server' 23 | 24 | Dir.glob(File.dirname(__FILE__) + "/support/**/*.rb").each do |file| 25 | require file 26 | end 27 | 28 | Rspec.configure do |config| 29 | config.debug = true 30 | 31 | # == Mock Framework 32 | # 33 | # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: 34 | # 35 | # config.mock_with :mocha 36 | # config.mock_with :flexmock 37 | # config.mock_with :rr 38 | # config.mock_with :rspec 39 | end 40 | -------------------------------------------------------------------------------- /oauth2-rails/lib/oauth2/rails/adapters/active_record.rb: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | 3 | module Rails 4 | 5 | module Adapters 6 | 7 | class ActiveRecord < Base 8 | 9 | def initialize 10 | super 11 | @models = Hash.new 12 | end 13 | 14 | def create_authorization_code_grant(attributes) 15 | model(:authorization_code_grant).create( 16 | attributes.slice(:client, :user, :request_uri, :code) 17 | ) 18 | end 19 | 20 | # create_table :oauth2_authorization_code_grants do |t| 21 | # t.string :code 22 | # t.string :redirect_uri 23 | # t.integer :user_id 24 | # t.integer :client_id 25 | # end 26 | 27 | protected 28 | 29 | def constantize_model(id) 30 | OAuth2::Rails.config.models[:models][id].to_s.camelize.constantize 31 | end 32 | 33 | def model(id) 34 | @models[id] ||= constantize_model(id) 35 | end 36 | 37 | end 38 | 39 | end 40 | 41 | end 42 | 43 | end -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Alexander Flatter, Diogo Almeida and Miguel Teixeira 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. -------------------------------------------------------------------------------- /oauth2-server/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Alexander Flatter, Diogo Almeida and Miguel Teixeira 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. -------------------------------------------------------------------------------- /oauth2-core/lib/oauth2/attributes.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/concern' 2 | require 'active_support/core_ext/class/inheritable_attributes' 3 | 4 | module OAuth2 5 | 6 | module Attributes 7 | 8 | extend ActiveSupport::Concern 9 | 10 | included do 11 | class_inheritable_array :attribute_names 12 | self.attribute_names = Array.new 13 | end 14 | 15 | def attributes 16 | @attributes ||= Hash.new 17 | end 18 | 19 | module ClassMethods 20 | 21 | # Defines a callback for a handle. 22 | def attribute(handle) 23 | attribute_names << handle.to_sym 24 | 25 | class_eval(<<-EOS, __FILE__, __LINE__ + 1) 26 | def #{handle}(&block) 27 | @attributes ||= {} 28 | 29 | if block_given? 30 | @attributes[:#{handle}] = block 31 | return 32 | end 33 | 34 | if @attributes.key?(:#{handle}) 35 | value = @attributes[:#{handle}] 36 | value.is_a?(Proc) ? value.call : value 37 | else 38 | raise "No attribute or callback for '#{handle}' defined" 39 | end 40 | end 41 | 42 | def #{handle.to_s.gsub('?', '')}=(value) 43 | @attributes ||= {} 44 | @attributes[:#{handle}] = value 45 | end 46 | EOS 47 | end 48 | 49 | def attributes(*handles) 50 | handles.each do |handle| 51 | attribute(handle) 52 | end 53 | end 54 | 55 | end 56 | 57 | end 58 | 59 | end -------------------------------------------------------------------------------- /oauth2-core/spec/headers/authorization_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'oauth2/headers/authorization' 3 | 4 | describe OAuth2::Headers::Authorization do 5 | 6 | it "should parse a real world cryptographic example" do 7 | example = <<-EOS 8 | Token token="vF9dft4qmT", 9 | nonce="s8djwd", 10 | timestamp="137131200", 11 | algorithm="hmac-sha256", 12 | signature="wOJIO9A2W5mFwDgiDvZbTSMK/PY=" 13 | EOS 14 | 15 | header = OAuth2::Headers::Authorization.parse(example) 16 | header.token.should == "vF9dft4qmT" 17 | header.nonce.should == "s8djwd" 18 | header.timestamp.should == "137131200" 19 | header.algorithm.should == "hmac-sha256" 20 | header.signature.should == "wOJIO9A2W5mFwDgiDvZbTSMK/PY=" 21 | end 22 | 23 | it "should parse a real world bearer example" do 24 | example = 'Token token="vF9dft4qmT"' 25 | header = OAuth2::Headers::Authorization.parse(example) 26 | header.token.should == "vF9dft4qmT" 27 | end 28 | 29 | it "returns attributes in order" do 30 | attributes = OAuth2::Headers::Authorization::Attributes 31 | subject.attributes.should be_a(ActiveSupport::OrderedHash) 32 | subject.attributes.keys.should == attributes 33 | end 34 | 35 | it "ignores parameters without value using the parse method" do 36 | example_with_empty_value = <<-EOS 37 | Token token="vF9dft4qmT", 38 | nonce="" 39 | EOS 40 | 41 | example_without_empty_value = <<-EOS 42 | Token token="vF9dft4qmT" 43 | EOS 44 | 45 | OAuth2::Headers::Authorization.parse(example_with_empty_value).to_s.should == OAuth2::Headers::Authorization.parse(example_without_empty_value).to_s 46 | end 47 | 48 | it "ignores parameters without value using the new method" do 49 | OAuth2::Headers::Authorization.new(:token => "vF9dft4qmT", :signature => "").to_s.should == OAuth2::Headers::Authorization.new(:token => "vF9dft4qmT").to_s 50 | end 51 | 52 | it "builds a header string" 53 | 54 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | =========== 3 | 4 | oauth2-ruby is a Ruby library that makes it easy for developers to use OAuth2 protocol, currently in use in sites such as Facebook, Twitter and Launchpad (37 Signals). 5 | 6 | **Disclaimer:** As this is alpha software, it is suspected to change and considered unstable. 7 | 8 | ## OAuth 2 protocol compliance 9 | 10 | The current implementation of the gem is based on OAuth2 draft 00 (more about it [here](http://tools.ietf.org/html/draft-ietf-oauth-v2-00) and [here](http://tools.ietf.org/html/draft-hammer-oauth2-00)). Our goal is to support [Draft 09](http://tools.ietf.org/html/draft-ietf-oauth-v2-09) by the time gem hits version 1.0. 11 | 12 | ## Packages 13 | 14 | Currently the project consists of three seperate packages: oauth2-core, oauth2-server and oauth2-client - the latter will be available soon. 15 | 16 | ### oauth2-core 17 | 18 | * makes parsing, validating and building [_Authorization_](http://tools.ietf.org/html/draft-hammer-oauth2-00#section-5.1) and [_WWW-Authenticate_](http://tools.ietf.org/html/draft-hammer-oauth2-00#section-6.1) headers easy 19 | * implements OAuth2::Attributes which gives the possibility to set an attribute via callback (blocks), accessor or passing a hash on object initialization. This ensures that the library is very flexible. 20 | 21 | ### oauth2-server 22 | 23 | * provides different flows according to the OAuth2 specification. Currently, only the [web server](http://tools.ietf.org/html/draft-hammer-oauth2-00#section-3.5.2) flow is implemented. 24 | * makes handling OAuth2 requests easy. It currently supports [bearer](http://tools.ietf.org/html/draft-hammer-oauth2-00#section-5.2) and [cryptographic](http://tools.ietf.org/html/draft-hammer-oauth2-00#section-5.3) requests. 25 | 26 | Getting started 27 | =============== 28 | 29 | The [wiki](http://github.com/aflatter/oauth2-ruby/wikis) features some examples. 30 | 31 | How to contribute 32 | ================= 33 | 34 | If you wish to helps us make OAuth 2 an easy ride with Ruby, please take note of the following: 35 | 36 | * If you have an issue, please submit it [here on Github](http://github.com/aflatter/oauth2-ruby/issues) 37 | * Should you wish to commit a patch, please fork the project and send a pull request. But - please - don't forget the tests :) 38 | 39 | License 40 | ======= 41 | 42 | This Ruby GEM is made available to you under the [MIT license](http://github.com/aflatter/oauth2-ruby/blob/master/MIT-LICENSE). 43 | -------------------------------------------------------------------------------- /oauth2-core/lib/oauth2/headers/authorization.rb: -------------------------------------------------------------------------------- 1 | require 'oauth2/attributes' 2 | require 'active_support/ordered_hash' 3 | 4 | module OAuth2 5 | 6 | module Headers 7 | 8 | class Authorization 9 | 10 | def initialize(attributes = {}) 11 | attributes.each_pair do |key, value| 12 | if Attributes.include?(key.to_sym) && !value.empty? 13 | instance_variable_set("@#{key}", value) 14 | end 15 | end 16 | end 17 | 18 | # These attributes are expected to be contained in the header 19 | Attributes = [ 20 | :token, :nonce, :timestamp, :algorithm, :signature 21 | ] 22 | 23 | Attributes.each do |attribute| 24 | attr_accessor(attribute) 25 | end 26 | 27 | def validate 28 | case request_type 29 | when :bearer 30 | @errors << :bearer_request_requires_token unless token 31 | when :cryptographic 32 | %w{nonce timestamp algorithm signature}.each do |attribute| 33 | unless instance_variable_get("@#{attribute}") 34 | error = "cryptographic_request_requires_#{attribute}".to_sym 35 | @errors << error 36 | end 37 | end 38 | end 39 | 40 | @errors.blank? 41 | end 42 | 43 | def errors 44 | @errors ||= [] 45 | end 46 | 47 | def attributes 48 | hash = ActiveSupport::OrderedHash.new 49 | Attributes.each do |attribute| 50 | hash[attribute] = instance_variable_get("@#{attribute}") 51 | end 52 | hash 53 | end 54 | 55 | def to_s 56 | attrs = attributes.collect do |key, value| 57 | %{#{key}="#{value}"} if value 58 | end.compact 59 | 60 | "Token " + attrs.join(",\n ") 61 | end 62 | 63 | class << self 64 | 65 | # This method does what it is named after. Give it a String and it 66 | # returns a Hash. The header specification can be found on: 67 | # http://tools.ietf.org/html/draft-hammer-oauth2-00#section-5.1 68 | # TODO: Verify that token is the first attribute. 69 | def parse(string) 70 | header = new 71 | 72 | string.strip! 73 | 74 | type, tuples = string[0..4], string[5..-1].split("\n") 75 | 76 | unless type == "Token" 77 | header.errors << :format_invalid 78 | return header 79 | end 80 | 81 | tuples.map! { |tuple| tuple.strip! } 82 | 83 | tuples.each do |tuple| 84 | 85 | # Parameters sent without a value MUST be treated as if they were 86 | # omitted from the request. 87 | # http://tools.ietf.org/html/draft-ietf-oauth-v2-09#page-18 88 | unless tuple =~ /\s*(.+)="(.*)"/ 89 | header.errors << :format_invalid 90 | else 91 | key, value = $1.to_sym, $2 92 | next if value.empty? 93 | 94 | unless Attributes.include?(key) 95 | header.errors << "unknown_attribute_#{key}".to_sym 96 | else 97 | header.send("#{key}=".to_sym, value) 98 | end 99 | end 100 | end 101 | 102 | header 103 | end 104 | 105 | end 106 | 107 | end 108 | 109 | end 110 | 111 | end --------------------------------------------------------------------------------