1
0
Fork 0
mirror of https://github.com/omniauth/omniauth.git synced 2022-11-09 12:31:49 -05:00

Clearing out everything to move towards the new 1.0 independent gems strategy.

This commit is contained in:
Michael Bleigh 2011-09-03 21:26:57 -03:00
parent 9f8119544a
commit cc73281406
253 changed files with 60 additions and 10805 deletions

13
Gemfile
View file

@ -1,14 +1,3 @@
source 'http://rubygems.org'
platforms :jruby do
gem 'jruby-openssl', '~> 0.7'
end
gemspec :path => 'oa-core'
gemspec :path => 'oa-enterprise'
gemspec :path => 'oa-more'
gemspec :path => 'oa-oauth'
gemspec :path => 'oa-openid'
gem 'activerecord', '3.1.0.rc1'
gemspec

View file

@ -1,27 +0,0 @@
# A sample Guardfile
# More info at https://github.com/guard/guard#readme
guard 'rspec', :version => 2 do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec/" }
# Rails example
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
watch(%r{^spec/support/(.+)\.rb$}) { "spec/" }
watch('spec/spec_helper.rb') { "spec/" }
watch('config/routes.rb') { "spec/routing" }
watch('app/controllers/application_controller.rb') { "spec/controllers" }
# Capybara request specs
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
end
guard 'bundler' do
watch('Gemfile')
# Uncomment next line if Gemfile contain `gemspec' command
# watch(/^.+\.gemspec/)
end

View file

@ -1,19 +0,0 @@
Copyright (c) 2010-2011 Michael Bleigh, Erik Michaels-Ober, and Intridea, Inc.
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.

55
Rakefile Executable file → Normal file
View file

@ -1,51 +1,6 @@
#!/usr/bin/env rake
$:.unshift File.expand_path('..', __FILE__)
require 'tasks/all'
desc 'Clean up temporary files'
task :clean => 'all:clean'
desc 'Build gem files for all projects into the package directory'
task :build => 'all:build'
desc 'Build and install gems for all projects'
task :install => 'all:install'
desc 'Write version with MAJOR, MINOR, PATCH, and PRE environment variables'
task 'version:write' => 'all:version:write'
desc 'Display the current version for all projects'
task :version => 'all:version'
desc 'Increment the major version for all projects'
task 'version:bump:major' => 'all:version:bump:major'
desc 'Increment the minor version for all projects'
task 'version:bump:minor' => 'all:version:bump:minor'
desc 'Increment the patch version for all projects'
task 'version:bump:patch' => 'all:version:bump:patch'
desc 'Run specs for all projects'
task :spec => 'all:spec'
require 'bundler'
Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
task :default => :spec
task :test => :spec
task :default => :test
desc 'Generate docs for all projects'
task 'doc:yard' => 'all:doc:yard'
task :tag do
sh "git tag -a -m \"Version #{version}\" v#{version}"
sh "git push"
sh "git push --tags"
end
task :push => 'all:push'
desc 'Build, tag, and push gems for all projects to Rubygems'
task :release => [:build, :tag, :push]
namespace :doc do
require 'yard'
YARD::Rake::YardocTask.new do |task|
task.files = PROJECTS.map{|project| "#{root}/#{project}/lib/**/*.rb"} + ['README.markdown', 'LICENSE']
end
end

View file

@ -1,6 +0,0 @@
require 'omniauth/core'
require 'omniauth/oauth'
require 'omniauth/openid'
require 'omniauth/enterprise'
require 'omniauth/more'
require 'omniauth/identity'

View file

@ -8,6 +8,7 @@ module OmniAuth
autoload :Strategy, 'omniauth/strategy'
autoload :Test, 'omniauth/test'
autoload :Form, 'omniauth/form'
autoload :AuthHash, 'omniauth/auth_hash'
def self.strategies
@@strategies ||= []

View file

@ -99,7 +99,12 @@ module OmniAuth
def self.build(title=nil,&block)
form = OmniAuth::Form.new(title)
form.instance_eval(&block)
if block.arity > 0
yield form
else
form.instance_eval(&block)
end
form
end
def label_field(text, target)

View file

@ -38,12 +38,19 @@ module OmniAuth
return mock_call!(env) if OmniAuth.config.test_mode
return options_call if on_auth_path? && options_request?
return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
return callback_call if on_callback_path?
return other_phase if respond_to?(:other_phase)
@app.call(env)
end
# Responds to an OPTIONS request.
def options_call
verbs = OmniAuth.config.allowed_request_methods.map(&:to_s).map(&:upcase).join(', ')
return [ 200, { 'Allow' => verbs }, [] ]
end
# Performs the steps necessary to run the request phase of a strategy.
def request_call
setup_phase
@ -73,11 +80,19 @@ module OmniAuth
end
def on_request_path?
current_path.casecmp(request_path) == 0
on_path?(request_path)
end
def on_callback_path?
current_path.casecmp(callback_path) == 0
on_path?(callback_path)
end
def on_path?(path)
current_path.casecmp(path) == 0
end
def options_request?
request.request_method == 'OPTIONS'
end
def mock_call!(env)
@ -168,10 +183,7 @@ module OmniAuth
end
def auth_hash
{
'provider' => name.to_s,
'uid' => nil
}
AuthHash.new(:provider => name.to_s)
end
def full_host

View file

View file

@ -1,3 +0,0 @@
--color
--format=nested
--backtrace

View file

@ -1,4 +0,0 @@
--markup markdown
--markup-provider maruku
-
LICENSE

View file

@ -1,3 +0,0 @@
source 'http://rubygems.org'
gemspec

View file

@ -1,19 +0,0 @@
Copyright (c) 2010-2011 Michael Bleigh and Intridea, Inc.
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.

View file

@ -1,6 +0,0 @@
require 'bundler'
Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
task :default => :spec
task :test => :spec

View file

@ -1 +0,0 @@
Autotest.add_discovery { "rspec2" }

View file

@ -1 +0,0 @@
require 'omniauth/core'

View file

@ -1,33 +0,0 @@
require 'omniauth/core'
module OmniAuth
class Builder < ::Rack::Builder
def initialize(app, &block)
@app = app
super(&block)
end
def on_failure(&block)
OmniAuth.config.on_failure = block
end
def configure(&block)
OmniAuth.configure(&block)
end
def provider(klass, *args, &block)
if klass.is_a?(Class)
middleware = klass
else
middleware = OmniAuth::Strategies.const_get("#{OmniAuth::Utils.camelize(klass.to_s)}")
end
use middleware, *args, &block
end
def call(env)
@ins << @app unless @ins.include?(@app)
to_app.call(env)
end
end
end

View file

@ -1,141 +0,0 @@
require 'rack'
require 'singleton'
module OmniAuth
module Strategies; end
autoload :Builder, 'omniauth/builder'
autoload :Strategy, 'omniauth/strategy'
autoload :Test, 'omniauth/test'
autoload :Form, 'omniauth/form'
autoload :AuthHash, 'omniauth/auth_hash'
def self.strategies
@@strategies ||= []
end
class Configuration
include Singleton
@@defaults = {
:path_prefix => '/auth',
:on_failure => Proc.new do |env|
message_key = env['omniauth.error.type']
new_path = "#{OmniAuth.config.path_prefix}/failure?message=#{message_key}"
[302, {'Location' => new_path, 'Content-Type'=> 'text/html'}, []]
end,
:form_css => Form::DEFAULT_CSS,
:test_mode => false,
:allowed_request_methods => [:get, :post],
:mock_auth => {
:default => {
'provider' => 'default',
'uid' => '1234',
'user_info' => {
'name' => 'Bob Example'
}
}
}
}
def self.defaults
@@defaults
end
def initialize
@@defaults.each_pair{|k,v| self.send("#{k}=",v)}
end
def on_failure(&block)
if block_given?
@on_failure = block
else
@on_failure
end
end
def add_mock(provider, mock={})
# Stringify keys recursively one level.
mock.keys.each do |key|
mock[key.to_s] = mock.delete(key)
end
mock.each_pair do |key, val|
if val.is_a? Hash
val.keys.each do |subkey|
val[subkey.to_s] = val.delete(subkey)
end
end
end
# Merge with the default mock and ensure provider is correct.
mock = self.mock_auth[:default].dup.merge(mock)
mock["provider"] = provider.to_s
# Add it to the mocks.
self.mock_auth[provider.to_sym] = mock
end
attr_writer :on_failure
attr_accessor :path_prefix, :allowed_request_methods, :form_css, :test_mode, :mock_auth, :full_host
end
def self.config
Configuration.instance
end
def self.configure
yield config
end
def self.mock_auth_for(provider)
config.mock_auth[provider.to_sym] || config.mock_auth[:default]
end
module Utils
CAMELIZE_SPECIAL = {
'oauth' => 'OAuth',
'oauth2' => 'OAuth2',
'openid' => 'OpenID',
'open_id' => 'OpenID',
'github' => 'GitHub',
'tripit' => 'TripIt',
'soundcloud' => 'SoundCloud',
'smugmug' => 'SmugMug',
'cas' => 'CAS',
'trademe' => 'TradeMe',
'ldap' => 'LDAP',
'google_oauth2' => 'GoogleOAuth2'
}
module_function
def form_css
"<style type='text/css'>#{OmniAuth.config.form_css}</style>"
end
def deep_merge(hash, other_hash)
target = hash.dup
other_hash.keys.each do |key|
if other_hash[key].is_a? ::Hash and hash[key].is_a? ::Hash
target[key] = deep_merge(target[key],other_hash[key])
next
end
target[key] = other_hash[key]
end
target
end
def camelize(word, first_letter_in_uppercase = true)
return CAMELIZE_SPECIAL[word.to_s] if CAMELIZE_SPECIAL[word.to_s]
if first_letter_in_uppercase
word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
else
word.first + camelize(word)[1..-1]
end
end
end
end

View file

@ -1,191 +0,0 @@
require 'omniauth/core'
module OmniAuth
class Form
DEFAULT_CSS = <<-CSS
body {
background: #ccc;
font-family: "Lucida Grande", "Lucida Sans", Helvetica, Arial, sans-serif;
}
h1 {
text-align: center;
margin: 30px auto 0px;
font-size: 18px;
padding: 10px 10px 15px;
background: #555;
color: white;
width: 320px;
border: 10px solid #444;
border-bottom: 0;
-moz-border-radius-topleft: 10px;
-moz-border-radius-topright: 10px;
-webkit-border-top-left-radius: 10px;
-webkit-border-top-right-radius: 10px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
h1, form {
-moz-box-shadow: 2px 2px 7px rgba(0,0,0,0.3);
-webkit-box-shadow: 2px 2px 7px rgba(0,0,0,0.3);
}
form {
background: white;
border: 10px solid #eee;
border-top: 0;
padding: 20px;
margin: 0px auto 40px;
width: 300px;
-moz-border-radius-bottomleft: 10px;
-moz-border-radius-bottomright: 10px;
-webkit-border-bottom-left-radius: 10px;
-webkit-border-bottom-right-radius: 10px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
label {
display: block;
font-weight: bold;
margin-bottom: 5px;
}
input {
font-size: 18px;
padding: 4px 8px;
display: block;
margin-bottom: 10px;
width: 280px;
}
input#identifier, input#openid_url {
background: url(http://openid.net/login-bg.gif) no-repeat;
background-position: 0 50%;
padding-left: 18px;
}
button {
font-size: 22px;
padding: 4px 8px;
display: block;
margin: 20px auto 0;
}
fieldset {
border: 1px solid #ccc;
border-left: 0;
border-right: 0;
padding: 10px 0;
}
fieldset input {
width: 260px;
font-size: 16px;
}
CSS
attr_accessor :options
def initialize(options = {})
options[:title] ||= "Authentication Info Required"
options[:header_info] ||= ""
self.options = options
@html = ""
header(options[:title],options[:header_info])
end
def self.build(title=nil,&block)
form = OmniAuth::Form.new(title)
if block.arity > 0
yield form
else
form.instance_eval(&block)
end
form
end
def label_field(text, target)
@html << "\n<label for='#{target}'>#{text}:</label>"
self
end
def input_field(type, name)
@html << "\n<input type='#{type}' id='#{name}' name='#{name}'/>"
self
end
def text_field(label, name)
label_field(label, name)
input_field('text', name)
self
end
def password_field(label, name)
label_field(label, name)
input_field('password', name)
self
end
def button(text)
@html << "\n<button type='submit'>#{text}</button>"
end
def html(html)
@html << html
end
def fieldset(legend, options = {}, &block)
@html << "\n<fieldset#{" style='#{options[:style]}'" if options[:style]}#{" id='#{options[:id]}'" if options[:id]}>\n <legend>#{legend}</legend>\n"
self.instance_eval &block
@html << "\n</fieldset>"
self
end
def header(title,header_info)
@html << <<-HTML
<!DOCTYPE html>
<html>
<head>
<title>#{title}</title>
#{css}
#{header_info}
</head>
<body>
<h1>#{title}</h1>
<form method='post' #{"action='#{options[:url]}' " if options[:url]}noValidate='noValidate'>
HTML
self
end
def footer
return self if @footer
@html << <<-HTML
<button type='submit'>Connect</button>
</form>
</body>
</html>
HTML
@footer = true
self
end
def to_html
footer
@html
end
def to_response
footer
Rack::Response.new(@html).finish
end
protected
def css
"\n<style type='text/css'>#{OmniAuth.config.form_css}</style>"
end
end
end

View file

@ -1,242 +0,0 @@
require 'omniauth/core'
module OmniAuth
class NoSessionError < StandardError; end
# The Strategy is the base unit of OmniAuth's ability to
# wrangle multiple providers. Each strategy provided by
# OmniAuth includes this mixin to gain the default functionality
# necessary to be compatible with the OmniAuth library.
module Strategy
def self.included(base)
OmniAuth.strategies << base
base.class_eval do
attr_reader :app, :name, :env, :options, :response
end
end
def initialize(app, name, *args, &block)
@app = app
@name = name.to_sym
@options = args.last.is_a?(Hash) ? args.pop : {}
yield self if block_given?
end
def inspect
"#<#{self.class.to_s}>"
end
def call(env)
dup.call!(env)
end
def call!(env)
raise OmniAuth::NoSessionError.new("You must provide a session to use OmniAuth.") unless env['rack.session']
@env = env
@env['omniauth.strategy'] = self if on_auth_path?
return mock_call!(env) if OmniAuth.config.test_mode
return options_call if on_auth_path? && options_request?
return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
return callback_call if on_callback_path?
return other_phase if respond_to?(:other_phase)
@app.call(env)
end
# Responds to an OPTIONS request.
def options_call
verbs = OmniAuth.config.allowed_request_methods.map(&:to_s).map(&:upcase).join(', ')
return [ 200, { 'Allow' => verbs }, [] ]
end
# Performs the steps necessary to run the request phase of a strategy.
def request_call
setup_phase
if response = call_through_to_app
response
else
if request.params['origin']
@env['rack.session']['omniauth.origin'] = request.params['origin']
elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/)
@env['rack.session']['omniauth.origin'] = env['HTTP_REFERER']
end
request_phase
end
end
# Performs the steps necessary to run the callback phase of a strategy.
def callback_call
setup_phase
@env['omniauth.origin'] = session.delete('omniauth.origin')
@env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
callback_phase
end
def on_auth_path?
on_request_path? || on_callback_path?
end
def on_request_path?
on_path?(request_path)
end
def on_callback_path?
on_path?(callback_path)
end
def on_path?(path)
current_path.casecmp(path) == 0
end
def options_request?
request.request_method == 'OPTIONS'
end
def mock_call!(env)
return mock_request_call if on_request_path?
return mock_callback_call if on_callback_path?
call_app!
end
def mock_request_call
setup_phase
return response if response = call_through_to_app
if request.params['origin']
@env['rack.session']['omniauth.origin'] = request.params['origin']
elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/)
@env['rack.session']['omniauth.origin'] = env['HTTP_REFERER']
end
redirect(script_name + callback_path + query_string)
end
def mock_callback_call
setup_phase
mocked_auth = OmniAuth.mock_auth_for(name.to_sym)
if mocked_auth.is_a?(Symbol)
fail!(mocked_auth)
else
@env['omniauth.auth'] = mocked_auth
@env['omniauth.origin'] = session.delete('omniauth.origin')
@env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
call_app!
end
end
def setup_phase
if options[:setup].respond_to?(:call)
options[:setup].call(env)
elsif options[:setup]
setup_env = env.merge('PATH_INFO' => setup_path, 'REQUEST_METHOD' => 'GET')
call_app!(setup_env)
end
end
def request_phase
raise NotImplementedError
end
def callback_phase
@env['omniauth.auth'] = auth_hash
@env['omniauth.params'] = session['query_params'] || {}
session['query_params'] = nil if session['query_params']
call_app!
end
def path_prefix
options[:path_prefix] || OmniAuth.config.path_prefix
end
def request_path
options[:request_path] || "#{path_prefix}/#{name}"
end
def callback_path
options[:callback_path] || "#{path_prefix}/#{name}/callback"
end
def setup_path
options[:setup_path] || "#{path_prefix}/#{name}/setup"
end
def current_path
request.path_info.downcase.sub(/\/$/,'')
end
def query_string
request.query_string.empty? ? "" : "?#{request.query_string}"
end
def call_through_to_app
status, headers, body = *call_app!
session['query_params'] = Rack::Request.new(env).params
@response = Rack::Response.new(body, status, headers)
status == 404 ? nil : @response.finish
end
def call_app!(env = @env)
@app.call(env)
end
def auth_hash
AuthHash.new(:provider => name.to_s)
end
def full_host
case OmniAuth.config.full_host
when String
OmniAuth.config.full_host
when Proc
OmniAuth.config.full_host.call(env)
else
uri = URI.parse(request.url.gsub(/\?.*$/,''))
uri.path = ''
uri.query = nil
uri.to_s
end
end
def callback_url
full_host + script_name + callback_path + query_string
end
def script_name
@env['SCRIPT_NAME'] || ''
end
def session
@env['rack.session']
end
def request
@request ||= Rack::Request.new(@env)
end
def redirect(uri)
r = Rack::Response.new
if options[:iframe]
r.write("<script type='text/javascript' charset='utf-8'>top.location.href = '#{uri}';</script>")
else
r.write("Redirecting to #{uri}...")
r.redirect(uri)
end
r.finish
end
def user_info; {} end
def fail!(message_key, exception = nil)
self.env['omniauth.error'] = exception
self.env['omniauth.error.type'] = message_key.to_sym
self.env['omniauth.error.strategy'] = self
OmniAuth.config.on_failure.call(self.env)
end
end
end

