├── .gemtest ├── .rspec ├── lib ├── oa-core.rb └── omniauth │ ├── test │ ├── phony_session.rb │ ├── strategy_macros.rb │ └── strategy_test_case.rb │ ├── test.rb │ ├── version.rb │ ├── builder.rb │ ├── auth_hash.rb │ ├── core.rb │ ├── form.rb │ └── strategy.rb ├── .yardopts ├── .travis.yml ├── Rakefile ├── Gemfile ├── Guardfile ├── spec ├── spec_helper.rb └── omniauth │ ├── builder_spec.rb │ ├── core_spec.rb │ ├── auth_hash_spec.rb │ └── strategy_spec.rb ├── .gitignore ├── LICENSE ├── omniauth.gemspec └── README.md /.gemtest: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format=progress 3 | -------------------------------------------------------------------------------- /lib/oa-core.rb: -------------------------------------------------------------------------------- 1 | require 'omniauth/core' 2 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --markup markdown 2 | --markup-provider maruku 3 | - 4 | LICENSE 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | rvm: 2 | - 1.8.7 3 | - 1.9.2 4 | - jruby 5 | - rbx 6 | - rbx-2.0 7 | - ree 8 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | require 'rspec/core/rake_task' 4 | RSpec::Core::RakeTask.new(:spec) 5 | task :default => :spec 6 | task :test => :spec 7 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://rubygems.org' 2 | 3 | gemspec 4 | 5 | group :development do 6 | gem 'guard' 7 | gem 'guard-rspec' 8 | gem 'guard-bundler' 9 | gem 'growl' 10 | gem 'rb-fsevent' 11 | end 12 | -------------------------------------------------------------------------------- /lib/omniauth/test/phony_session.rb: -------------------------------------------------------------------------------- 1 | class OmniAuth::Test::PhonySession 2 | def initialize(app); @app = app end 3 | def call(env) 4 | @session ||= (env['rack.session'] || {}) 5 | env['rack.session'] = @session 6 | @app.call(env) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | guard 'rspec', :version => 2 do 2 | watch(%r{^spec/.+_spec\.rb$}) 3 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } 4 | watch('spec/spec_helper.rb') { "spec/" } 5 | end 6 | 7 | guard 'bundler' do 8 | watch('Gemfile') 9 | watch(/^.+\.gemspec/) 10 | end 11 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | SimpleCov.start 3 | require 'rspec' 4 | require 'rack/test' 5 | require 'omniauth/core' 6 | require 'omniauth/test' 7 | 8 | RSpec.configure do |config| 9 | config.include Rack::Test::Methods 10 | config.extend OmniAuth::Test::StrategyMacros, :type => :strategy 11 | end 12 | 13 | -------------------------------------------------------------------------------- /lib/omniauth/test.rb: -------------------------------------------------------------------------------- 1 | module OmniAuth 2 | 3 | # Support for testing OmniAuth strategies. 4 | module Test 5 | 6 | autoload :PhonySession, 'omniauth/test/phony_session' 7 | autoload :StrategyMacros, 'omniauth/test/strategy_macros' 8 | autoload :StrategyTestCase, 'omniauth/test/strategy_test_case' 9 | 10 | end 11 | 12 | end 13 | -------------------------------------------------------------------------------- /lib/omniauth/version.rb: -------------------------------------------------------------------------------- 1 | module OmniAuth 2 | module Version 3 | unless defined?(::OmniAuth::Version::MAJOR) 4 | MAJOR = 1 5 | end 6 | unless defined?(::OmniAuth::Version::MINOR) 7 | MINOR = 0 8 | end 9 | unless defined?(::OmniAuth::Version::PATCH) 10 | PATCH = 0 11 | end 12 | unless defined?(::OmniAuth::Version::PRE) 13 | PRE = "alpha" 14 | end 15 | unless defined?(::OmniAuth::Version::STRING) 16 | STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.') 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/omniauth/builder_spec.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../../spec_helper', __FILE__) 2 | 3 | describe OmniAuth::Builder do 4 | describe '#provider' do 5 | it 'should translate a symbol to a constant' do 6 | OmniAuth::Strategies.should_receive(:const_get).with('MyStrategy').and_return(Class.new) 7 | OmniAuth::Builder.new(nil) do 8 | provider :my_strategy 9 | end 10 | end 11 | 12 | it 'should also just accept a class' do 13 | class ::ExampleClass; end 14 | 15 | lambda{ OmniAuth::Builder.new(nil) do 16 | provider ::ExampleClass 17 | end }.should_not raise_error 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | !.autotest 2 | !.document 3 | !.gemtest 4 | !.gitignore 5 | !.rspec 6 | !.yardopts 7 | *.gem 8 | *.rbc 9 | *.sw[a-z] 10 | *.tmproj 11 | *.tmproject 12 | *.un~ 13 | *~ 14 | .* 15 | .DS_Store 16 | .Spotlight-V100 17 | .Trashes 18 | .\#* 19 | ._* 20 | .bundle 21 | .config 22 | .directory 23 | .elc 24 | .loadpath 25 | .project 26 | .redcar 27 | .rvmrc 28 | .yardoc 29 | /.emacs.desktop 30 | /.emacs.desktop.lock 31 | /live 32 | Desktop.ini 33 | Gemfile.lock 34 | Icon? 35 | InstalledFiles 36 | Session.vim 37 | Thumbs.db 38 | \#* 39 | \#*\# 40 | _yardoc 41 | auto-save-list 42 | coverage 43 | dist/* 44 | doc 45 | doc/ 46 | lib/bundler/man 47 | oa-live 48 | pkg 49 | pkg/* 50 | rdoc 51 | spec/reports 52 | test/tmp 53 | test/version_tmp 54 | tmp 55 | tmtags 56 | tramp 57 | -------------------------------------------------------------------------------- /lib/omniauth/builder.rb: -------------------------------------------------------------------------------- 1 | require 'omniauth/core' 2 | 3 | module OmniAuth 4 | class Builder < ::Rack::Builder 5 | def initialize(app, &block) 6 | @app = app 7 | super(&block) 8 | end 9 | 10 | def on_failure(&block) 11 | OmniAuth.config.on_failure = block 12 | end 13 | 14 | def configure(&block) 15 | OmniAuth.configure(&block) 16 | end 17 | 18 | def provider(klass, *args, &block) 19 | if klass.is_a?(Class) 20 | middleware = klass 21 | else 22 | middleware = OmniAuth::Strategies.const_get("#{OmniAuth::Utils.camelize(klass.to_s)}") 23 | end 24 | 25 | use middleware, *args, &block 26 | end 27 | 28 | def call(env) 29 | @ins << @app unless @ins.include?(@app) 30 | to_app.call(env) 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/omniauth/test/strategy_macros.rb: -------------------------------------------------------------------------------- 1 | module OmniAuth 2 | 3 | module Test 4 | 5 | module StrategyMacros 6 | 7 | def sets_an_auth_hash 8 | it 'should set an auth hash' do 9 | last_request.env['omniauth.auth'].should be_kind_of(Hash) 10 | end 11 | end 12 | 13 | def sets_provider_to(provider) 14 | it "should set the provider to #{provider}" do 15 | (last_request.env['omniauth.auth'] || {})['provider'].should == provider 16 | end 17 | end 18 | 19 | def sets_uid_to(uid) 20 | it "should set the UID to #{uid}" do 21 | (last_request.env['omniauth.auth'] || {})['uid'].should == uid 22 | end 23 | end 24 | 25 | def sets_user_info_to(user_info) 26 | it "should set the user_info to #{user_info}" do 27 | (last_request.env['omniauth.auth'] || {})['user_info'].should == user_info 28 | end 29 | end 30 | end 31 | 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /lib/omniauth/auth_hash.rb: -------------------------------------------------------------------------------- 1 | require 'hashie/mash' 2 | 3 | module OmniAuth 4 | class AuthHash < Hashie::Mash 5 | 6 | # Tells you if this is considered to be a valid 7 | # OmniAuth AuthHash. The requirements for that 8 | # are that it has a provider name, a uid, and a 9 | # valid user_info hash. See UserInfo#valid? for 10 | # more details there. 11 | def valid? 12 | uid? && provider? && (!user_info? || user_info.valid?) 13 | end 14 | 15 | def regular_writer(key, value) 16 | if key.to_s == 'user_info' && !value.is_a?(UserInfo) 17 | value = UserInfo.new(value) 18 | end 19 | super 20 | end 21 | 22 | class UserInfo < Hashie::Mash 23 | def valid? 24 | name? 25 | end 26 | 27 | def name 28 | return self[:name] if name? 29 | return "#{first_name} #{last_name}".strip if first_name? || last_name? 30 | return nickname if nickname? 31 | return email if email? 32 | nil 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2011 Michael Bleigh and Intridea, Inc. 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. 20 | -------------------------------------------------------------------------------- /omniauth.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require File.expand_path('../lib/omniauth/version', __FILE__) 3 | 4 | Gem::Specification.new do |gem| 5 | gem.name = 'omniauth' 6 | gem.description = %q{A generalized Rack framework for multiple-provider authentication.} 7 | gem.authors = ['Michael Bleigh', 'Erik Michaels-Ober'] 8 | gem.email = ['michael@intridea.com', 'sferik@gmail.com'] 9 | 10 | gem.add_runtime_dependency 'rack' 11 | gem.add_runtime_dependency 'hashie' 12 | 13 | gem.add_development_dependency 'maruku', '~> 0.6' 14 | gem.add_development_dependency 'simplecov', '~> 0.4' 15 | gem.add_development_dependency 'rack-test', '~> 0.5' 16 | gem.add_development_dependency 'rake', '~> 0.8' 17 | gem.add_development_dependency 'rdiscount', '~> 1.6' 18 | gem.add_development_dependency 'rspec', '~> 2.5' 19 | gem.add_development_dependency 'yard', '~> 0.7' 20 | 21 | gem.version = OmniAuth::Version::STRING 22 | gem.files = `git ls-files`.split("\n") 23 | gem.homepage = 'http://github.com/intridea/omniauth' 24 | gem.require_paths = ['lib'] 25 | gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if gem.respond_to? :required_rubygems_version= 26 | gem.summary = gem.description 27 | gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 28 | end 29 | -------------------------------------------------------------------------------- /lib/omniauth/test/strategy_test_case.rb: -------------------------------------------------------------------------------- 1 | require 'rack' 2 | require 'omniauth/test' 3 | 4 | module OmniAuth 5 | 6 | module Test 7 | 8 | # Support for testing OmniAuth strategies. 9 | # 10 | # @example Usage 11 | # class MyStrategyTest < Test::Unit::TestCase 12 | # include OmniAuth::Test::StrategyTestCase 13 | # def strategy 14 | # # return the parameters to a Rack::Builder map call: 15 | # [MyStrategy.new, :some, :configuration, :options => 'here'] 16 | # end 17 | # setup do 18 | # post '/auth/my_strategy/callback', :user => { 'name' => 'Dylan', 'id' => '445' } 19 | # end 20 | # end 21 | module StrategyTestCase 22 | 23 | def app 24 | strat = self.strategy 25 | resp = self.app_response 26 | Rack::Builder.new { 27 | use OmniAuth::Test::PhonySession 28 | use *strat 29 | run lambda {|env| [404, {'Content-Type' => 'text/plain'}, [resp || env.key?('omniauth.auth').to_s]] } 30 | }.to_app 31 | end 32 | 33 | def app_response 34 | nil 35 | end 36 | 37 | def session 38 | last_request.env['rack.session'] 39 | end 40 | 41 | def strategy 42 | raise NotImplementedError.new('Including specs must define #strategy') 43 | end 44 | 45 | end 46 | 47 | end 48 | 49 | end 50 | -------------------------------------------------------------------------------- /spec/omniauth/core_spec.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../../spec_helper', __FILE__) 2 | 3 | describe OmniAuth do 4 | describe '.strategies' do 5 | it 'should increase when a new strategy is made' do 6 | lambda{ class ExampleStrategy 7 | include OmniAuth::Strategy 8 | end }.should change(OmniAuth.strategies, :size).by(1) 9 | OmniAuth.strategies.last.should == ExampleStrategy 10 | end 11 | end 12 | 13 | context 'configuration' do 14 | it 'should be callable from .configure' do 15 | OmniAuth.configure do |c| 16 | c.should be_kind_of(OmniAuth::Configuration) 17 | end 18 | end 19 | 20 | before do 21 | @old_path_prefix = OmniAuth.config.path_prefix 22 | @old_on_failure = OmniAuth.config.on_failure 23 | end 24 | 25 | after do 26 | OmniAuth.configure do |config| 27 | config.path_prefix = @old_path_prefix 28 | config.on_failure = @old_on_failure 29 | end 30 | end 31 | 32 | it 'should be able to set the path' do 33 | OmniAuth.configure do |config| 34 | config.path_prefix = '/awesome' 35 | end 36 | 37 | OmniAuth.config.path_prefix.should == '/awesome' 38 | end 39 | 40 | it 'should be able to set the on_failure rack app' do 41 | OmniAuth.configure do |config| 42 | config.on_failure do 43 | 'yoyo' 44 | end 45 | end 46 | 47 | OmniAuth.config.on_failure.call.should == 'yoyo' 48 | end 49 | end 50 | 51 | describe '::Utils' do 52 | describe '.deep_merge' do 53 | it 'should combine hashes' do 54 | OmniAuth::Utils.deep_merge({'abc' => {'def' => 123}}, {'abc' => {'foo' => 'bar'}}).should == { 55 | 'abc' => {'def' => 123, 'foo' => 'bar'} 56 | } 57 | end 58 | end 59 | 60 | describe '.camelize' do 61 | it 'should work on normal cases' do 62 | { 63 | 'some_word' => 'SomeWord', 64 | 'AnotherWord' => 'AnotherWord', 65 | 'one' => 'One', 66 | 'three_words_now' => 'ThreeWordsNow' 67 | }.each_pair{ |k,v| OmniAuth::Utils.camelize(k).should == v } 68 | end 69 | 70 | it 'should work in special cases' do 71 | { 72 | 'oauth' => "OAuth", 73 | 'openid' => 'OpenID', 74 | 'open_id' => 'OpenID' 75 | }.each_pair{ |k,v| OmniAuth::Utils.camelize(k).should == v} 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /spec/omniauth/auth_hash_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe OmniAuth::AuthHash do 4 | subject{ OmniAuth::AuthHash.new } 5 | it 'should convert a supplied user_info key into a UserInfo object' do 6 | subject.user_info = {:name => 'Awesome'} 7 | subject.user_info.should be_kind_of(OmniAuth::AuthHash::UserInfo) 8 | subject.user_info.name.should == 'Awesome' 9 | end 10 | 11 | describe '#valid?' do 12 | subject{ OmniAuth::AuthHash.new(:uid => '123', :provider => 'example', :user_info => {:name => 'Steven'}) } 13 | 14 | it 'should be valid with the right parameters' do 15 | subject.should be_valid 16 | end 17 | 18 | it 'should require a uid' do 19 | subject.uid = nil 20 | subject.should_not be_valid 21 | end 22 | 23 | it 'should require a provider' do 24 | subject.provider = nil 25 | subject.should_not be_valid 26 | end 27 | 28 | it 'should require a name in the user info hash' do 29 | subject.user_info.name = nil 30 | subject.should_not be_valid? 31 | end 32 | end 33 | 34 | describe OmniAuth::AuthHash::UserInfo do 35 | describe '#valid?' do 36 | it 'should be valid if there is a name' do 37 | OmniAuth::AuthHash::UserInfo.new(:name => 'Awesome').should be_valid 38 | end 39 | end 40 | 41 | describe '#name' do 42 | subject{ OmniAuth::AuthHash::UserInfo.new( 43 | :name => 'Phillip J. Fry', 44 | :first_name => 'Phillip', 45 | :last_name => 'Fry', 46 | :nickname => 'meatbag', 47 | :email => 'fry@planetexpress.com' 48 | )} 49 | 50 | it 'should default to the name key' do 51 | subject.name.should == 'Phillip J. Fry' 52 | end 53 | 54 | it 'should fall back to go to first_name last_name concatenation' do 55 | subject.name = nil 56 | subject.name.should == 'Phillip Fry' 57 | end 58 | 59 | it 'should display only a first or last name if only that is available' do 60 | subject.name = nil 61 | subject.first_name = nil 62 | subject.name.should == 'Fry' 63 | end 64 | 65 | it 'should display the nickname if no name, first, or last is available' do 66 | %w(name first_name last_name).each{|k| subject[k] = nil} 67 | subject.name.should == 'meatbag' 68 | end 69 | 70 | it 'should display the email if no name, first, last, or nick is available' do 71 | %w(name first_name last_name nickname).each{|k| subject[k] = nil} 72 | subject.name.should == 'fry@planetexpress.com' 73 | end 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OmniAuth: Standardized Multi-Provider Authentication 2 | 3 | **NOTICE:** This documentation and code is toward OmniAuth 1.0 in which 4 | each provider will become its own separate gem. If you're looking for 5 | the current released version, please visit [OmniAuth 0.3 Stable 6 | Branch](https://github.com/intridea/omniauth/tree/0-3-stable). 7 | 8 | ## Structural Changes Coming in 1.0 9 | 10 | In version 1.0, the `omniauth` gem will become simply the underlying 11 | framework upon which authentication strategies can be built. That means 12 | where once users would put `gem 'omniauth'` into their Gemfile and be 13 | finished, now each provider will have a separate gem (e.g. 14 | `oa-twitter`). 15 | 16 | This change will bring about better code, faster releases, and hopefully 17 | an even more vibrant provider landscape. For more on the rationale of 18 | the change, see [this issue](https://github.com/intridea/omniauth/issues/451). 19 | 20 | ## Technical Changes Coming in 1.0 21 | 22 | ### The AuthHash Class 23 | 24 | In the past, OmniAuth has provided a simple hash of authentication 25 | information. In 1.0, the returned data will be an AuthHash, a special 26 | kind of hash that has extra properties special to OmniAuth. In addition, 27 | the auth hash schema will be changing slightly. More on that soon. 28 | 29 | ### Universal Options 30 | 31 | In 1.0, it will be possible to set certain configuration options that 32 | will then apply to all providers. This will make certain things easier. 33 | 34 | ### Simpler Dynamic Workflow 35 | 36 | To date, the workflow for "dynamic" providers (being able to change them 37 | at runtime) has been somewhat difficult. We will be re-evaluating this 38 | process and making sure it's as good as it can be. 39 | 40 | ### Declarative Provider Authorship 41 | 42 | We hope to provide a more declarative provider authorship system that 43 | will make it both easier to write and easier to test strategies. Much of 44 | this may have to be implemented in "aggregate" strategy providers such 45 | as OAuth and OAuth2, but stay tuned for more on this. 46 | 47 | ### Testing, Testing, Testing! 48 | 49 | OmniAuth 1.0 will be strongly tested and solid. Because we can release 50 | it one piece at a time (starting with the core gem and expanding out 51 | into the other provider gems) we will be able to maintain much higher 52 | code quality and the project will generally be more manageable. 53 | 54 | ## Stay Tuned! 55 | 56 | OmniAuth 1.0 is a work in progress. We will keep the community updated 57 | about progress as we have more information. Thanks! 58 | 59 | # License 60 | OmniAuth is released under the MIT License. 61 | -------------------------------------------------------------------------------- /lib/omniauth/core.rb: -------------------------------------------------------------------------------- 1 | require 'rack' 2 | require 'singleton' 3 | 4 | module OmniAuth 5 | module Strategies; end 6 | 7 | autoload :Builder, 'omniauth/builder' 8 | autoload :Strategy, 'omniauth/strategy' 9 | autoload :Test, 'omniauth/test' 10 | autoload :Form, 'omniauth/form' 11 | autoload :AuthHash, 'omniauth/auth_hash' 12 | 13 | def self.strategies 14 | @@strategies ||= [] 15 | end 16 | 17 | class Configuration 18 | include Singleton 19 | 20 | @@defaults = { 21 | :path_prefix => '/auth', 22 | :on_failure => Proc.new do |env| 23 | message_key = env['omniauth.error.type'] 24 | new_path = "#{OmniAuth.config.path_prefix}/failure?message=#{message_key}" 25 | [302, {'Location' => new_path, 'Content-Type'=> 'text/html'}, []] 26 | end, 27 | :form_css => Form::DEFAULT_CSS, 28 | :test_mode => false, 29 | :allowed_request_methods => [:get, :post], 30 | :mock_auth => { 31 | :default => { 32 | 'provider' => 'default', 33 | 'uid' => '1234', 34 | 'user_info' => { 35 | 'name' => 'Bob Example' 36 | } 37 | } 38 | } 39 | } 40 | 41 | def self.defaults 42 | @@defaults 43 | end 44 | 45 | def initialize 46 | @@defaults.each_pair{|k,v| self.send("#{k}=",v)} 47 | end 48 | 49 | def on_failure(&block) 50 | if block_given? 51 | @on_failure = block 52 | else 53 | @on_failure 54 | end 55 | end 56 | 57 | def add_mock(provider, mock={}) 58 | # Stringify keys recursively one level. 59 | mock.keys.each do |key| 60 | mock[key.to_s] = mock.delete(key) 61 | end 62 | mock.each_pair do |key, val| 63 | if val.is_a? Hash 64 | val.keys.each do |subkey| 65 | val[subkey.to_s] = val.delete(subkey) 66 | end 67 | end 68 | end 69 | 70 | # Merge with the default mock and ensure provider is correct. 71 | mock = self.mock_auth[:default].dup.merge(mock) 72 | mock["provider"] = provider.to_s 73 | 74 | # Add it to the mocks. 75 | self.mock_auth[provider.to_sym] = mock 76 | end 77 | 78 | attr_writer :on_failure 79 | attr_accessor :path_prefix, :allowed_request_methods, :form_css, :test_mode, :mock_auth, :full_host 80 | end 81 | 82 | def self.config 83 | Configuration.instance 84 | end 85 | 86 | def self.configure 87 | yield config 88 | end 89 | 90 | def self.mock_auth_for(provider) 91 | config.mock_auth[provider.to_sym] || config.mock_auth[:default] 92 | end 93 | 94 | module Utils 95 | CAMELIZE_SPECIAL = { 96 | 'oauth' => 'OAuth', 97 | 'oauth2' => 'OAuth2', 98 | 'openid' => 'OpenID', 99 | 'open_id' => 'OpenID', 100 | 'github' => 'GitHub', 101 | 'tripit' => 'TripIt', 102 | 'soundcloud' => 'SoundCloud', 103 | 'smugmug' => 'SmugMug', 104 | 'cas' => 'CAS', 105 | 'trademe' => 'TradeMe', 106 | 'ldap' => 'LDAP', 107 | 'google_oauth2' => 'GoogleOAuth2' 108 | } 109 | 110 | module_function 111 | 112 | def form_css 113 | "" 114 | end 115 | 116 | def deep_merge(hash, other_hash) 117 | target = hash.dup 118 | 119 | other_hash.keys.each do |key| 120 | if other_hash[key].is_a? ::Hash and hash[key].is_a? ::Hash 121 | target[key] = deep_merge(target[key],other_hash[key]) 122 | next 123 | end 124 | 125 | target[key] = other_hash[key] 126 | end 127 | 128 | target 129 | end 130 | 131 | def camelize(word, first_letter_in_uppercase = true) 132 | return CAMELIZE_SPECIAL[word.to_s] if CAMELIZE_SPECIAL[word.to_s] 133 | 134 | if first_letter_in_uppercase 135 | word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase } 136 | else 137 | word.first + camelize(word)[1..-1] 138 | end 139 | end 140 | end 141 | end 142 | -------------------------------------------------------------------------------- /lib/omniauth/form.rb: -------------------------------------------------------------------------------- 1 | require 'omniauth/core' 2 | 3 | module OmniAuth 4 | class Form 5 | DEFAULT_CSS = <<-CSS 6 | body { 7 | background: #ccc; 8 | font-family: "Lucida Grande", "Lucida Sans", Helvetica, Arial, sans-serif; 9 | } 10 | 11 | h1 { 12 | text-align: center; 13 | margin: 30px auto 0px; 14 | font-size: 18px; 15 | padding: 10px 10px 15px; 16 | background: #555; 17 | color: white; 18 | width: 320px; 19 | border: 10px solid #444; 20 | border-bottom: 0; 21 | -moz-border-radius-topleft: 10px; 22 | -moz-border-radius-topright: 10px; 23 | -webkit-border-top-left-radius: 10px; 24 | -webkit-border-top-right-radius: 10px; 25 | border-top-left-radius: 10px; 26 | border-top-right-radius: 10px; 27 | } 28 | 29 | h1, form { 30 | -moz-box-shadow: 2px 2px 7px rgba(0,0,0,0.3); 31 | -webkit-box-shadow: 2px 2px 7px rgba(0,0,0,0.3); 32 | } 33 | 34 | form { 35 | background: white; 36 | border: 10px solid #eee; 37 | border-top: 0; 38 | padding: 20px; 39 | margin: 0px auto 40px; 40 | width: 300px; 41 | -moz-border-radius-bottomleft: 10px; 42 | -moz-border-radius-bottomright: 10px; 43 | -webkit-border-bottom-left-radius: 10px; 44 | -webkit-border-bottom-right-radius: 10px; 45 | border-bottom-left-radius: 10px; 46 | border-bottom-right-radius: 10px; 47 | } 48 | 49 | label { 50 | display: block; 51 | font-weight: bold; 52 | margin-bottom: 5px; 53 | } 54 | 55 | input { 56 | font-size: 18px; 57 | padding: 4px 8px; 58 | display: block; 59 | margin-bottom: 10px; 60 | width: 280px; 61 | } 62 | 63 | input#identifier, input#openid_url { 64 | background: url(http://openid.net/login-bg.gif) no-repeat; 65 | background-position: 0 50%; 66 | padding-left: 18px; 67 | } 68 | 69 | button { 70 | font-size: 22px; 71 | padding: 4px 8px; 72 | display: block; 73 | margin: 20px auto 0; 74 | } 75 | 76 | fieldset { 77 | border: 1px solid #ccc; 78 | border-left: 0; 79 | border-right: 0; 80 | padding: 10px 0; 81 | } 82 | 83 | fieldset input { 84 | width: 260px; 85 | font-size: 16px; 86 | } 87 | CSS 88 | 89 | attr_accessor :options 90 | 91 | def initialize(options = {}) 92 | options[:title] ||= "Authentication Info Required" 93 | options[:header_info] ||= "" 94 | self.options = options 95 | 96 | @html = "" 97 | header(options[:title],options[:header_info]) 98 | end 99 | 100 | def self.build(title=nil,&block) 101 | form = OmniAuth::Form.new(:title => title) 102 | if block.arity > 0 103 | yield form 104 | else 105 | form.instance_eval(&block) 106 | end 107 | form 108 | end 109 | 110 | def label_field(text, target) 111 | @html << "\n" 112 | self 113 | end 114 | 115 | def input_field(type, name) 116 | @html << "\n" 117 | self 118 | end 119 | 120 | def text_field(label, name) 121 | label_field(label, name) 122 | input_field('text', name) 123 | self 124 | end 125 | 126 | def password_field(label, name) 127 | label_field(label, name) 128 | input_field('password', name) 129 | self 130 | end 131 | 132 | def button(text) 133 | @html << "\n" 134 | end 135 | 136 | def html(html) 137 | @html << html 138 | end 139 | 140 | def fieldset(legend, options = {}, &block) 141 | @html << "\n
" 144 | self 145 | end 146 | 147 | def header(title,header_info) 148 | @html << <<-HTML 149 | 150 | 151 | 152 |