View file

@ -1,12 +0,0 @@
module OmniAuth
# Support for testing OmniAuth strategies.
module Test
autoload :PhonySession, 'omniauth/test/phony_session'
autoload :StrategyMacros, 'omniauth/test/strategy_macros'
autoload :StrategyTestCase, 'omniauth/test/strategy_test_case'
end
end

View file

@ -1,8 +0,0 @@
class OmniAuth::Test::PhonySession
def initialize(app); @app = app end
def call(env)
@session ||= (env['rack.session'] || {})
env['rack.session'] = @session
@app.call(env)
end
end

View file

@ -1,34 +0,0 @@
module OmniAuth
module Test
module StrategyMacros
def sets_an_auth_hash
it 'should set an auth hash' do
last_request.env['omniauth.auth'].should be_kind_of(Hash)
end
end
def sets_provider_to(provider)
it "should set the provider to #{provider}" do
(last_request.env['omniauth.auth'] || {})['provider'].should == provider
end
end
def sets_uid_to(uid)
it "should set the UID to #{uid}" do
(last_request.env['omniauth.auth'] || {})['uid'].should == uid
end
end
def sets_user_info_to(user_info)
it "should set the user_info to #{user_info}" do
(last_request.env['omniauth.auth'] || {})['user_info'].should == user_info
end
end
end
end
end

View file

@ -1,49 +0,0 @@
require 'rack'
require 'omniauth/test'
module OmniAuth
module Test
# Support for testing OmniAuth strategies.
#
# @example Usage
# class MyStrategyTest < Test::Unit::TestCase
# include OmniAuth::Test::StrategyTestCase
# def strategy
# # return the parameters to a Rack::Builder map call:
# [MyStrategy.new, :some, :configuration, :options => 'here']
# end
# setup do
# post '/auth/my_strategy/callback', :user => { 'name' => 'Dylan', 'id' => '445' }
# end
# end
module StrategyTestCase
def app
strat = self.strategy
resp = self.app_response
Rack::Builder.new {
use OmniAuth::Test::PhonySession
use *strat
run lambda {|env| [404, {'Content-Type' => 'text/plain'}, [resp || env.key?('omniauth.auth').to_s]] }
}.to_app
end
def app_response
nil
end
def session
last_request.env['rack.session']
end
def strategy
raise NotImplementedError.new('Including specs must define #strategy')
end
end
end
end

View file

@ -1,19 +0,0 @@
module OmniAuth
module Version
unless defined?(::OmniAuth::Version::MAJOR)
MAJOR = 0
end
unless defined?(::OmniAuth::Version::MINOR)
MINOR = 3
end
unless defined?(::OmniAuth::Version::PATCH)
PATCH = 0
end
unless defined?(::OmniAuth::Version::PRE)
PRE = "rc3"
end
unless defined?(::OmniAuth::Version::STRING)
STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
end
end
end

View file

@ -1,20 +0,0 @@
require File.expand_path('../../spec_helper', __FILE__)
describe OmniAuth::Builder do
describe '#provider' do
it 'should translate a symbol to a constant' do
OmniAuth::Strategies.should_receive(:const_get).with('MyStrategy').and_return(Class.new)
OmniAuth::Builder.new(nil) do
provider :my_strategy
end
end
it 'should also just accept a class' do
class ::ExampleClass; end
lambda{ OmniAuth::Builder.new(nil) do
provider ::ExampleClass
end }.should_not raise_error
end
end
end

View file

@ -1,79 +0,0 @@
require File.expand_path('../../spec_helper', __FILE__)
describe OmniAuth do
describe '.strategies' do
it 'should increase when a new strategy is made' do
lambda{ class ExampleStrategy
include OmniAuth::Strategy
end }.should change(OmniAuth.strategies, :size).by(1)
OmniAuth.strategies.last.should == ExampleStrategy
end
end
context 'configuration' do
it 'should be callable from .configure' do
OmniAuth.configure do |c|
c.should be_kind_of(OmniAuth::Configuration)
end
end
before do
@old_path_prefix = OmniAuth.config.path_prefix
@old_on_failure = OmniAuth.config.on_failure
end
after do
OmniAuth.configure do |config|
config.path_prefix = @old_path_prefix
config.on_failure = @old_on_failure
end
end
it 'should be able to set the path' do
OmniAuth.configure do |config|
config.path_prefix = '/awesome'
end
OmniAuth.config.path_prefix.should == '/awesome'
end
it 'should be able to set the on_failure rack app' do
OmniAuth.configure do |config|
config.on_failure do
'yoyo'
end
end
OmniAuth.config.on_failure.call.should == 'yoyo'
end
end
describe '::Utils' do
describe '.deep_merge' do
it 'should combine hashes' do
OmniAuth::Utils.deep_merge({'abc' => {'def' => 123}}, {'abc' => {'foo' => 'bar'}}).should == {
'abc' => {'def' => 123, 'foo' => 'bar'}
}
end
end
describe '.camelize' do
it 'should work on normal cases' do
{
'some_word' => 'SomeWord',
'AnotherWord' => 'AnotherWord',
'one' => 'One',
'three_words_now' => 'ThreeWordsNow'
}.each_pair{ |k,v| OmniAuth::Utils.camelize(k).should == v }
end
it 'should work in special cases' do
{
'oauth' => "OAuth",
'openid' => 'OpenID',
'open_id' => 'OpenID'
}.each_pair{ |k,v| OmniAuth::Utils.camelize(k).should == v}
end
end
end
end

View file

@ -1,397 +0,0 @@
require File.expand_path('../../spec_helper', __FILE__)
class ExampleStrategy
include OmniAuth::Strategy
def call(env); self.call!(env) end
attr_reader :last_env
def request_phase
@fail = fail!(options[:failure]) if options[:failure]
@last_env = env
return @fail if @fail
raise "Request Phase"
end
def callback_phase
@fail = fail!(options[:failure]) if options[:failure]
@last_env = env
return @fail if @fail
raise "Callback Phase"
end
end
def make_env(path = '/auth/test', props = {})
{
'REQUEST_METHOD' => 'GET',
'PATH_INFO' => path,
'rack.session' => {},
'rack.input' => StringIO.new('test=true')
}.merge(props)
end
describe OmniAuth::Strategy do
let(:app){ lambda{|env| [404, {}, ['Awesome']]}}
describe '#initialize' do
context 'options extraction' do
it 'should be the last argument if the last argument is a Hash' do
ExampleStrategy.new(app, 'test', :abc => 123).options[:abc].should == 123
end
it 'should be a blank hash if none are provided' do
ExampleStrategy.new(app, 'test').options.should == {}
end
end
end
describe '#full_host' do
let(:strategy){ ExampleStrategy.new(app, 'test', {}) }
it 'should not freak out if there is a pipe in the URL' do
strategy.call!(make_env('/whatever', 'rack.url_scheme' => 'http', 'SERVER_NAME' => 'facebook.lame', 'QUERY_STRING' => 'code=asofibasf|asoidnasd', 'SCRIPT_NAME' => '', 'SERVER_PORT' => 80))
lambda{ strategy.full_host }.should_not raise_error
end
end
describe '#call' do
let(:strategy){ ExampleStrategy.new(app, 'test', @options) }
context 'omniauth.origin' do
it 'should be set on the request phase' do
lambda{ strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin')) }.should raise_error("Request Phase")
strategy.last_env['rack.session']['omniauth.origin'].should == 'http://example.com/origin'
end
it 'should be turned into an env variable on the callback phase' do
lambda{ strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'})) }.should raise_error("Callback Phase")
strategy.last_env['omniauth.origin'].should == 'http://example.com/origin'
end
it 'should set from the params if provided' do
lambda{ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo')) }.should raise_error('Request Phase')
strategy.last_env['rack.session']['omniauth.origin'].should == '/foo'
end
it 'should be set on the failure env' do
OmniAuth.config.should_receive(:on_failure).and_return(lambda{|env| env})
@options = {:failure => :forced_fail}
strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => '/awesome'}))
end
context "with script_name" do
it 'should be set on the request phase, containing full path' do
env = {'HTTP_REFERER' => 'http://example.com/sub_uri/origin', 'SCRIPT_NAME' => '/sub_uri' }
lambda{ strategy.call(make_env('/auth/test', env)) }.should raise_error("Request Phase")
strategy.last_env['rack.session']['omniauth.origin'].should == 'http://example.com/sub_uri/origin'
end
it 'should be turned into an env variable on the callback phase, containing full path' do
env = {
'rack.session' => {'omniauth.origin' => 'http://example.com/sub_uri/origin'},
'SCRIPT_NAME' => '/sub_uri'
}
lambda{ strategy.call(make_env('/auth/test/callback', env)) }.should raise_error("Callback Phase")
strategy.last_env['omniauth.origin'].should == 'http://example.com/sub_uri/origin'
end
end
end
context 'default paths' do
it 'should use the default request path' do
lambda{ strategy.call(make_env) }.should raise_error("Request Phase")
end
it 'should be case insensitive on request path' do
lambda{ strategy.call(make_env('/AUTH/Test'))}.should raise_error("Request Phase")
end
it 'should be case insensitive on callback path' do
lambda{ strategy.call(make_env('/AUTH/TeSt/CaLlBAck'))}.should raise_error("Callback Phase")
end
it 'should use the default callback path' do
lambda{ strategy.call(make_env('/auth/test/callback')) }.should raise_error("Callback Phase")
end
it 'should strip trailing spaces on request' do
lambda{ strategy.call(make_env('/auth/test/')) }.should raise_error("Request Phase")
end
it 'should strip trailing spaces on callback' do
lambda{ strategy.call(make_env('/auth/test/callback/')) }.should raise_error("Callback Phase")
end
context 'callback_url' do
it 'uses the default callback_path' do
strategy.should_receive(:full_host).and_return('http://example.com')
lambda{ strategy.call(make_env) }.should raise_error("Request Phase")
strategy.callback_url.should == 'http://example.com/auth/test/callback'
end
it 'preserves the query parameters' do
strategy.stub(:full_host).and_return('http://example.com')
begin
strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5'))
rescue RuntimeError; end
strategy.callback_url.should == 'http://example.com/auth/test/callback?id=5'
end
it 'consider script name' do
strategy.stub(:full_host).and_return('http://example.com')
begin
strategy.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri'))
rescue RuntimeError; end
strategy.callback_url.should == 'http://example.com/sub_uri/auth/test/callback'
end
end
end
context 'pre-request call through' do
subject { ExampleStrategy.new(app, 'test') }
let(:app){ lambda{|env| env['omniauth.boom'] = true; [env['test.status'] || 404, {}, ['Whatev']] } }
it 'should be able to modify the env on the fly before the request_phase' do
lambda{ subject.call(make_env) }.should raise_error("Request Phase")
subject.response.status.should == 404
subject.last_env.should be_key('omniauth.boom')
end
it 'should call through to the app instead if a non-404 response is received' do
lambda{ subject.call(make_env('/auth/test', 'test.status' => 200)) }.should_not raise_error
subject.response.body.should == ['Whatev']
end
end
context 'custom paths' do
it 'should use a custom request_path if one is provided' do
@options = {:request_path => '/awesome'}
lambda{ strategy.call(make_env('/awesome')) }.should raise_error("Request Phase")
end
it 'should use a custom callback_path if one is provided' do
@options = {:callback_path => '/radical'}
lambda{ strategy.call(make_env('/radical')) }.should raise_error("Callback Phase")
end
context 'callback_url' do
it 'uses a custom callback_path if one is provided' do
@options = {:callback_path => '/radical'}
strategy.should_receive(:full_host).and_return('http://example.com')
lambda{ strategy.call(make_env('/radical')) }.should raise_error("Callback Phase")
strategy.callback_url.should == 'http://example.com/radical'
end
it 'preserves the query parameters' do
@options = {:callback_path => '/radical'}
strategy.stub(:full_host).and_return('http://example.com')
begin
strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5'))
rescue RuntimeError; end
strategy.callback_url.should == 'http://example.com/radical?id=5'
end
end
end
context 'custom prefix' do
before do
@options = {:path_prefix => '/wowzers'}
end
it 'should use a custom prefix for request' do
lambda{ strategy.call(make_env('/wowzers/test')) }.should raise_error("Request Phase")
end
it 'should use a custom prefix for callback' do
lambda{ strategy.call(make_env('/wowzers/test/callback')) }.should raise_error("Callback Phase")
end
context 'callback_url' do
it 'uses a custom prefix' do
strategy.should_receive(:full_host).and_return('http://example.com')
lambda{ strategy.call(make_env('/wowzers/test')) }.should raise_error("Request Phase")
strategy.callback_url.should == 'http://example.com/wowzers/test/callback'
end
it 'preserves the query parameters' do
strategy.stub(:full_host).and_return('http://example.com')
begin
strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5'))
rescue RuntimeError; end
strategy.callback_url.should == 'http://example.com/wowzers/test/callback?id=5'
end
end
end
context 'request method restriction' do
before do
OmniAuth.config.allowed_request_methods = [:post]
end
it 'should not allow a request method of the wrong type' do
lambda{ strategy.call(make_env)}.should_not raise_error
end
it 'should allow a request method of the correct type' do
lambda{ strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'POST'))}.should raise_error("Request Phase")
end
after do
OmniAuth.config.allowed_request_methods = [:get, :post]
end
end
context 'receiving an OPTIONS request' do
shared_examples_for "an OPTIONS request" do
it 'should respond with 200' do
response[0].should == 200
end
it 'should set the Allow header properly' do
response[1]['Allow'].should == "GET, POST"
end
end
context 'to the request path' do
let(:response) { strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'OPTIONS')) }
it_should_behave_like 'an OPTIONS request'
end
context 'to the request path' do
let(:response) { strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'OPTIONS')) }
it_should_behave_like 'an OPTIONS request'
end
context 'to some other path' do
it 'should not short-circuit the request' do
env = make_env('/other', 'REQUEST_METHOD' => 'OPTIONS')
strategy.call(env).should == app.call(env)
end
end
end
context 'test mode' do
before do
OmniAuth.config.test_mode = true
end
it 'should short circuit the request phase entirely' do
response = strategy.call(make_env)
response[0].should == 302
response[1]['Location'].should == '/auth/test/callback'
end
it 'should be case insensitive on request path' do
strategy.call(make_env('/AUTH/Test'))[0].should == 302
end
it 'should respect SCRIPT_NAME (a.k.a. BaseURI)' do
response = strategy.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri'))
response[1]['Location'].should == '/sub_uri/auth/test/callback'
end
it 'should be case insensitive on callback path' do
strategy.call(make_env('/AUTH/TeSt/CaLlBAck')).should == strategy.call(make_env('/auth/test/callback'))
end
it 'should maintain query string parameters' do
response = strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'cheese=stilton'))
response[1]['Location'].should == '/auth/test/callback?cheese=stilton'
end
it 'should not short circuit requests outside of authentication' do
strategy.call(make_env('/')).should == app.call(make_env('/'))
end
it 'should respond with the default hash if none is set' do
strategy.call make_env('/auth/test/callback')
strategy.env['omniauth.auth']['uid'].should == '1234'
end
it 'should respond with a provider-specific hash if one is set' do
OmniAuth.config.mock_auth[:test] = {
'uid' => 'abc'
}
strategy.call make_env('/auth/test/callback')
strategy.env['omniauth.auth']['uid'].should == 'abc'
end
it 'should simulate login failure if mocked data is set as a symbol' do
OmniAuth.config.mock_auth[:test] = :invalid_credentials
strategy.call make_env('/auth/test/callback')
strategy.env['omniauth.error.type'].should == :invalid_credentials
end
it 'should set omniauth.origin on the request phase' do
strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin'))
strategy.env['rack.session']['omniauth.origin'].should == 'http://example.com/origin'
end
it 'should set omniauth.origin from the params if provided' do
strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo'))
strategy.env['rack.session']['omniauth.origin'].should == '/foo'
end
it 'should turn omniauth.origin into an env variable on the callback phase' do
OmniAuth.config.mock_auth[:test] = {}
strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'}))
strategy.env['omniauth.origin'].should == 'http://example.com/origin'
end
end
context 'custom full_host' do
it 'should be the string when a string is there' do
OmniAuth.config.full_host = 'my.host.com'
strategy.full_host.should == 'my.host.com'
end
it 'should run the proc with the env when it is a proc' do
OmniAuth.config.full_host = Proc.new{|env| env['HOST']}
strategy.call(make_env('/auth/test', 'HOST' => 'my.host.net'))
strategy.full_host.should == 'my.host.net'
end
end
end
context 'setup phase' do
context 'when options[:setup] = true' do
let(:strategy){ ExampleStrategy.new(app, 'test', :setup => true) }
let(:app){lambda{|env| env['omniauth.strategy'].options[:awesome] = 'sauce' if env['PATH_INFO'] == '/auth/test/setup'; [404, {}, 'Awesome'] }}
it 'should call through to /auth/:provider/setup' do
strategy.call(make_env('/auth/test'))
strategy.options[:awesome].should == 'sauce'
end
it 'should not call through on a non-omniauth endpoint' do
strategy.call(make_env('/somewhere/else'))
strategy.options[:awesome].should_not == 'sauce'
end
end
context 'when options[:setup] is an app' do
let(:setup_proc) do
Proc.new do |env|
env['omniauth.strategy'].options[:awesome] = 'sauce'
end
end
let(:strategy){ ExampleStrategy.new(app, 'test', :setup => setup_proc) }
it 'should not call the app on a non-omniauth endpoint' do
strategy.call(make_env('/somehwere/else'))
strategy.options[:awesome].should_not == 'sauce'
end
it 'should call the rack app' do
strategy.call(make_env('/auth/test'))
strategy.options[:awesome].should == 'sauce'
end
end
end
end

View file

@ -1,12 +0,0 @@
require 'simplecov'
SimpleCov.start
require 'rspec'
require 'rack/test'
require 'omniauth/core'
require 'omniauth/test'
RSpec.configure do |config|
config.include Rack::Test::Methods
config.extend OmniAuth::Test::StrategyMacros, :type => :strategy
end

View file

View file

@ -1,3 +0,0 @@
--color
--format=nested
--backtrace

View file

@ -1,4 +0,0 @@
--markup markdown
--markup-provider maruku
-
LICENSE

View file

@ -1,11 +0,0 @@
require File.expand_path('../lib/omniauth/version', __FILE__)
source 'http://rubygems.org'
gem 'oa-core', OmniAuth::Version::STRING, :path => '../oa-core'
platforms :jruby do
gem 'jruby-openssl', '~> 0.7'
end
gemspec

View file

@ -1,19 +0,0 @@
Copyright (c) 2010-2011 Michael Bleigh and Intridea, Inc.
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.

View file

@ -1,115 +0,0 @@
= OmniAuth::Enterprise
OmniAuth strategies for use in your intranet.
== Installation
To get just enterprise functionality:
gem install oa-enterprise
For the full auth suite:
gem install omniauth
== CAS
Use the CAS strategy as a middleware in your application:
require 'omniauth/enterprise'
use OmniAuth::Strategies::CAS, :server => 'http://cas.mycompany.com/cas'
Then simply direct users to '/auth/cas' to have them sign in via your company's CAS server.
See OmniAuth::Strategies::CAS::Configuration for more configuration options.
== LDAP
Use the LDAP strategy as a middleware in your application:
require 'omniauth/enterprise'
use OmniAuth::Strategies::LDAP,
:title => "My LDAP",
:host => '10.101.10.1',
:port => 389,
:method => :plain,
:base => 'dc=intridea, dc=com',
:uid => 'sAMAccountName',
:name_proc => Proc.new {|name| name.gsub(/@.*$/,'')}
:bind_dn => 'default_bind_dn'
:password => 'password'
All of the listed options are required, with the exception of :name_proc, :bind_dn, and :password
Allowed values of :method are: :plain, :ssl, :tls.
:bind_dn and :password are used to perform the initial binding if user lookup is
needed. If the user lookup returns result, the DN attribute from the result set is used
to perform the final binding. This is needed only when the LDAP server requires
DN to be used for binding and you may only want user to using email or username
in the login form.
:uid is the LDAP attribute name for the user name in the login form. typically
AD would be 'sAMAccountName' or 'UserPrincipalName', while OpenLDAP is 'uid'.
You can also use 'dn', if your user choose the put in the dn in the login form
(but usually is too long for user to remember or know).
:name_proc allows you to match the user name entered with the format of the
:uid attributes. For example, value of 'sAMAccountName' in AD contains only the
windows user name. If your user prefers use email to login, a name_proc as
above will trim the email string down to just the windows name. In summary,
:name_proc helps you to fill the gap between the authentication and user lookup
process.
:try_sasl and :sasl_mechanisms are optional. Use them to initialize a SASL
connection to server. Allowed values are 'DIGEST-MD5' and 'GSS-SPNEGO'. If you
are not familiar with these authentication methods, please just avoid them.
Direct users to '/auth/ldap' to have them authenticated via your
company's LDAP server.
== SAML
Use the SAML strategy as a middleware in your application:
require 'omniauth/enterprise'
use OmniAuth::Strategies::SAML,
:assertion_consumer_service_url => "consumer_service_url",
:issuer => "issuer",
:idp_sso_target_url => "idp_sso_target_url",
:idp_cert_fingerprint => "E7:91:B2:E1:...",
:name_identifier_format => "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
:assertion_consumer_service_url
The URL at which the SAML assertion should be received.
:issuer
The name of your application. Some identity providers might need this to establish the
identity of the service provider requesting the login.
:idp_sso_target_url
The URL to which the authentication request should be sent. This would be on the identity provider.
:idp_cert_fingerprint
The certificate fingerprint, e.g. "90:CC:16:F0:8D:A6:D1:C6:BB:27:2D:BA:93:80:1A:1F:16:8E:4E:08".
This is provided from the identity provider when setting up the relationship.
:name_identifier_format
Describes the format of the username required by this application.
If you need the email address, use "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress".
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf section 8.3 for
other options. Note that the identity provider might not support all options.
== Multiple Strategies
If you're using multiple strategies together, use OmniAuth's Builder. That's
what it's there for:
require 'omniauth/enterprise'
require 'omniauth/oauth' # for Campfire
require 'openid/store/filesystem'
use OmniAuth::Builder do
provider :cas, :server => 'http://cas.mycompany.com/cas'
provider :campfire
end

View file

@ -1,6 +0,0 @@
require 'bundler'
Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
task :default => :spec
task :test => :spec

View file

@ -1 +0,0 @@
require 'omniauth/enterprise'

View file

@ -1,9 +0,0 @@
require 'omniauth/core'
module OmniAuth
module Strategies
autoload :CAS, 'omniauth/strategies/cas'
autoload :LDAP, 'omniauth/strategies/ldap'
autoload :SAML, 'omniauth/strategies/saml'
end
end

View file

@ -1,47 +0,0 @@
require 'omniauth/enterprise'
module OmniAuth
module Strategies
class CAS
include OmniAuth::Strategy
autoload :Configuration, 'omniauth/strategies/cas/configuration'
autoload :ServiceTicketValidator, 'omniauth/strategies/cas/service_ticket_validator'
def initialize(app, options = {}, &block)
super(app, options[:name] || :cas, options.dup, &block)
@configuration = OmniAuth::Strategies::CAS::Configuration.new(options)
end
protected
def request_phase
[
302,
{
'Location' => @configuration.login_url(callback_url),
'Content-Type' => 'text/plain'
},
["You are being redirected to CAS for sign-in."]
]
end
def callback_phase
ticket = request.params['ticket']
return fail!(:no_ticket, 'No CAS Ticket') unless ticket
validator = ServiceTicketValidator.new(@configuration, callback_url, ticket)
@user_info = validator.user_info
return fail!(:invalid_ticket, 'Invalid CAS Ticket') if @user_info.nil? || @user_info.empty?
super
end
def auth_hash
OmniAuth::Utils.deep_merge(super, {
'uid' => @user_info.delete('user'),
'extra' => @user_info
})
end
end
end
end

View file

@ -1,98 +0,0 @@
require 'rack'
module OmniAuth
module Strategies
class CAS
class Configuration
DEFAULT_LOGIN_URL = "%s/login"
DEFAULT_SERVICE_VALIDATE_URL = "%s/serviceValidate"
# @param [Hash] params configuration options
# @option params [String, nil] :cas_server the CAS server root URL; probably something like
# `http://cas.mycompany.com` or `http://cas.mycompany.com/cas`; optional.
# @option params [String, nil] :cas_login_url (:cas_server + '/login') the URL to which to
# redirect for logins; options if `:cas_server` is specified,
# required otherwise.
# @option params [String, nil] :cas_service_validate_url (:cas_server + '/serviceValidate') the
# URL to use for validating service tickets; optional if `:cas_server` is
# specified, requred otherwise.
# @option params [Boolean, nil] :disable_ssl_verification disable verification for SSL cert,
# helpful when you developing with a fake cert.
def initialize(params)
parse_params params
end
# Build a CAS login URL from +service+.
#
# @param [String] service the service (a.k.a. return-to) URL
#
# @return [String] a URL like `http://cas.mycompany.com/login?service=...`
def login_url(service)
append_service @login_url, service
end
# Build a service-validation URL from +service+ and +ticket+.
# If +service+ has a ticket param, first remove it. URL-encode
# +service+ and add it and the +ticket+ as paraemters to the
# CAS serviceValidate URL.
#
# @param [String] service the service (a.k.a. return-to) URL
# @param [String] ticket the ticket to validate
#
# @return [String] a URL like `http://cas.mycompany.com/serviceValidate?service=...&ticket=...`
def service_validate_url(service, ticket)
service = service.sub(/[?&]ticket=[^?&]+/, '')
url = append_service(@service_validate_url, service)
url << '&ticket=' << Rack::Utils.escape(ticket)
end
def disable_ssl_verification?
@disable_ssl_verification
end
private
def parse_params(params)
if params[:cas_server].nil? && params[:cas_login_url].nil?
raise ArgumentError.new(":cas_server or :cas_login_url MUST be provided")
end
@login_url = params[:cas_login_url]
@login_url ||= DEFAULT_LOGIN_URL % params[:cas_server]
validate_is_url 'login URL', @login_url
if params[:cas_server].nil? && params[:cas_service_validate_url].nil?
raise ArgumentError.new(":cas_server or :cas_service_validate_url MUST be provided")
end
@service_validate_url = params[:cas_service_validate_url]
@service_validate_url ||= DEFAULT_SERVICE_VALIDATE_URL % params[:cas_server]
validate_is_url 'service-validate URL', @service_validate_url
@disable_ssl_verification = params[:disable_ssl_verification]
end
IS_NOT_URL_ERROR_MESSAGE = "%s is not a valid URL"
def validate_is_url(name, possibly_a_url)
url = URI.parse(possibly_a_url) rescue nil
raise ArgumentError.new(IS_NOT_URL_ERROR_MESSAGE % name) unless url.kind_of?(URI::HTTP)
end
# Adds +service+ as an URL-escaped parameter to +base+.
#
# @param [String] base the base URL
# @param [String] service the service (a.k.a. return-to) URL.
#
# @return [String] the new joined URL.
def append_service(base, service)
result = base.dup
result << (result.include?('?') ? '&' : '?')
result << 'service='
result << Rack::Utils.escape(service)
end
end
end
end
end

View file

@ -1,91 +0,0 @@
require 'net/http'
require 'net/https'
require 'nokogiri'
module OmniAuth
module Strategies
class CAS
class ServiceTicketValidator
VALIDATION_REQUEST_HEADERS = { 'Accept' => '*/*' }
# Build a validator from a +configuration+, a
# +return_to+ URL, and a +ticket+.
#
# @param [OmniAuth::Strategies::CAS::Configuration] configuration the CAS configuration
# @param [String] return_to_url the URL of this CAS client service
# @param [String] ticket the service ticket to validate
def initialize(configuration, return_to_url, ticket)
@configuration = configuration
@uri = URI.parse(@configuration.service_validate_url(return_to_url, ticket))
end
# Request validation of the ticket from the CAS server's
# serviceValidate (CAS 2.0) function.
#
# Swallows all XML parsing errors (and returns +nil+ in those cases).
#
# @return [Hash, nil] a user information hash if the response is valid; +nil+ otherwise.
#
# @raise any connection errors encountered.
def user_info
parse_user_info(find_authentication_success(get_service_response_body))
end
private
# turns an `<cas:authenticationSuccess>` node into a Hash;
# returns nil if given nil
def parse_user_info(node)
return nil if node.nil?
hash = {}
node.children.each do |e|
unless e.kind_of?(Nokogiri::XML::Text) ||
e.name == 'cas:proxies' ||
e.name == 'proxies'
# There are no child elements
if e.element_children.count == 0
hash[e.name.sub(/^cas:/, '')] = e.content
elsif e.element_children.count
hash[e.name.sub(/^cas:/, '')] = [] if hash[e.name.sub(/^cas:/, '')].nil?
hash[e.name.sub(/^cas:/, '')].push parse_user_info e
end
end
end
hash
end
# finds an `<cas:authenticationSuccess>` node in
# a `<cas:serviceResponse>` body if present; returns nil
# if the passed body is nil or if there is no such node.
def find_authentication_success(body)
return nil if body.nil? || body == ''
begin
doc = Nokogiri::XML(body)
begin
doc.xpath('/cas:serviceResponse/cas:authenticationSuccess')
rescue Nokogiri::XML::XPath::SyntaxError
doc.xpath('/serviceResponse/authenticationSuccess')
end
rescue Nokogiri::XML::XPath::SyntaxError
nil
end
end
# retrieves the `<cas:serviceResponse>` XML from the CAS server
def get_service_response_body
result = ''
http = ::Net::HTTP.new(@uri.host, @uri.port)
http.use_ssl = @uri.port == 443 || @uri.instance_of?(URI::HTTPS)
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl? && @configuration.disable_ssl_verification?
http.start do |c|
response = c.get "#{@uri.path}?#{@uri.query}", VALIDATION_REQUEST_HEADERS.dup
result = response.body
end
result
end
end
end
end
end

View file

@ -1,124 +0,0 @@
require 'omniauth/enterprise'
require 'net/ldap'
require 'sasl/base'
require 'sasl'
module OmniAuth
module Strategies
class LDAP
include OmniAuth::Strategy
autoload :Adaptor, 'omniauth/strategies/ldap/adaptor'
@@config = {
'name' => 'cn',
'first_name' => 'givenName',
'last_name' => 'sn',
'email' => ['mail', "email", 'userPrincipalName'],
'phone' => ['telephoneNumber', 'homePhone', 'facsimileTelephoneNumber'],
'mobile_number' => ['mobile', 'mobileTelephoneNumber'],
'nickname' => ['uid', 'userid', 'sAMAccountName'],
'title' => 'title',
'location' => {"%0, %1, %2, %3 %4" => [['address', 'postalAddress', 'homePostalAddress', 'street', 'streetAddress'], ['l'], ['st'],['co'],['postOfficeBox']]},
'uid' => 'dn',
'url' => ['wwwhomepage'],
'image' => 'jpegPhoto',
'description' => 'description'
}
# Initialize the LDAP Middleware
#
# @param [Rack Application] app Standard Rack middleware argument.
# @option options [String, 'LDAP Authentication'] :title A title for the authentication form.
def initialize(app, options = {}, &block)
super(app, options[:name] || :ldap, options.dup, &block)
@name_proc = (@options.delete(:name_proc) || Proc.new {|name| name})
@adaptor = OmniAuth::Strategies::LDAP::Adaptor.new(options)
end
protected
def request_phase
if env['REQUEST_METHOD'] == 'GET'
get_credentials
else
session['omniauth.ldap'] = {'username' => request['username'], 'password' => request['password']}
redirect callback_path
end
end
def get_credentials
OmniAuth::Form.build(:title => (options[:title] || "LDAP Authentication")) do
text_field 'Login', 'username'
password_field 'Password', 'password'
end.to_response
end
def callback_phase
begin
creds = session['omniauth.ldap']
session.delete 'omniauth.ldap'
@ldap_user_info = {}
begin
(@adaptor.bind(:allow_anonymous => true) unless @adaptor.bound?)
rescue Exception => e
puts "failed to bind with the default credentials: " + e.message
end
@ldap_user_info = @adaptor.search(:filter => Net::LDAP::Filter.eq(@adaptor.uid, @name_proc.call(creds['username'])),:limit => 1) if @adaptor.bound?
bind_dn = creds['username']
bind_dn = @ldap_user_info[:dn].to_a.first if @ldap_user_info[:dn]
@adaptor.bind(:bind_dn => bind_dn, :password => creds['password'])
@ldap_user_info = @adaptor.search(:filter => Net::LDAP::Filter.eq(@adaptor.uid, @name_proc.call(creds['username'])),:limit => 1) if @ldap_user_info.empty?
@user_info = self.class.map_user(@@config, @ldap_user_info)
@env['omniauth.auth'] = auth_hash
rescue Exception => e
return fail!(:invalid_credentials, e)
end
call_app!
end
def auth_hash
OmniAuth::Utils.deep_merge(super, {
'uid' => @user_info["uid"],
'user_info' => @user_info,
'extra' => @ldap_user_info
})
end
# Use only first value if the field is returned as an Array
def self.get_ldap_field(ldap_object, field)
value = ldap_object[field.to_sym]
case value
when Array
value.first.to_s
else
value.to_s
end
end
def self.map_user(mapper, object)
user = {}
mapper.each do |key, value|
case value
when String
user[key] = get_ldap_field(object, value.downcase) if object[value.downcase.to_sym]
when Array
value.each {|v| (user[key] = get_ldap_field(object, v.downcase); break;) if object[v.downcase.to_sym]}
when Hash
value.map do |key1, value1|
pattern = key1.dup
value1.each_with_index do |v,i|
part = '';
v.each {|v1| (part = get_ldap_field(object, v1.downcase); break;) if object[v1.downcase.to_sym]}
pattern.gsub!("%#{i}",part||'')
end
user[key] = pattern
end
end
end
user
end
end
end
end

View file

@ -1,276 +0,0 @@
#this code boughts pieces from activeldap and net-ldap
require 'rack'
require 'net/ldap'
require 'net/ntlm'
require 'uri'
module OmniAuth
module Strategies
class LDAP
class Adaptor
class LdapError < StandardError; end
class ConfigurationError < StandardError; end
class AuthenticationError < StandardError; end
class ConnectionError < StandardError; end
VALID_ADAPTER_CONFIGURATION_KEYS = [:host, :port, :method, :bind_dn, :password, :try_sasl, :sasl_mechanisms, :uid, :base, :allow_anonymous]
MUST_HAVE_KEYS = [:host, :port, :method, :uid, :base]
METHOD = {
:ssl => :simple_tls,
:tls => :start_tls,
:plain => nil,
}
attr_accessor :bind_dn, :password
attr_reader :connection, :uid, :base
def initialize(configuration={})
@connection = nil
@disconnected = false
@bound = false
@configuration = configuration.dup
@configuration[:allow_anonymous] ||= false
@logger = @configuration.delete(:logger)
message = []
MUST_HAVE_KEYS.each do |name|
message << name if configuration[name].nil?
end
raise ArgumentError.new(message.join(",") +" MUST be provided") unless message.empty?
VALID_ADAPTER_CONFIGURATION_KEYS.each do |name|
instance_variable_set("@#{name}", configuration[name])
end
end
def connect(options={})
host = options[:host] || @host
method = ensure_method(options[:method] || @method || :plain)
port = options[:port] || @port || ensure_port(method)
@disconnected = false
@bound = false
@bind_tried = false
config = {
:host => host,
:port => port,
}
config[:encryption] = {:method => method} if method
@connection, @uri, @with_start_tls = begin
uri = construct_uri(host, port, method == :simple_tls)
with_start_tls = method == :start_tls
[Net::LDAP::Connection.new(config), uri, with_start_tls]
rescue Net::LDAP::LdapError
raise ConnectionError, $!.message
end
end
def unbind(options={})
@connection.close # Net::LDAP doesn't implement unbind.
end
def bind(options={})
connect(options) unless connecting?
begin
@bind_tried = true
bind_dn = (options[:bind_dn] || @bind_dn).to_s
try_sasl = options.has_key?(:try_sasl) ? options[:try_sasl] : @try_sasl
if options.has_key?(:allow_anonymous)
allow_anonymous = options[:allow_anonymous]
else
allow_anonymous = @allow_anonymous
end
# Rough bind loop:
# Attempt 1: SASL if available
# Attempt 2: SIMPLE with credentials if password block
# Attempt 3: SIMPLE ANONYMOUS if 1 and 2 fail and allow anonymous is set to true
if try_sasl and sasl_bind(bind_dn, options)
puts "bound with sasl"
elsif simple_bind(bind_dn, options)
puts "bound with simple"
elsif allow_anonymous and bind_as_anonymous(options)
puts "bound as anonymous"
else
message = yield if block_given?
message ||= ('All authentication methods for %s exhausted.') % target
raise AuthenticationError, message
end
@bound = true
rescue Net::LDAP::LdapError
raise AuthenticationError, $!.message
end
end
def disconnect!(options={})
unbind(options)
@connection = @uri = @with_start_tls = nil
@disconnected = true
end
def rebind(options={})
unbind(options) if bound?
connect(options)
end
def connecting?
!@connection.nil? and !@disconnected
end
def bound?
connecting? and @bound
end
def search(options={}, &block)
base = options[:base] || @base
filter = options[:filter]
limit = options[:limit]
args = {
:base => base,
:filter => filter,
:size => limit
}
attributes = {}
execute(:search, args) do |entry|
entry.attribute_names.each do |name|
attributes[name] = entry[name]
end
end
attributes
end
private
def execute(method, *args, &block)
result = @connection.send(method, *args, &block)
message = nil
if result.is_a?(Hash)
message = result[:errorMessage]
result = result[:resultCode]
end
unless result.zero?
message = [Net::LDAP.result2string(result), message].compact.join(": ")
raise LdapError, message
end
end
def ensure_port(method)
if method == :ssl
URI::LDAPS::DEFAULT_PORT
else
URI::LDAP::DEFAULT_PORT
end
end
def prepare_connection(options)
end
def ensure_method(method)
method ||= "plain"
normalized_method = method.to_s.downcase.to_sym
return METHOD[normalized_method] if METHOD.has_key?(normalized_method)
available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ")
format = "%s is not one of the available connect methods: %s"
raise ConfigurationError, format % [method.inspect, available_methods]
end
def sasl_bind(bind_dn, options={})
sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms
sasl_mechanisms.each do |mechanism|
begin
normalized_mechanism = mechanism.downcase.gsub(/-/, '_')
sasl_bind_setup = "sasl_bind_setup_#{normalized_mechanism}"
next unless respond_to?(sasl_bind_setup, true)
initial_credential, challenge_response = send(sasl_bind_setup, bind_dn, options)
args = {
:method => :sasl,
:initial_credential => initial_credential,
:mechanism => mechanism,
:challenge_response => challenge_response,
}
info = {
:name => "bind: SASL", :dn => bind_dn, :mechanism => mechanism,
}
execute(:bind, args)
return true
rescue Exception => e
puts e.message
end
end
false
end
def sasl_bind_setup_digest_md5(bind_dn, options)
initial_credential = ""
challenge_response = Proc.new do |cred|
pref = SASL::Preferences.new :digest_uri => "ldap/#{@host}", :username => bind_dn, :has_password? => true, :password => options[:password]||@password
sasl = SASL.new("DIGEST-MD5", pref)
response = sasl.receive("challenge", cred)
response[1]
end
[initial_credential, challenge_response]
end
def sasl_bind_setup_gss_spnego(bind_dn, options)
user,psw = [bind_dn, options[:password]||@password]
raise LdapError.new( "invalid binding information" ) unless (user && psw)
nego = proc {|challenge|
t2_msg = Net::NTLM::Message.parse( challenge )
user, domain = user.split('\\').reverse
t2_msg.target_name = Net::NTLM::encode_utf16le(domain) if domain
t3_msg = t2_msg.response( {:user => user, :password => psw}, {:ntlmv2 => true} )
t3_msg.serialize
}
[Net::NTLM::Message::Type1.new.serialize, nego]
end
def simple_bind(bind_dn, options={})
args = {
:method => :simple,
:username => bind_dn,
:password => (options[:password]||@password).to_s,
}
begin
raise AuthenticationError if args[:password] == ""
execute(:bind, args)
true
rescue Exception
false
end
end
def bind_as_anonymous(options={})
execute(:bind, {:method => :anonymous})
true
end
def construct_uri(host, port, ssl)
protocol = ssl ? "ldaps" : "ldap"
URI.parse("#{protocol}://#{host}:#{port}").to_s
end
def target
return nil if @uri.nil?
if @with_start_tls
"#{@uri}(StartTLS)"
else
@uri
end
end
end
end
end
end

View file

@ -1,50 +0,0 @@
require 'omniauth/enterprise'
module OmniAuth
module Strategies
class SAML
include OmniAuth::Strategy
autoload :AuthRequest, 'omniauth/strategies/saml/auth_request'
autoload :AuthResponse, 'omniauth/strategies/saml/auth_response'
autoload :ValidationError, 'omniauth/strategies/saml/validation_error'
autoload :XMLSecurity, 'omniauth/strategies/saml/xml_security'
@@settings = {}
def initialize(app, options={})
super(app, :saml)
@@settings = {
:assertion_consumer_service_url => options[:assertion_consumer_service_url],
:issuer => options[:issuer],
:idp_sso_target_url => options[:idp_sso_target_url],
:idp_cert_fingerprint => options[:idp_cert_fingerprint],
:name_identifier_format => options[:name_identifier_format] || "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
}
end
def request_phase
request = OmniAuth::Strategies::SAML::AuthRequest.new
redirect(request.create(@@settings))
end
def callback_phase
begin
response = OmniAuth::Strategies::SAML::AuthResponse.new(request.params['SAMLResponse'])
response.settings = @@settings
@name_id = response.name_id
return fail!(:invalid_ticket, 'Invalid SAML Ticket') if @name_id.nil? || @name_id.empty?
super
rescue ArgumentError => e
fail!(:invalid_ticket, 'Invalid SAML Response')
end
end
def auth_hash
OmniAuth::Utils.deep_merge(super, {
'uid' => @name_id
})
end
end
end
end

View file

@ -1,38 +0,0 @@
require "base64"
require "uuid"
require "zlib"
require "cgi"
module OmniAuth
module Strategies
class SAML
class AuthRequest
def create(settings, params = {})
uuid = "_" + UUID.new.generate
time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
request =
"<samlp:AuthnRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"#{uuid}\" Version=\"2.0\" IssueInstant=\"#{time}\" ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" AssertionConsumerServiceURL=\"#{settings[:assertion_consumer_service_url]}\">" +
"<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{settings[:issuer]}</saml:Issuer>\n" +
"<samlp:NameIDPolicy xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Format=\"#{settings[:name_identifier_format]}\" AllowCreate=\"true\"></samlp:NameIDPolicy>\n" +
"<samlp:RequestedAuthnContext xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Comparison=\"exact\">" +
"<saml:AuthnContextClassRef xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext>\n" +
"</samlp:AuthnRequest>"
deflated_request = Zlib::Deflate.deflate(request, 9)[2..-5]
base64_request = Base64.encode64(deflated_request)
encoded_request = CGI.escape(base64_request)
request_params = "?SAMLRequest=" + encoded_request
params.each_pair do |key, value|
request_params << "&#{key}=#{CGI.escape(value.to_s)}"
end
settings[:idp_sso_target_url] + request_params
end
end
end
end
end

View file

@ -1,141 +0,0 @@
require "time"
module OmniAuth
module Strategies
class SAML
class AuthResponse
ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
DSIG = "http://www.w3.org/2000/09/xmldsig#"
attr_accessor :options, :response, :document, :settings
def initialize(response, options = {})
raise ArgumentError.new("Response cannot be nil") if response.nil?
self.options = options
self.response = response
self.document = OmniAuth::Strategies::SAML::XMLSecurity::SignedDocument.new(Base64.decode64(response))
end
def is_valid?
validate(soft = true)
end
def validate!
validate(soft = false)
end
# The value of the user identifier as designated by the initialization request response
def name_id
@name_id ||= begin
node = REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
node ||= REXML::XPath.first(document, "/p:Response[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Assertion/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
node.nil? ? nil : node.text
end
end
# A hash of alle the attributes with the response. Assuming there is only one value for each key
def attributes
@attr_statements ||= begin
result = {}
stmt_element = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AttributeStatement", { "p" => PROTOCOL, "a" => ASSERTION })
return {} if stmt_element.nil?
stmt_element.elements.each do |attr_element|
name = attr_element.attributes["Name"]
value = attr_element.elements.first.text
result[name] = value
end
result.keys.each do |key|
result[key.intern] = result[key]
end
result
end
end
# When this user session should expire at latest
def session_expires_at
@expires_at ||= begin
node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AuthnStatement", { "p" => PROTOCOL, "a" => ASSERTION })
parse_time(node, "SessionNotOnOrAfter")
end
end
# Conditions (if any) for the assertion to run
def conditions
@conditions ||= begin
REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Conditions", { "p" => PROTOCOL, "a" => ASSERTION })
end
end
private
def validation_error(message)
raise OmniAuth::Strategies::SAML::ValidationError.new(message)
end
def validate(soft = true)
validate_response_state(soft) &&
validate_conditions(soft) &&
document.validate(get_fingerprint, soft)
end
def validate_response_state(soft = true)
if response.empty?
return soft ? false : validation_error("Blank response")
end
if settings.nil?
return soft ? false : validation_error("No settings on response")
end
if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil?
return soft ? false : validation_error("No fingerprint or certificate on settings")
end
true
end
def get_fingerprint
if settings.idp_cert
cert = OpenSSL::X509::Certificate.new(settings.idp_cert)
Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
else
settings.idp_cert_fingerprint
end
end
def validate_conditions(soft = true)
return true if conditions.nil?
return true if options[:skip_conditions]
if not_before = parse_time(conditions, "NotBefore")
if Time.now.utc < not_before
return soft ? false : validation_error("Current time is earlier than NotBefore condition")
end
end
if not_on_or_after = parse_time(conditions, "NotOnOrAfter")
if Time.now.utc >= not_on_or_after
return soft ? false : validation_error("Current time is on or after NotOnOrAfter condition")
end
end
true
end
def parse_time(node, attribute)
if node && node.attributes[attribute]
Time.parse(node.attributes[attribute])
end
end
end
end
end
end

View file

@ -1,8 +0,0 @@
module OmniAuth
module Strategies
class SAML
class ValidationError < Exception
end
end
end
end

View file

@ -1,126 +0,0 @@
# The contents of this file are subject to the terms
# of the Common Development and Distribution License
# (the License). You may not use this file except in
# compliance with the License.
#
# You can obtain a copy of the License at
# https://opensso.dev.java.net/public/CDDLv1.0.html or
# opensso/legal/CDDLv1.0.txt
# See the License for the specific language governing
# permission and limitations under the License.
#
# When distributing Covered Code, include this CDDL
# Header Notice in each file and include the License file
# at opensso/legal/CDDLv1.0.txt.
# If applicable, add the following below the CDDL Header,
# with the fields enclosed by brackets [] replaced by
# your own identifying information:
# "Portions Copyrighted [year] [name of copyright owner]"
#
# $Id: xml_sec.rb,v 1.6 2007/10/24 00:28:41 todddd Exp $
#
# Copyright 2007 Sun Microsystems Inc. All Rights Reserved
# Portions Copyrighted 2007 Todd W Saxton.
require 'rubygems'
require "rexml/document"
require "rexml/xpath"
require "openssl"
require "xmlcanonicalizer"
require "digest/sha1"
module OmniAuth
module Strategies
class SAML
module XMLSecurity
class SignedDocument < REXML::Document
DSIG = "http://www.w3.org/2000/09/xmldsig#"
attr_accessor :signed_element_id
def initialize(response)
super(response)
extract_signed_element_id
end
def validate(idp_cert_fingerprint, soft = true)
# get cert from response
base64_cert = self.elements["//ds:X509Certificate"].text
cert_text = Base64.decode64(base64_cert)
cert = OpenSSL::X509::Certificate.new(cert_text)
# check cert matches registered idp cert
fingerprint = Digest::SHA1.hexdigest(cert.to_der)
if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase
return soft ? false : (raise OmniAuth::Strategies::SAML::ValidationError.new("Fingerprint mismatch"))
end
validate_doc(base64_cert, soft)
end
def validate_doc(base64_cert, soft = true)
# validate references
# check for inclusive namespaces
inclusive_namespaces = []
inclusive_namespace_element = REXML::XPath.first(self, "//ec:InclusiveNamespaces")
if inclusive_namespace_element
prefix_list = inclusive_namespace_element.attributes.get_attribute('PrefixList').value
inclusive_namespaces = prefix_list.split(" ")
end
# remove signature node
sig_element = REXML::XPath.first(self, "//ds:Signature", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"})
sig_element.remove
# check digests
REXML::XPath.each(sig_element, "//ds:Reference", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}) do |ref|
uri = ref.attributes.get_attribute("URI").value
hashed_element = REXML::XPath.first(self, "//[@ID='#{uri[1,uri.size]}']")
canoner = XML::Util::XmlCanonicalizer.new(false, true)
canoner.inclusive_namespaces = inclusive_namespaces if canoner.respond_to?(:inclusive_namespaces) && !inclusive_namespaces.empty?
canon_hashed_element = canoner.canonicalize(hashed_element)
hash = Base64.encode64(Digest::SHA1.digest(canon_hashed_element)).chomp
digest_value = REXML::XPath.first(ref, "//ds:DigestValue", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}).text
if hash != digest_value
return soft ? false : (raise OmniAuth::Strategies::SAML::ValidationError.new("Digest mismatch"))
end
end
# verify signature
canoner = XML::Util::XmlCanonicalizer.new(false, true)
signed_info_element = REXML::XPath.first(sig_element, "//ds:SignedInfo", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"})
canon_string = canoner.canonicalize(signed_info_element)
base64_signature = REXML::XPath.first(sig_element, "//ds:SignatureValue", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}).text
signature = Base64.decode64(base64_signature)
# get certificate object
cert_text = Base64.decode64(base64_cert)
cert = OpenSSL::X509::Certificate.new(cert_text)
if !cert.public_key.verify(OpenSSL::Digest::SHA1.new, signature, canon_string)
return soft ? false : (raise OmniAuth::Strategies::SAML::ValidationError.new("Key validation error"))
end
return true
end
private
def extract_signed_element_id
reference_element = REXML::XPath.first(self, "//ds:Signature/ds:SignedInfo/ds:Reference", {"ds"=>DSIG})
self.signed_element_id = reference_element.attribute("URI").value unless reference_element.nil?
end
end
end
end
end
end

View file

@ -1,19 +0,0 @@
module OmniAuth
module Version
unless defined?(::OmniAuth::Version::MAJOR)
MAJOR = 0
end
unless defined?(::OmniAuth::Version::MINOR)
MINOR = 3
end
unless defined?(::OmniAuth::Version::PATCH)
PATCH = 0
end
unless defined?(::OmniAuth::Version::PRE)
PRE = "rc3"
end
unless defined?(::OmniAuth::Version::STRING)
STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
end
end
end

View file

@ -1,31 +0,0 @@
# encoding: utf-8
require File.expand_path('../lib/omniauth/version', __FILE__)
Gem::Specification.new do |gem|
gem.add_dependency 'addressable', '~> 2.2.6'
gem.add_dependency 'net-ldap', '~> 0.2.2'
gem.add_dependency 'nokogiri', '~> 1.5.0'
gem.add_dependency 'oa-core', OmniAuth::Version::STRING
gem.add_dependency 'pyu-ruby-sasl', '~> 0.0.3.1'
gem.add_dependency 'rubyntlm', '~> 0.1.1'
gem.add_dependency 'uuid'
gem.add_dependency 'XMLCanonicalizer', '~> 1.0.1'
gem.add_development_dependency 'rack-test', '~> 0.5'
gem.add_development_dependency 'rake', '~> 0.8'
gem.add_development_dependency 'rdiscount', '~> 1.6'
gem.add_development_dependency 'rspec', '~> 2.5'
gem.add_development_dependency 'simplecov', '~> 0.4'
gem.add_development_dependency 'webmock', '~> 1.7'
gem.add_development_dependency 'yard', '~> 0.7'
gem.authors = ['James A. Rosen', 'Ping Yu', 'Michael Bleigh', 'Erik Michaels-Ober', 'Raecoo Cao']
gem.description = %q{Enterprise strategies for OmniAuth.}
gem.email = ['james.a.rosen@gmail.com', 'ping@intridea.com', 'michael@intridea.com', 'sferik@gmail.com', 'raecoo@intridea.com']
gem.files = `git ls-files`.split("\n")
gem.homepage = 'http://github.com/intridea/omniauth'
gem.name = 'oa-enterprise'
gem.require_paths = ['lib']
gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if gem.respond_to? :required_rubygems_version=
gem.summary = gem.description
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
gem.version = OmniAuth::Version::STRING
end

View file

@ -1,4 +0,0 @@
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationFailure>
</cas:authenticationFailure>
</cas:serviceResponse>

View file

@ -1,8 +0,0 @@
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>psegel</cas:user>
<cas:first-name>Peter</cas:first-name>
<cas:last-name>Segel</cas:last-name>
<hire-date>2004-07-13</hire-date>
</cas:authenticationSuccess>
</cas:serviceResponse>

View file

@ -1,94 +0,0 @@
require File.expand_path('../../../spec_helper', __FILE__)
require 'cgi'
describe OmniAuth::Strategies::CAS, :type => :strategy do
include OmniAuth::Test::StrategyTestCase
def strategy
@cas_server ||= 'https://cas.example.org'
[OmniAuth::Strategies::CAS, {:cas_server => @cas_server}]
end
describe 'GET /auth/cas' do
before do
get '/auth/cas'
end
it 'should redirect to the CAS server' do
last_response.should be_redirect
return_to = CGI.escape(last_request.url + '/callback')
last_response.headers['Location'].should == @cas_server + '/login?service=' + return_to
end
end
describe 'GET /auth/cas/callback without a ticket' do
before do
get '/auth/cas/callback'
end
it 'should fail' do
last_response.should be_redirect
last_response.headers['Location'].should =~ /no_ticket/
end
end
describe 'GET /auth/cas/callback with an invalid ticket' do
before do
stub_request(:get, /^https:\/\/cas.example.org(:443)?\/serviceValidate\?([^&]+&)?ticket=9391d/).
to_return(:body => File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'cas_failure.xml')))
get '/auth/cas/callback?ticket=9391d'
end
it 'should fail' do
last_response.should be_redirect
last_response.headers['Location'].should =~ /invalid_ticket/
end
end
describe 'GET /auth/cas/callback with a valid ticket' do
before do
stub_request(:get, /^https:\/\/cas.example.org(:443)?\/serviceValidate\?([^&]+&)?ticket=593af/).
with { |request| @request_uri = request.uri.to_s }.
to_return(:body => File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'cas_success.xml')))
get '/auth/cas/callback?ticket=593af'
end
it 'should strip the ticket parameter from the callback URL before sending it to the CAS server' do
@request_uri.scan('ticket=').length.should == 1
end
sets_an_auth_hash
sets_provider_to 'cas'
sets_uid_to 'psegel'
it 'should set additional user information' do
extra = (last_request.env['omniauth.auth'] || {})['extra']
extra.should be_kind_of(Hash)
extra['first-name'].should == 'Peter'
extra['last-name'].should == 'Segel'
extra['hire-date'].should == '2004-07-13'
end
it 'should call through to the master app' do
last_response.body.should == 'true'
end
end
unless RUBY_VERSION =~ /^1\.8\.\d$/
describe 'GET /auth/cas/callback with a valid ticket and gzipped response from the server on ruby >1.8' do
before do
zipped = StringIO.new
Zlib::GzipWriter.wrap zipped do |io|
io.write File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'cas_success.xml'))
end
stub_request(:get, /^https:\/\/cas.example.org(:443)?\/serviceValidate\?([^&]+&)?ticket=593af/).
with { |request| @request_uri = request.uri.to_s }.
to_return(:body => zipped.string, :headers => { 'content-encoding' => 'gzip' })
get '/auth/cas/callback?ticket=593af'
end
it 'should call through to the master app when response is gzipped' do
last_response.body.should == 'true'
end
end
end
end

View file

@ -1,41 +0,0 @@
require File.expand_path('../../../spec_helper', __FILE__)
require 'cgi'
describe OmniAuth::Strategies::LDAP, :type => :strategy do
include OmniAuth::Test::StrategyTestCase
def strategy
@ldap_server ||= 'ldap.example.org'
[OmniAuth::Strategies::LDAP, {
:host => @ldap_server,
:port => 636,
:method => :ssl,
:uid => 'jeremyf',
:base => 'o="University of OmniAuth", st=Sublime, c=RubyNation',
}]
end
describe 'GET /auth/ldap' do
before do
get '/auth/ldap'
end
# TODO: Add checks that page has authentication form; I attempted
# to use `should have_tag` but that was not working.
it 'should get authentication page' do
last_response.status.should == 200
end
end
describe 'POST /auth/ldap' do
before do
post '/auth/ldap', {:username => 'jeremy', :password => 'valid_password' }
end
it 'should redirect us to /auth/ldap/callback' do
last_response.should be_redirect
last_response.location.should == '/auth/ldap/callback'
end
end
end

View file

@ -1,37 +0,0 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe OmniAuth::Strategies::SAML, :type => :strategy do
include OmniAuth::Test::StrategyTestCase
def strategy
[OmniAuth::Strategies::SAML, {
:assertion_consumer_service_url => "http://consumer.service.url/auth/saml/callback",
:issuer => "https://saml.issuer.url/issuers/29490",
:idp_sso_target_url => "https://idp.sso.target_url/signon/29490",
:idp_cert_fingerprint => "E7:91:B2:E1:4C:65:2C:49:F3:33:74:0A:58:5A:7E:55:F7:15:7A:33",
:name_identifier_format => "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
}]
end
describe 'GET /auth/saml' do
before do
get '/auth/saml'
end
it 'should get authentication page' do
last_response.should be_redirect
end
end
describe 'POST /auth/saml/callback' do
it 'should raise ArgumentError exception without the SAMLResponse parameter' do
post '/auth/saml/callback'
last_response.should be_redirect
last_response.location.should == '/auth/failure?message=invalid_ticket'
end
end
end

View file

@ -1,14 +0,0 @@
require 'simplecov'
SimpleCov.start
require 'rspec'
require 'rack/test'
require 'webmock/rspec'
require 'omniauth/core'
require 'omniauth/test'
require 'omniauth/enterprise'
RSpec.configure do |config|
config.include WebMock::API
config.include Rack::Test::Methods
config.extend OmniAuth::Test::StrategyMacros, :type => :strategy
end

View file

@ -1,2 +0,0 @@
--format=nested
--colour

View file

@ -1,90 +0,0 @@
# OmniAuth Identity
The OmniAuth Identity gem provides a way for applications to utilize a
traditional login/password based authentication system without the need
to give up the simple authentication flow provided by OmniAuth. Identity
is designed on purpose to be as featureless as possible: it provides the
basic construct for user management and then gets out of the way.
## Usage
You use `oa-identity` just like you would any other OmniAuth provider: as a
Rack middleware. The basic setup for a email/password authentication would
look something like this:
use OmniAuth::Builder do
provider :identity, :fields => [:email]
end
Next, you need to create a model (called `Identity by default`) that will be
able to persist the information provided by the user. Luckily for you, there
are pre-built models for popular ORMs that make this dead simple. You just
need to subclass the relevant class:
class Identity < OmniAuth::Identity::Models::ActiveRecord
# Add whatever you like!
end
Adapters are provided for `ActiveRecord` and `MongoMapper` and are
autoloaded on request (but not loaded by default so no dependencies are
injected).
Once you've got an Identity persistence model and the strategy up and
running, you can point users to `/auth/identity` and it will request
that they log in or give them the opportunity to sign up for an account.
Once they have authenticated with their identity, OmniAuth will call
through to `/auth/identity/callback` with the same kinds of information
it would had the user authenticated through an external provider.
Simple!
## Custom Auth Model
To use a class other than the default, specify the <tt>:model</tt> option to a
different class.
use OmniAuth::Builder do
provider :identity, :fields => [:email], :model => MyCustomClass
end
## Customizing Registration Failure
To use your own custom registration form, create a form that POSTs to
'/auth/identity/register' with 'password', 'password_confirmation', and your
other fields.
<%= form_tag '/auth/identity/register' do |f| %>
<h1>Create an Account</h1>
<%= text_field_tag :email %>
<%= password_field_tag, :password %>
<%= password_field_tag, :password_confirmation %>
<%= submit_tag %>
<% end %>
Beware not to nest your form parameters within a namespace. This strategy
looks for the form parameters at the top level of the post params. If you are
using [simple\_form](https://github.com/plataformatec/simple_form), then you
can avoid the params nesting by specifying <tt>:input_html</tt>.
<%= simple_form_for @identity, :url => '/auth/identity/register' do |f| %>
<h1>Create an Account</h1>
<%# specify :input_html to avoid params nesting %>
<%= f.input :email, :input_html => {:name => 'email'} %>
<%= f.input :password, :as => 'password', :input_html => {:name => 'password'} %>
<%= f.input :password_confirmation, :label => "Confirm Password", :as => 'password', :input_html => {:name => 'password_confirmation'} %>
<button type='submit'>Sign Up</button>
<% end %>
Next you'll need to let OmniAuth know what action to call when a registration
fails. In your OmniAuth configuration, specify any valid rack endpoint in the
<tt>:on_failed_registration</tt> option.
use OmniAuth::Builder do
provider :identity,
:fields => [:email],
:on_failed_registration => UsersController.action(:new)
end
For more information on rack endpoints, check out [this
introduction](http://library.edgecase.com/Rails/2011/01/04/rails-routing-and-rack-endpoints.html)
and
[ActionController::Metal](http://rubydoc.info/docs/rails/ActionController/Metal)

View file

@ -1,8 +0,0 @@
require 'bundler'
Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
task :default => :spec
task :test => :spec

View file

@ -1 +0,0 @@
require 'omniauth/identity'

View file

@ -1,17 +0,0 @@
require 'omniauth/core'
module OmniAuth
module Strategies
autoload :Identity, 'omniauth/strategies/identity'
end
module Identity
autoload :Model, 'omniauth/identity/model'
autoload :SecurePassword, 'omniauth/identity/secure_password'
module Models
autoload :ActiveRecord, 'omniauth/identity/models/active_record'
# autoload :MongoMapper, 'omniauth/identity/models/mongo_mapper'
# autoload :Mongoid, 'omniauth/identity/models/mongoid'
end
end
end

View file

@ -1,119 +0,0 @@
module OmniAuth
module Identity
# This module provides an includable interface for implementing the
# necessary API for OmniAuth Identity to properly locate identities
# and provide all necessary information. All methods marked as
# abstract must be implemented in the including class for things to
# work properly.
module Model
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
# Locate an identity given its unique login key.
#
# @abstract
# @param [String] key The unique login key.
# @return [Model] An instance of the identity model class.
def locate(key)
raise NotImplementedError
end
# Authenticate a user with the given key and password.
#
# @param [String] key The unique login key provided for a given identity.
# @param [String] password The presumed password for the identity.
# @return [Model] An instance of the identity model class.
def authenticate(key, password)
instance = locate(key)
return false unless instance
instance.authenticate(password)
end
# Used to set or retrieve the method that will be used to get
# and set the user-supplied authentication key.
# @return [String] The method name.
def auth_key(method = false)
@auth_key = method.to_s unless method == false
@auth_key = nil if @auth_key == ''
@auth_key || 'email'
end
end
# Returns self if the provided password is correct, false
# otherwise.
#
# @abstract
# @param [String] password The password to check.
# @return [self or false] Self if authenticated, false if not.
def authenticate(password)
raise NotImplementedError
end
SCHEMA_ATTRIBUTES = %w(name email nickname first_name last_name location description image phone)
# A hash of as much of the standard OmniAuth schema as is stored
# in this particular model. By default, this will call instance
# methods for each of the attributes it needs in turn, ignoring
# any for which `#respond_to?` is `false`.
#
# If `first_name`, `nickname`, and/or `last_name` is provided but
# `name` is not, it will be automatically calculated.
#
# @return [Hash] A string-keyed hash of user information.
def user_info
info = SCHEMA_ATTRIBUTES.inject({}) do |hash,attribute|
hash[attribute] = send(attribute) if respond_to?(attribute)
hash
end
info['name'] ||= [info['first_name'], info['last_name']].join(' ').strip if info['first_name'] || info['last_name']
info['name'] ||= info['nickname']
info
end
# An identifying string that must be globally unique to the
# application. Defaults to stringifying the `id` method.
#
# @return [String] An identifier string unique to this identity.
def uid
if respond_to?('id')
return nil if self.id.nil?
self.id.to_s
else
raise NotImplementedError
end
end
# Used to retrieve the user-supplied authentication key (e.g. a
# username or email). Determined using the class method of the same name,
# defaults to `:email`.
#
# @return [String] An identifying string that will be entered by
# users upon sign in.
def auth_key
if respond_to?(self.class.auth_key)
send(self.class.auth_key)
else
raise NotImplementedError
end
end
# Used to set the user-supplied authentication key (e.g. a
# username or email. Determined using the `.auth_key` class
# method.
#
# @param [String] value The value to which the auth key should be
# set.
def auth_key=(value)
if respond_to?(self.class.auth_key + '=')
send(self.class.auth_key + '=', value)
else
raise NotImplementedError
end
end
end
end
end

View file

@ -1,24 +0,0 @@
require 'active_record'
module OmniAuth
module Identity
module Models
class ActiveRecord < ::ActiveRecord::Base
include OmniAuth::Identity::Model
include OmniAuth::Identity::SecurePassword
self.abstract_class = true
has_secure_password
def self.auth_key=(key)
super
validates_uniqueness_of key, :case_sensitive => false
end
def self.locate(key)
where(auth_key => key).first
end
end
end
end
end

View file

@ -1,78 +0,0 @@
require 'bcrypt'
module OmniAuth
module Identity
# This is taken directly from Rails 3.1 code and is used if
# the version of ActiveModel that's being used does not
# include SecurePassword. The only difference is that instead of
# using ActiveSupport::Concern, it checks to see if there is already
# a has_secure_password method.
module SecurePassword
def self.included(base)
unless base.respond_to?(:has_secure_password)
base.extend ClassMethods
end
end
module ClassMethods
# Adds methods to set and authenticate against a BCrypt password.
# This mechanism requires you to have a password_digest attribute.
#
# Validations for presence of password, confirmation of password (using
# a "password_confirmation" attribute) are automatically added.
# You can add more validations by hand if need be.
#
# Example using Active Record (which automatically includes ActiveModel::SecurePassword):
#
# # Schema: User(name:string, password_digest:string)
# class User < ActiveRecord::Base
# has_secure_password
# end
#
# user = User.new(:name => "david", :password => "", :password_confirmation => "nomatch")
# user.save # => false, password required
# user.password = "mUc3m00RsqyRe"
# user.save # => false, confirmation doesn't match
# user.password_confirmation = "mUc3m00RsqyRe"
# user.save # => true
# user.authenticate("notright") # => false
# user.authenticate("mUc3m00RsqyRe") # => user
# User.find_by_name("david").try(:authenticate, "notright") # => nil
# User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user
def has_secure_password
attr_reader :password
validates_confirmation_of :password
validates_presence_of :password_digest
include InstanceMethodsOnActivation
if respond_to?(:attributes_protected_by_default)
def self.attributes_protected_by_default
super + ['password_digest']
end
end
end
end
module InstanceMethodsOnActivation
# Returns self if the password is correct, otherwise false.
def authenticate(unencrypted_password)
if BCrypt::Password.new(password_digest) == unencrypted_password
self
else
false
end
end
# Encrypts the password into the password_digest attribute.
def password=(unencrypted_password)
@password = unencrypted_password
unless unencrypted_password.blank?
self.password_digest = BCrypt::Password.create(unencrypted_password)
end
end
end
end
end
end

View file

@ -1,96 +0,0 @@
module OmniAuth
module Strategies
# The identity strategy allows you to provide simple internal
# user authentication using the same process flow that you
# use for external OmniAuth providers.
class Identity
include OmniAuth::Strategy
# @option options [Symbol] :name The name you want to use for this strategy.
# @option options [Symbol] :model The class you wish to use as the identity model.
# @option options [Array] :fields ([:name, :email]) Required information at identity registration.
def initialize(app, options = {})
options[:fields] ||= [:name, :email]
super(app, options[:name] || :identity, options.dup)
end
def request_phase
OmniAuth::Form.build(
:title => (options[:title] || "Identity Verification"),
:url => callback_path
) do |f|
f.text_field 'Login', 'auth_key'
f.password_field 'Password', 'password'
f.html "<p align='center'><a href='#{registration_path}'>Create an Identity</a></p>"
end.to_response
end
def callback_phase
return fail!(:invalid_credentials) unless identity
super
end
def other_phase
if on_registration_path?
if request.get?
registration_form
elsif request.post?
registration_phase
end
else
call_app!
end
end
def registration_form
OmniAuth::Form.build(:title => 'Register Identity') do |f|
options[:fields].each do |field|
f.text_field field.to_s.capitalize, field.to_s
end
f.password_field 'Password', 'password'
f.password_field 'Confirm Password', 'password_confirmation'
end.to_response
end
def registration_phase
attributes = (options[:fields] + [:password, :password_confirmation]).inject({}){|h,k| h[k] = request[k.to_s]; h}
@identity = model.create(attributes)
if @identity.persisted?
env['PATH_INFO'] = callback_path
callback_phase
else
if options[:on_failed_registration]
self.env['omniauth.identity'] = @identity
options[:on_failed_registration].call(self.env)
else
registration_form
end
end
end
def auth_hash
{
'provider' => name.to_s,
'uid' => identity.uid,
'user_info' => identity.user_info
}
end
def registration_path
options[:registration_path] || "#{path_prefix}/#{name}/register"
end
def on_registration_path?
on_path?(registration_path)
end
def identity
@identity ||= model.authenticate(request['auth_key'], request['password'])
end
def model
options[:model] || ::Identity
end
end
end
end

View file

@ -1,27 +0,0 @@
# -*- encoding: utf-8 -*-
require File.expand_path('../../lib/omniauth/version', __FILE__)
Gem::Specification.new do |gem|
gem.add_runtime_dependency 'oa-core', OmniAuth::Version::STRING
gem.add_development_dependency 'maruku', '~> 0.6'
gem.add_development_dependency 'simplecov', '~> 0.4'
gem.add_development_dependency 'rack-test', '~> 0.5'
gem.add_development_dependency 'rake', '~> 0.8'
gem.add_development_dependency 'rspec', '~> 2.5'
gem.add_development_dependency 'yard', '~> 0.6'
gem.add_development_dependency 'ZenTest', '~> 4.5'
gem.add_development_dependency 'bcrypt-ruby', '~> 2.1.4'
gem.add_development_dependency 'activerecord', '~> 3.0'
gem.name = 'oa-identity'
gem.version = OmniAuth::Version::STRING
gem.description = %q{Internal authentication handlers for OmniAuth.}
gem.summary = gem.description
gem.email = ['michael@intridea.com', 'sferik@gmail.com']
gem.homepage = 'http://github.com/intridea/omniauth'
gem.authors = ['Michael Bleigh', 'Erik Michaels-Ober']
gem.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
gem.files = `git ls-files`.split("\n")
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
gem.require_paths = ['lib']
gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if gem.respond_to? :required_rubygems_version=
end

View file

@ -1,123 +0,0 @@
require 'spec_helper'
class ExampleModel
include OmniAuth::Identity::Model
end
describe OmniAuth::Identity::Model do
context 'Class Methods' do
subject{ ExampleModel }
describe '.locate' do
it('should be abstract'){ lambda{ subject.locate('abc') }.should raise_error(NotImplementedError) }
end
describe '.authenticate' do
it 'should call locate and then authenticate' do
mocked_instance = mock('ExampleModel', :authenticate => 'abbadoo')
subject.should_receive(:locate).with('example').and_return(mocked_instance)
subject.authenticate('example','pass').should == 'abbadoo'
end
it 'should recover gracefully if locate is nil' do
subject.stub!(:locate).and_return(nil)
subject.authenticate('blah','foo').should be_false
end
end
end
context 'Instance Methods' do
subject{ ExampleModel.new }
describe '#authenticate' do
it('should be abstract'){ lambda{ subject.authenticate('abc') }.should raise_error(NotImplementedError) }
end
describe '#uid' do
it 'should default to #id' do
subject.should_receive(:respond_to?).with('id').and_return(true)
subject.stub!(:id).and_return 'wakka-do'
subject.uid.should == 'wakka-do'
end
it 'should stringify it' do
subject.stub!(:id).and_return 123
subject.uid.should == '123'
end
it 'should raise NotImplementedError if #id is not defined' do
subject.should_receive(:respond_to?).with('id').and_return(false)
lambda{ subject.uid }.should raise_error(NotImplementedError)
end
end
describe '#auth_key' do
it 'should default to #email' do
subject.should_receive(:respond_to?).with('email').and_return(true)
subject.stub!(:email).and_return('bob@bob.com')
subject.auth_key.should == 'bob@bob.com'
end
it 'should use the class .auth_key' do
subject.class.auth_key 'login'
subject.stub!(:login).and_return 'bob'
subject.auth_key.should == 'bob'
subject.class.auth_key nil
end
it 'should raise a NotImplementedError if the auth_key method is not defined' do
lambda{ subject.auth_key }.should raise_error(NotImplementedError)
end
end
describe '#auth_key=' do
it 'should default to setting email' do
subject.should_receive(:respond_to?).with('email=').and_return(true)
subject.should_receive(:email=).with 'abc'
subject.auth_key = 'abc'
end
it 'should use a custom .auth_key if one is provided' do
subject.class.auth_key 'login'
subject.should_receive(:respond_to?).with('login=').and_return(true)
subject.should_receive('login=').with('abc')
subject.auth_key = 'abc'
end
it 'should raise a NotImplementedError if the autH_key method is not defined' do
lambda{ subject.auth_key = 'broken' }.should raise_error(NotImplementedError)
end
end
describe '#user_info' do
it 'should include attributes that are set' do
subject.stub!(:name).and_return('Bob Bobson')
subject.stub!(:nickname).and_return('bob')
subject.user_info.should == {
'name' => 'Bob Bobson',
'nickname' => 'bob'
}
end
it 'should automatically set name off of first and last name' do
subject.stub!(:first_name).and_return('Bob')
subject.stub!(:last_name).and_return('Bobson')
subject.user_info['name'].should == 'Bob Bobson'
end
it 'should automatically set name off of nickname' do
subject.stub!(:nickname).and_return('bob')
subject.user_info['name'] == 'bob'
end
it 'should not overwrite a provided name' do
subject.stub!(:name).and_return('Awesome Dude')
subject.stub!(:first_name).and_return('Frank')
subject.user_info['name'].should == 'Awesome Dude'
end
end
end
end

View file

@ -1,16 +0,0 @@
require 'spec_helper'
describe(OmniAuth::Identity::Models::ActiveRecord, :db => true) do
class TestIdentity < OmniAuth::Identity::Models::ActiveRecord
auth_key :ham_sandwich
end
it 'should locate using the auth key using a where query' do
TestIdentity.should_receive(:where).with('ham_sandwich' => 'open faced').and_return(['wakka'])
TestIdentity.locate('open faced').should == 'wakka'
end
it 'should not use STI rules for its table name' do
TestIdentity.table_name.should == 'test_identities'
end
end

View file

@ -1,27 +0,0 @@
require 'spec_helper'
class HasTheMethod
def self.has_secure_password; end
end
class DoesNotHaveTheMethod
end
describe OmniAuth::Identity::SecurePassword do
it 'should extend with the class methods if it does not have the method' do
DoesNotHaveTheMethod.should_receive(:extend).with(OmniAuth::Identity::SecurePassword::ClassMethods)
DoesNotHaveTheMethod.send(:include, OmniAuth::Identity::SecurePassword)
end
it 'should not extend if the method is already defined' do
HasTheMethod.should_not_receive(:extend)
HasTheMethod.send(:include, OmniAuth::Identity::SecurePassword)
end
it 'should respond to has_secure_password afterwards' do
[HasTheMethod,DoesNotHaveTheMethod].each do |klass|
klass.send(:include, OmniAuth::Identity::SecurePassword)
klass.should be_respond_to(:has_secure_password)
end
end
end

View file

@ -1,130 +0,0 @@
require 'spec_helper'
class MockIdentity; end
describe OmniAuth::Strategies::Identity do
attr_accessor :app
let(:auth_hash){ last_response.headers['env']['omniauth.auth'] }
let(:identity_hash){ last_response.headers['env']['omniauth.identity'] }
# customize rack app for testing, if block is given, reverts to default
# rack app after testing is done
def set_app!(identity_options = {})
identity_options.reverse_merge!({:model => MockIdentity})
old_app = self.app
self.app = Rack::Builder.app do
use Rack::Session::Cookie
use OmniAuth::Strategies::Identity, identity_options
run lambda{|env| [404, {'env' => env}, ["HELLO!"]]}
end
if block_given?
yield
self.app = old_app
end
self.app
end
before(:all) do
set_app!
end
describe '#request_phase' do
it 'should display a form' do
get '/auth/identity'
last_response.body.should be_include("<form")
end
end
describe '#callback_phase' do
let(:user){ mock(:uid => 'user1', :user_info => {'name' => 'Rockefeller'})}
context 'with valid credentials' do
before do
MockIdentity.should_receive('authenticate').with('john','awesome').and_return(user)
post '/auth/identity/callback', :auth_key => 'john', :password => 'awesome'
end
it 'should populate the auth hash' do
auth_hash.should be_kind_of(Hash)
end
it 'should populate the uid' do
auth_hash['uid'].should == 'user1'
end
it 'should populate the user_info hash' do
auth_hash['user_info'].should == {'name' => 'Rockefeller'}
end
end
context 'with invalid credentials' do
before do
OmniAuth.config.on_failure = lambda{|env| [401, {}, [env['omniauth.error.type'].inspect]]}
MockIdentity.should_receive(:authenticate).with('wrong','login').and_return(false)
post '/auth/identity/callback', :auth_key => 'wrong', :password => 'login'
end
it 'should fail with :invalid_credentials' do
last_response.body.should == ':invalid_credentials'
end
end
end
describe '#registration_form' do
it 'should trigger from /auth/identity/register by default' do
get '/auth/identity/register'
last_response.body.should be_include("Register Identity")
end
end
describe '#registration_phase' do
context 'with successful creation' do
let(:properties){ {
:name => 'Awesome Dude',
:email => 'awesome@example.com',
:password => 'face',
:password_confirmation => 'face'
} }
before do
m = mock(:uid => 'abc', :name => 'Awesome Dude', :email => 'awesome@example.com', :user_info => {:name => 'DUUUUDE!'}, :persisted? => true)
MockIdentity.should_receive(:create).with(properties).and_return(m)
end
it 'should set the auth hash' do
post '/auth/identity/register', properties
auth_hash['uid'].should == 'abc'
end
end
context 'with invalid identity' do
let(:properties) { {
:name => 'Awesome Dude',
:email => 'awesome@example.com',
:password => 'NOT',
:password_confirmation => 'MATCHING'
} }
before do
MockIdentity.should_receive(:create).with(properties).and_return(mock(:persisted? => false))
end
context 'default' do
it 'should show registration form' do
post '/auth/identity/register', properties
last_response.body.should be_include("Register Identity")
end
end
context 'custom on_failed_registration endpoint' do
it 'should set the identity hash' do
set_app!(:on_failed_registration => lambda{|env| [404, {'env' => env}, ["HELLO!"]]}) do
post '/auth/identity/register', properties
identity_hash.should_not be_nil
end
end
end
end
end
end

View file

@ -1,14 +0,0 @@
require 'rubygems'
require 'bundler'
Bundler.setup :default, :development, :test
require 'simplecov'
SimpleCov.start
require 'rack/test'
require 'omniauth/identity'
RSpec.configure do |config|
config.include Rack::Test::Methods
end

View file

View file

@ -1,3 +0,0 @@
--color
--format=nested
--backtrace

View file

@ -1,4 +0,0 @@
--markup markdown
--markup-provider maruku
-
LICENSE

View file

@ -1,11 +0,0 @@
require File.expand_path('../lib/omniauth/version', __FILE__)
source 'http://rubygems.org'
gem 'oa-core', OmniAuth::Version::STRING, :path => '../oa-core'
platforms :jruby do
gem 'jruby-openssl', '~> 0.7'
end
gemspec

View file

@ -1,19 +0,0 @@
Copyright (c) 2010-2011 Michael Bleigh and Intridea, Inc.
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.

View file

@ -1,22 +0,0 @@
= OmniAuth::More
OmniAuth stratgies for authentication providers that do not
fit into one of the other authentication gems.
== Installation
To install omniauth as a suite of gems:
gem install omniauth
To install just the providers in the "more" gem:
gem install oa-more
== OmniAuth Builder
If you want to allow multiple providers, use the OmniAuth Builder:
use OmniAuth::Builder do
provider :flickr, 'api_key', 'secret_key', :scope => 'read'
end

View file

@ -1,6 +0,0 @@
require 'bundler'
Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
task :default => :spec
task :test => :spec

View file

@ -1 +0,0 @@
require 'omniauth/more'

View file

@ -1,12 +0,0 @@
require 'omniauth/core'
module OmniAuth
module Strategies
autoload :Draugiem, 'omniauth/strategies/draugiem'
autoload :Flickr, 'omniauth/strategies/flickr'
autoload :HttpBasic, 'omniauth/strategies/http_basic'
autoload :Ign, 'omniauth/strategies/ign'
autoload :LastFm, 'omniauth/strategies/last_fm'
autoload :WindowsLive, 'omniauth/strategies/windows_live'
end
end

View file

@ -1,104 +0,0 @@
require 'omniauth/core'
require 'digest/md5'
require 'rest-client'
require 'multi_json'
module OmniAuth
module Strategies
#
# Authenticate to draugiem.lv and frype.com and others.
#
# @example Basic Rails Usage
#
# Add this to config/initializers/omniauth.rb
#
# Rails.application.config.middleware.use OmniAuth::Builder do
# provider :draugiem, 'App id', 'API Key'
# end
#
# @example Basic Rack example
#
# use Rack::Session::Cookie
# use OmniAuth::Strategies::Draugiem, 'App id', 'API Key'
#
class Draugiem
include OmniAuth::Strategy
attr_accessor :app_id, :api_key
def initialize(app, app_id, api_key)
super(app, :draugiem)
@app_id = app_id
@api_key = api_key
end
protected
def request_phase
params = {
:app => @app_id,
:redirect => callback_url,
:hash => Digest::MD5.hexdigest("#{@api_key}#{callback_url}")
}
query_string = params.collect{ |key,value| "#{key}=#{Rack::Utils.escape(value)}" }.join('&')
redirect "http://api.draugiem.lv/authorize/?#{query_string}"
end
def callback_phase
if request.params['dr_auth_status'] == 'ok' && request.params['dr_auth_code']
response = RestClient.get('http://api.draugiem.lv/json/', { :params => draugiem_authorize_params(request.params['dr_auth_code']) })
auth = MultiJson.decode(response.to_s)
unless auth['error']
@auth_data = auth
super
else
fail!(auth['error']['code'].to_s,auth["error"]["description"].to_s)
end
else
fail!(:invalid_request)
end
rescue Exception => e
fail!(:invalid_response, e)
end
def auth_hash
OmniAuth::Utils.deep_merge(super, {
'uid' => @auth_data['uid'],
'user_info' => get_user_info,
'credentials' => {
'apikey' => @auth_data['apikey']
},
'extra' => { 'user_hash' => @auth_data }
})
end
private
def get_user_info
if @auth_data['users'] && @auth_data['users'][@auth_data['uid']]
user = @auth_data['users'][@auth_data['uid']]
{
'name' => "#{user['name']} #{user['surname']}",
'nickname' => user['nick'],
'first_name' => user['name'],
'last_name' => user['surname'],
'location' => user['place'],
'age' => user['age'] =~ /^0-9$/ ? user['age'] : nil,
'adult' => user['adult'] == '1' ? true : false,
'image' => user['img'],
'sex' => user['sex']
}
else
{}
end
end
def draugiem_authorize_params code
{
:action => 'authorize',
:app => @api_key,
:code => code
}
end
end
end
end

View file

@ -1,56 +0,0 @@
require 'rest-client'
require 'omniauth/more'
module OmniAuth
module Strategies
class HttpBasic
include OmniAuth::Strategy
def initialize(app, name, endpoint = nil, headers = {}, &block)
super
@endpoint = endpoint
@request_headers = headers
end
attr_reader :endpoint, :request_headers
def request_phase
if env['REQUEST_METHOD'] == 'GET'
get_credentials
else
perform
end
end
def title
name.split('_').map{|s| s.capitalize}.join(' ')
end
def get_credentials
OmniAuth::Form.build(:title => title) do
text_field 'Username', 'username'
password_field 'Password', 'password'
end.to_response
end
def perform
@response = perform_authentication(endpoint)
@env['omniauth.auth'] = auth_hash
@env['REQUEST_METHOD'] = 'GET'
@env['PATH_INFO'] = "#{OmniAuth.config.path_prefix}/#{name}/callback"
call_app!
rescue RestClient::Request::Unauthorized => e
fail!(:invalid_credentials, e)
end
def perform_authentication(uri, headers = request_headers)
RestClient.get(uri, headers)
end
def callback_phase
fail!(:invalid_credentials)
end
end
end
end

View file

@ -1,93 +0,0 @@
require 'omniauth/core'
require 'openssl'
module OmniAuth
module Strategies
class Ign
include OmniAuth::Strategy
IDENTIFIER_URL_PARAMETER = ""
class CallbackError < StandardError
attr_accessor :error, :error_reason
def initialize(error, error_reason)
self.error = error
self.error_reason = error_reason
end
end
def initialize(app, api_key, hostname=nil, options = {})
options[:name] ||= "ign"
super(app, :ign)
@api_key = api_key
@hostname = hostname
end
protected
def request_phase
OmniAuth::Form.build(:title => 'IGN Authentication', :header_info=>js) do
label_field('Identifying you with the IGN server', IDENTIFIER_URL_PARAMETER)
end.to_response
end
def callback_phase
signature = OpenSSL::HMAC.hexdigest('sha1', @api_key, ("#{request.params["username"]}::#{request.params["timestamp"]}"))
raise CallbackError.new("Invalid Signature","The supplied and calculated signature did not match, user not approved.") if signature != request.params["signature"]
super
rescue CallbackError => e
fail!(:invalid_response, e)
end
def auth_hash
OmniAuth::Utils.deep_merge(super, {
'uid' => "ign-" + request.params["username"],
'credentials' => { 'token' => request.params["signature"] },
'user_info' => user_info,
'extra' => { 'user_hash' => request.params }
})
end
def user_info
{
'nickname' => request.params["username"],
}
end
def js
@js = <<-JS
$(document).ready(function() {
$.ajax({
url: "http://#{@hostname}/users/current.json?callback=z33k",
type: "get",
dataType:"jsonp",
success: function(data) {
if(typeof data.error == 'undefined'){
// There is a current My IGN user
var username = data.my_ign_username;
var signature = data.signature;
var timestamp = data.timestamp;
window.location = "/auth/ign/callback?username=" +username+"&signature="+signature+"&timestamp=" + timestamp;
}
else{
nouser();
}
}
});
return false;
});
function nouser() {
var url = "http://my.ign.com/login?r="+window.location;
top.location = url;
window.location = url;
}
JS
"\n<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js' type='text/javascript'></script>" +
"\n<script type='text/javascript'>#{@js}</script>" +
"\n<style type='text/css'>button {visibility:hidden;}</style>"
end
end
end
end

View file

@ -1,93 +0,0 @@
require 'omniauth/core'
require 'digest/md5'
require 'rest-client'
require 'multi_json'
module OmniAuth
module Strategies
#
# Authenticate to LastFM
#
# @example Basic Usage
#
# use OmniAuth::Strategies::LastFm, 'API Key', 'Secret Key'
class LastFm
include OmniAuth::Strategy
attr_accessor :api_key, :secret_key, :options
# error catching, based on OAuth2 callback
class CallbackError < StandardError
attr_accessor :error, :error_reason
def initialize(error, error_reason)
self.error = error
self.error_reason = error_reason
end
end
# @param [Rack Application] app standard middleware application parameter
# @param [String] api_key the application id as [registered on LastFM](http://www.last.fm/api/account)
# @param [String] secret_key the application secret as [registered on LastFM](http://www.last.fm/api/account)
# @option options, You can optionally specify a callback URL that is different to your API Account callback url. Include this as a query param cb
def initialize(app, api_key, secret_key, options = {})
super(app, :last_fm)
@api_key = api_key
@secret_key = secret_key
@options = options
end
protected
def request_phase
params = { :api_key => api_key, :cb => options[:cb] }
query_string = params.collect{ |key,value| "#{key}=#{Rack::Utils.escape(value)}" }.join('&')
redirect "http://www.last.fm/api/auth/?#{query_string}"
end
def callback_phase
token = request.params['token']
params = { :api_key => api_key, :method => 'auth.getSession', :format => 'json' }
params[:token] = token
params[:api_sig] = signature(token)
response = RestClient.get('http://ws.audioscrobbler.com/2.0/', { :params => params })
@auth = MultiJson.decode(response.to_s)
raise CallbackError.new(@auth['error'],@auth['message']) if @auth['error']
user_params = { :method => "user.getInfo", :user => @auth['session']['name'], :api_key => api_key, :format => "json" }
user_response = RestClient.get('http://ws.audioscrobbler.com/2.0/', { :params => user_params })
@user_auth = MultiJson.decode(user_response.to_s)
raise CallbackError.new(@user_auth['error'],@user_auth['message']) if @user_auth['error']
super
rescue CallbackError => e
fail!(:invalid_response, e)
end
def auth_hash
OmniAuth::Utils.deep_merge(super, {
'uid' => @user_auth['user']['id'],
'credentials' => { 'token' => @auth['session']['key'] },
'user_info' => user_info,
'extra' => { 'user_hash' => @user_auth }
})
end
def user_info
{
'name' => @user_auth['user']['realname'],
'nickname' => @user_auth['user']['name'],
'location' => @user_auth['user']['country'],
'image' => @user_auth['user']['image'],
'urls' => {
'Profile' => @user_auth['user']['url']
}
}
end
def signature(token)
sign = "api_key#{api_key}methodauth.getSessiontoken#{token}#{secret_key}"
Digest::MD5.hexdigest(sign)
end
end
end
end

View file

@ -1,39 +0,0 @@
require 'omniauth/core'
require 'omniauth/strategies/windows_live/windowslivelogin'
module OmniAuth
module Strategies
class WindowsLive
include OmniAuth::Strategy
attr_accessor :app_id, :app_secret
# Initialize the strategy by providing
#
# @param app_id [String] The application ID from your registered app with Microsoft.
# @param app_secret [String] The secret from your registered app with Microsoft.
# @option options [String] :locale A localization string for the login, should be in the form `en-us` or similar.
# @option options [String] :state Some state information that is serialized into the query string upon callback.
# @option options [Boolean] :ssl Whether or not to use SSL for login. Defaults to `true`.
# @option options [Boolean] :force_nonprovisioned When true, forces a non-provisioned (i.e. no app id or secret) mode.
def initialize(app, app_id = nil, app_secret = nil, options = {})
self.app_id = app_id
self.app_secret = app_secret
super(app, :windows_live, app_id, app_secret, options)
options[:ssl] ||= true
options[:locale] ||= 'en-us'
options[:force_nonprovisioned] = true unless app_id
end
protected
def consumer
WindowsLiveLogin.new app_id, app_secret, options[:security_algorithm], options[:force_nonprovisioned], options[:policy_url], callback_url
end
def request_phase
redirect consumer.getLoginUrl(options[:state], options[:locale])
end
end
end
end

View file

@ -1,67 +0,0 @@
require 'omniauth/core'
require 'digest/md5'
require 'rest-client'
require 'multi_json'
module OmniAuth
module Strategies
class Yupoo
include OmniAuth::Strategy
attr_accessor :api_key, :secret_key, :options
class CallbackError < StandardError
attr_accessor :error, :error_reason
def initialize(error, error_reason)
self.error = error
self.error_reason = error_reason
end
end
def initialize(app, api_key, secret_key, options = {})
super(app, :yupoo)
@api_key = api_key
@secret_key = secret_key
@options = {:scope => 'read'}.merge(options)
end
protected
def request_phase
params = { :api_key => api_key, :perms => options[:scope] }
params[:api_sig] = yupoo_sign(params)
query_string = params.collect{ |key,value| "#{key}=#{Rack::Utils.escape(value)}" }.join('&')
redirect "http://www.yupoo.com/services/auth/?#{query_string}"
end
def callback_phase
params = { :api_key => api_key, :method => 'yupoo.auth.getToken', :frob => request.params['frob'], :format => 'json', :nojsoncallback => '1' }
params[:api_sig] = yupoo_sign(params)
response = RestClient.get('http://www.yupoo.com/api/rest/', { :params => params })
auth = MultiJson.decode(response.to_s)
raise CallbackError.new(auth['code'],auth['message']) if auth['stat'] == 'fail'
@user = auth['auth']['user']
@access_token = auth['auth']['token']['_content']
super
rescue CallbackError => e
fail!(:invalid_response, e)
end
def auth_hash
OmniAuth::Utils.deep_merge(super, {
'uid' => @user['nsid'],
'credentials' => { 'token' => @access_token },
'user_info' => @user,
'extra' => { 'user_hash' => @user }
})
end
def yupoo_sign(params)
Digest::MD5.hexdigest(secret_key + params.sort{|a,b| a[0].to_s <=> b[0].to_s }.flatten.join)
end
end
end
end

View file

@ -1,19 +0,0 @@
module OmniAuth
module Version
unless defined?(::OmniAuth::Version::MAJOR)
MAJOR = 0
end
unless defined?(::OmniAuth::Version::MINOR)
MINOR = 3
end
unless defined?(::OmniAuth::Version::PATCH)
PATCH = 0
end
unless defined?(::OmniAuth::Version::PRE)
PRE = "rc3"
end
unless defined?(::OmniAuth::Version::STRING)
STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
end
end
end

View file

@ -1,27 +0,0 @@
# encoding: utf-8
require File.expand_path('../lib/omniauth/version', __FILE__)
Gem::Specification.new do |gem|
gem.add_dependency 'multi_json', '~> 1.0.0'
gem.add_dependency 'oa-core', OmniAuth::Version::STRING
gem.add_dependency 'rest-client', '~> 1.6.0'
gem.add_development_dependency 'json_pure', '~> 1.5'
gem.add_development_dependency 'rack-test', '~> 0.5'
gem.add_development_dependency 'rake', '~> 0.8'
gem.add_development_dependency 'rdiscount', '~> 1.6'
gem.add_development_dependency 'rspec', '~> 2.5'
gem.add_development_dependency 'simplecov', '~> 0.4'
gem.add_development_dependency 'webmock', '~> 1.7'
gem.add_development_dependency 'yard', '~> 0.7'
gem.authors = ['Michael Bleigh', 'Erik Michaels-Ober']
gem.description = %q{Additional strategies for OmniAuth.}
gem.email = 'michael@intridea.com'
gem.files = `git ls-files`.split("\n")
gem.homepage = 'http://github.com/intridea/omniauth'
gem.name = 'oa-more'
gem.require_paths = ['lib']
gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if gem.respond_to? :required_rubygems_version=
gem.summary = gem.description
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
gem.version = OmniAuth::Version::STRING
end

View file

@ -1,51 +0,0 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe 'OmniAuth::Strategies::Draugiem', :type => :strategy do
include OmniAuth::Test::StrategyTestCase
def strategy
[OmniAuth::Strategies::Draugiem, '123', "abc"]
end
it 'should initialize with api key and app id' do
lambda{OmniAuth::Strategies::Draugiem.new({},'123','abc')}.should_not raise_error
end
describe '/auth/draugiem' do
it 'should redirect to api.draugiem.lv' do
get '/auth/draugiem'
last_response.should be_redirect
last_response.headers['Location'].should match %r{http://api\.draugiem\.lv/authorize/}
end
it 'should gather user data after success authorization' do
stub_request(:get, "http://api.draugiem.lv/json/?action=authorize&app=abc&code=123456").
to_return(:body => MultiJson.encode({
'apikey'=>"123456789",
'uid'=>"100",
'language'=>"lv",
'users'=>{
'100'=>{
'uid'=>"100",
'name'=>"John",
'surname'=>"Lenon",
'nick'=>"johnybravo",
'place'=>"Durbe",
'age'=>"false",
'adult'=>"1",
'img'=>"http://4.bp.blogspot.com/_ZmXOoYjxXog/Sg2jby1RFSI/AAAAAAAAE_Q/1LpfjimAz50/s400/JohnnyBravo3.gif",
'sex'=>"M"
}
}
}))
get '/auth/draugiem/callback?dr_auth_status=ok&dr_auth_code=123456'
last_request.env['omniauth.auth']['credentials']['apikey'].should == "123456789"
last_request.env['omniauth.auth']['user_info']['location'].should == "Durbe"
last_request.env['omniauth.auth']['user_info']['age'].should be_nil
last_request.env['omniauth.auth']['user_info']['adult'].should be_true
end
end
end

View file

@ -1,7 +0,0 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe OmniAuth::Strategies::HttpBasic do
it 'should exist' do
# do nothing
end
end

View file

@ -1,7 +0,0 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe 'OmniAuth::Strategies::LastFm' do
it 'should initialize with a consumer key and secret' do
lambda{OmniAuth::Strategies::LastFm.new({},'abc','def')}.should_not raise_error
end
end

View file

@ -1,11 +0,0 @@
require 'simplecov'
SimpleCov.start
require 'rspec'
require 'rack/test'
require 'webmock/rspec'
require 'omniauth/more'
RSpec.configure do |config|
config.include Rack::Test::Methods
config.include WebMock::API
end

View file

View file

@ -1,3 +0,0 @@
--color
--format=nested
--backtrace

View file

@ -1,4 +0,0 @@
--markup markdown
--markup-provider maruku
-
LICENSE

View file

@ -1,11 +0,0 @@
require File.expand_path('../lib/omniauth/version', __FILE__)
source 'http://rubygems.org'
gem 'oa-core', OmniAuth::Version::STRING, :path => '../oa-core'
platforms :jruby do
gem 'jruby-openssl', '~> 0.7'
end
gemspec

View file

@ -1,19 +0,0 @@
Copyright (c) 2010-2011 Michael Bleigh and Intridea, Inc.
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.

Some files were not shown because too many files have changed in this diff Show more