mirror of
https://github.com/omniauth/omniauth.git
synced 2022-11-09 12:31:49 -05:00
Cleanup EOL whitespace
This commit is contained in:
parent
b3bcdda9ab
commit
5029992fcf
28 changed files with 523 additions and 528 deletions
|
@ -5,15 +5,15 @@ 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
|
||||
|
@ -21,33 +21,33 @@ module OmniAuth
|
|||
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
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
require 'omniauth/core'
|
||||
|
||||
module OmniAuth
|
||||
class Builder < ::Rack::Builder
|
||||
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)
|
||||
|
|
|
@ -73,7 +73,7 @@ module OmniAuth
|
|||
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
|
||||
|
|
|
@ -7,7 +7,7 @@ module OmniAuth
|
|||
background: #ccc;
|
||||
font-family: "Lucida Grande", "Lucida Sans", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin: 30px auto 0px;
|
||||
|
@ -25,12 +25,12 @@ module OmniAuth
|
|||
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;
|
||||
|
@ -45,13 +45,13 @@ module OmniAuth
|
|||
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;
|
||||
|
@ -59,13 +59,13 @@ module OmniAuth
|
|||
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;
|
||||
|
@ -85,7 +85,7 @@ module OmniAuth
|
|||
font-size: 16px;
|
||||
}
|
||||
CSS
|
||||
|
||||
|
||||
attr_accessor :options
|
||||
|
||||
def initialize(options = {})
|
||||
|
@ -95,28 +95,28 @@ module OmniAuth
|
|||
@html = ""
|
||||
header(options[:title])
|
||||
end
|
||||
|
||||
|
||||
def self.build(title=nil, &block)
|
||||
form = OmniAuth::Form.new(title)
|
||||
form.instance_eval(&block)
|
||||
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)
|
||||
|
@ -126,7 +126,7 @@ module OmniAuth
|
|||
def button(text)
|
||||
@html << "\n<button type='submit'>#{text}</button>"
|
||||
end
|
||||
|
||||
|
||||
def html(html)
|
||||
@html << html
|
||||
end
|
||||
|
@ -137,7 +137,7 @@ module OmniAuth
|
|||
@html << "\n</fieldset>"
|
||||
self
|
||||
end
|
||||
|
||||
|
||||
def header(title)
|
||||
@html << <<-HTML
|
||||
<!DOCTYPE html>
|
||||
|
@ -152,7 +152,7 @@ module OmniAuth
|
|||
HTML
|
||||
self
|
||||
end
|
||||
|
||||
|
||||
def footer
|
||||
return self if @footer
|
||||
@html << <<-HTML
|
||||
|
@ -164,19 +164,19 @@ module OmniAuth
|
|||
@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
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
require 'omniauth/core'
|
||||
|
||||
module OmniAuth
|
||||
class NoSessionError < StandardError; end
|
||||
module Strategy
|
||||
class NoSessionError < StandardError; end
|
||||
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
|
||||
|
@ -30,24 +30,24 @@ module OmniAuth
|
|||
raise OmniAuth::NoSessionError.new("You must provide a session to use OmniAuth.") unless env['rack.session']
|
||||
|
||||
@env = env
|
||||
@env['omniauth.strategy'] = self
|
||||
|
||||
@env['omniauth.strategy'] = self
|
||||
|
||||
return mock_call!(env) if OmniAuth.config.test_mode
|
||||
|
||||
|
||||
if current_path == request_path && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
|
||||
setup_phase
|
||||
setup_phase
|
||||
if response = call_through_to_app
|
||||
response
|
||||
else
|
||||
if request.params['origin']
|
||||
@env['rack.session']['omniauth.origin'] = 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
|
||||
elsif current_path == callback_path
|
||||
setup_phase
|
||||
setup_phase
|
||||
@env['omniauth.origin'] = session.delete('omniauth.origin')
|
||||
@env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
|
||||
|
||||
|
@ -62,7 +62,7 @@ module OmniAuth
|
|||
end
|
||||
|
||||
def mock_call!(env)
|
||||
if current_path == request_path
|
||||
if current_path == request_path
|
||||
setup_phase
|
||||
if response = call_through_to_app
|
||||
response
|
||||
|
@ -89,10 +89,10 @@ module OmniAuth
|
|||
call_app!
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def setup_phase
|
||||
if options[:setup].respond_to?(:call)
|
||||
options[:setup].call(env)
|
||||
options[:setup].call(env)
|
||||
elsif options[:setup]
|
||||
setup_env = env.merge('PATH_INFO' => setup_path, 'REQUEST_METHOD' => 'GET')
|
||||
call_app!(setup_env)
|
||||
|
@ -102,20 +102,20 @@ module OmniAuth
|
|||
def request_phase
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
|
||||
def callback_phase
|
||||
@env['omniauth.auth'] = auth_hash
|
||||
call_app!
|
||||
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
|
||||
|
@ -131,25 +131,25 @@ module OmniAuth
|
|||
def query_string
|
||||
request.query_string.empty? ? "" : "?#{request.query_string}"
|
||||
end
|
||||
|
||||
|
||||
def call_through_to_app
|
||||
status, headers, body = *call_app!
|
||||
@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
|
||||
{
|
||||
'provider' => name.to_s,
|
||||
'uid' => nil
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def full_host
|
||||
case OmniAuth.config.full_host
|
||||
when String
|
||||
|
@ -179,7 +179,7 @@ module OmniAuth
|
|||
def request
|
||||
@request ||= Rack::Request.new(@env)
|
||||
end
|
||||
|
||||
|
||||
def redirect(uri)
|
||||
r = Rack::Response.new
|
||||
|
||||
|
@ -189,12 +189,12 @@ module OmniAuth
|
|||
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
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
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
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
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
|
||||
|
|
|
@ -2,9 +2,9 @@ require 'rack'
|
|||
require 'omniauth/test'
|
||||
|
||||
module OmniAuth
|
||||
|
||||
|
||||
module Test
|
||||
|
||||
|
||||
# Support for testing OmniAuth strategies.
|
||||
#
|
||||
# @example Usage
|
||||
|
@ -19,7 +19,7 @@ module OmniAuth
|
|||
# end
|
||||
# end
|
||||
module StrategyTestCase
|
||||
|
||||
|
||||
def app
|
||||
strat = self.strategy
|
||||
resp = self.app_response
|
||||
|
@ -29,7 +29,7 @@ module OmniAuth
|
|||
run lambda {|env| [404, {'Content-Type' => 'text/plain'}, [resp || env.key?('omniauth.auth').to_s]] }
|
||||
}.to_app
|
||||
end
|
||||
|
||||
|
||||
def app_response
|
||||
nil
|
||||
end
|
||||
|
@ -37,13 +37,13 @@ module OmniAuth
|
|||
def session
|
||||
last_request.env['rack.session']
|
||||
end
|
||||
|
||||
|
||||
def strategy
|
||||
raise NotImplementedError.new('Including specs must define #strategy')
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -9,45 +9,45 @@ describe OmniAuth do
|
|||
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
|
||||
|
@ -56,7 +56,7 @@ describe OmniAuth do
|
|||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe '.camelize' do
|
||||
it 'should work on normal cases' do
|
||||
{
|
||||
|
@ -66,7 +66,7 @@ describe OmniAuth do
|
|||
'three_words_now' => 'ThreeWordsNow'
|
||||
}.each_pair{ |k,v| OmniAuth::Utils.camelize(k).should == v }
|
||||
end
|
||||
|
||||
|
||||
it 'should work in special cases' do
|
||||
{
|
||||
'oauth' => "OAuth",
|
||||
|
|
|
@ -6,14 +6,14 @@ class ExampleStrategy
|
|||
attr_reader :last_env
|
||||
def request_phase
|
||||
@fail = fail!(options[:failure]) if options[:failure]
|
||||
@last_env = env
|
||||
return @fail if @fail
|
||||
@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
|
||||
return @fail if @fail
|
||||
raise "Callback Phase"
|
||||
end
|
||||
end
|
||||
|
@ -34,7 +34,7 @@ describe OmniAuth::Strategy 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
|
||||
|
@ -48,10 +48,10 @@ describe OmniAuth::Strategy do
|
|||
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")
|
||||
|
@ -98,13 +98,13 @@ describe OmniAuth::Strategy do
|
|||
it 'should use the default request path' do
|
||||
lambda{ strategy.call(make_env) }.should raise_error("Request 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")
|
||||
lambda{ strategy.call(make_env('/auth/test/')) }.should raise_error("Request Phase")
|
||||
end
|
||||
|
||||
it 'should strip trailing spaces on callback' do
|
||||
|
@ -137,11 +137,11 @@ describe OmniAuth::Strategy do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'pre-request call through' do
|
||||
|
||||
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
|
||||
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')
|
||||
|
@ -152,13 +152,13 @@ describe OmniAuth::Strategy do
|
|||
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")
|
||||
|
@ -184,16 +184,16 @@ describe OmniAuth::Strategy do
|
|||
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
|
||||
|
@ -216,22 +216,22 @@ describe OmniAuth::Strategy do
|
|||
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]
|
||||
OmniAuth.config.allowed_request_methods = [:get, :post]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -270,12 +270,12 @@ describe OmniAuth::Strategy do
|
|||
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'
|
||||
|
@ -283,7 +283,7 @@ describe OmniAuth::Strategy do
|
|||
|
||||
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
|
||||
|
@ -305,7 +305,7 @@ describe OmniAuth::Strategy do
|
|||
|
||||
context 'setup phase' do
|
||||
context 'when options[:setup] = true' do
|
||||
let(:strategy){ ExampleStrategy.new(app, 'test', :setup => true) }
|
||||
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
|
||||
|
@ -327,7 +327,7 @@ describe OmniAuth::Strategy do
|
|||
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'
|
||||
|
@ -335,7 +335,7 @@ describe OmniAuth::Strategy do
|
|||
|
||||
it 'should call the rack app' do
|
||||
strategy.call(make_env('/auth/test'))
|
||||
strategy.options[:awesome].should == 'sauce'
|
||||
strategy.options[:awesome].should == 'sauce'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,19 +4,19 @@ 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),
|
||||
|
@ -34,7 +34,7 @@ module OmniAuth
|
|||
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'),
|
||||
|
|
|
@ -4,7 +4,7 @@ module OmniAuth
|
|||
module Strategies
|
||||
class CAS
|
||||
class Configuration
|
||||
|
||||
|
||||
DEFAULT_LOGIN_URL = "%s/login"
|
||||
|
||||
DEFAULT_SERVICE_VALIDATE_URL = "%s/serviceValidate"
|
||||
|
@ -27,7 +27,7 @@ module OmniAuth
|
|||
# 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
|
||||
|
@ -91,7 +91,7 @@ module OmniAuth
|
|||
result << 'service='
|
||||
result << Rack::Utils.escape(service)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ require 'nokogiri'
|
|||
module OmniAuth
|
||||
module Strategies
|
||||
class CAS
|
||||
class ServiceTicketValidator
|
||||
class ServiceTicketValidator
|
||||
|
||||
VALIDATION_REQUEST_HEADERS = { 'Accept' => '*/*' }
|
||||
|
||||
|
@ -47,7 +47,7 @@ module OmniAuth
|
|||
hash
|
||||
end
|
||||
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.
|
||||
|
@ -64,7 +64,7 @@ module OmniAuth
|
|||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# retrieves the `<cas:serviceResponse>` XML from the CAS server
|
||||
def get_service_response_body
|
||||
result = ''
|
||||
|
@ -77,7 +77,7 @@ module OmniAuth
|
|||
end
|
||||
result
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,9 +7,9 @@ module OmniAuth
|
|||
module Strategies
|
||||
class LDAP
|
||||
include OmniAuth::Strategy
|
||||
|
||||
|
||||
autoload :Adaptor, 'omniauth/strategies/ldap/adaptor'
|
||||
@@config = {'name' => 'cn',
|
||||
@@config = {'name' => 'cn',
|
||||
'first_name' => 'givenName',
|
||||
'last_name' => 'sn',
|
||||
'email' => ['mail', "email", 'userPrincipalName'],
|
||||
|
@ -32,9 +32,9 @@ module OmniAuth
|
|||
@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
|
||||
|
@ -51,15 +51,15 @@ module OmniAuth
|
|||
end.to_response
|
||||
end
|
||||
|
||||
def callback_phase
|
||||
def callback_phase
|
||||
begin
|
||||
creds = session.delete 'omniauth.ldap'
|
||||
@ldap_user_info = {}
|
||||
begin
|
||||
(@adaptor.bind(:allow_anonymous => true) unless @adaptor.bound?)
|
||||
rescue Exception => e
|
||||
begin
|
||||
(@adaptor.bind(:allow_anonymous => true) unless @adaptor.bound?)
|
||||
rescue Exception => e
|
||||
puts "failed to bind with the default credentials: " + e.message
|
||||
end
|
||||
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]
|
||||
|
@ -68,13 +68,13 @@ module OmniAuth
|
|||
@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
|
||||
|
||||
end
|
||||
|
||||
def auth_hash
|
||||
OmniAuth::Utils.deep_merge(super, {
|
||||
'uid' => @user_info["uid"],
|
||||
|
@ -82,7 +82,7 @@ module OmniAuth
|
|||
'extra' => @ldap_user_info
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
def self.map_user(mapper, object)
|
||||
user = {}
|
||||
mapper.each do |key, value|
|
||||
|
@ -97,14 +97,14 @@ module OmniAuth
|
|||
value1.each_with_index do |v,i|
|
||||
part = '';
|
||||
v.each {|v1| (part = object[v1.downcase.to_sym].to_s; break;) if object[v1.downcase.to_sym]}
|
||||
pattern.gsub!("%#{i}",part||'')
|
||||
end
|
||||
pattern.gsub!("%#{i}",part||'')
|
||||
end
|
||||
user[key] = pattern
|
||||
end
|
||||
end
|
||||
end
|
||||
user
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,58 +9,57 @@ module OmniAuth
|
|||
module Strategies
|
||||
class LDAP
|
||||
class Adaptor
|
||||
class LdapError < StandardError; end
|
||||
class ConfigurationError < StandardError; end
|
||||
class AuthenticationError < StandardError; end
|
||||
class ConnectionError < StandardError; end
|
||||
|
||||
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?
|
||||
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
|
||||
|
||||
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
|
||||
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,
|
||||
:eport => 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
|
||||
|
@ -69,78 +68,74 @@ module OmniAuth
|
|||
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]
|
||||
filter = options[:filter]
|
||||
limit = options[:limit]
|
||||
|
||||
args = {
|
||||
:base => @base,
|
||||
:filter => filter,
|
||||
:size => limit
|
||||
}
|
||||
|
||||
puts args.inspect
|
||||
|
||||
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]
|
||||
filter = options[:filter]
|
||||
limit = options[:limit]
|
||||
|
||||
args = {
|
||||
:base => @base,
|
||||
:filter => filter,
|
||||
:size => limit
|
||||
}
|
||||
|
||||
attributes = {}
|
||||
execute(:search, args) do |entry|
|
||||
|
@ -151,11 +146,11 @@ module OmniAuth
|
|||
attributes
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
private
|
||||
|
||||
def execute(method, *args, &block)
|
||||
result = @connection.send(method, *args, &block)
|
||||
message = nil
|
||||
result = @connection.send(method, *args, &block)
|
||||
message = nil
|
||||
|
||||
if result.is_a?(Hash)
|
||||
message = result[:errorMessage]
|
||||
|
@ -166,117 +161,117 @@ module OmniAuth
|
|||
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,
|
||||
}
|
||||
puts info.inspect
|
||||
|
||||
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)
|
||||
puts options.inspect
|
||||
user,psw = [bind_dn, options[:password]||@password]
|
||||
raise LdapError.new( "invalid binding information" ) unless (user && psw)
|
||||
def ensure_port(method)
|
||||
if method == :ssl
|
||||
URI::LDAPS::DEFAULT_PORT
|
||||
else
|
||||
URI::LDAP::DEFAULT_PORT
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
execute(:bind, args)
|
||||
true
|
||||
rescue Exception
|
||||
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
|
||||
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
|
||||
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)
|
||||
puts options.inspect
|
||||
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
|
||||
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
|
||||
|
|
|
@ -86,8 +86,8 @@ describe OmniAuth::Strategies::CAS, :type => :strategy do
|
|||
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'
|
||||
it 'should call through to the master app when response is gzipped' do
|
||||
last_response.body.should == 'true'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ module OmniAuth
|
|||
class Flickr
|
||||
include OmniAuth::Strategy
|
||||
attr_accessor :api_key, :secret_key, :options
|
||||
|
||||
|
||||
# error catching, based on OAuth2 callback
|
||||
class CallbackError < StandardError
|
||||
attr_accessor :error, :error_reason
|
||||
|
@ -36,30 +36,30 @@ module OmniAuth
|
|||
end
|
||||
|
||||
protected
|
||||
|
||||
|
||||
def request_phase
|
||||
params = { :api_key => api_key, :perms => options[:scope] }
|
||||
params[:api_sig] = flickr_sign(params)
|
||||
query_string = params.collect{ |key,value| "#{key}=#{Rack::Utils.escape(value)}" }.join('&')
|
||||
redirect "http://flickr.com/services/auth/?#{query_string}"
|
||||
end
|
||||
|
||||
|
||||
def callback_phase
|
||||
params = { :api_key => api_key, :method => 'flickr.auth.getToken', :frob => request.params['frob'], :format => 'json', :nojsoncallback => '1' }
|
||||
params[:api_sig] = flickr_sign(params)
|
||||
|
||||
|
||||
response = RestClient.get('http://api.flickr.com/services/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'],
|
||||
|
@ -68,7 +68,7 @@ module OmniAuth
|
|||
'extra' => { 'user_hash' => @user }
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
def user_info
|
||||
name = @user['fullname']
|
||||
name = @user['username'] if name.nil? || name.empty?
|
||||
|
@ -77,7 +77,7 @@ module OmniAuth
|
|||
'name' => name,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def flickr_sign(params)
|
||||
Digest::MD5.hexdigest(secret_key + params.sort{|a,b| a[0].to_s <=> b[0].to_s }.flatten.join)
|
||||
end
|
||||
|
|
|
@ -5,9 +5,9 @@ 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.
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#######################################################################
|
||||
# FILE: windowslivelogin.rb
|
||||
#
|
||||
# DESCRIPTION: Sample implementation of Web Authentication and
|
||||
# Delegated Authentication protocol in Ruby. Also
|
||||
# includes trusted sign-in and application verification
|
||||
# FILE: windowslivelogin.rb
|
||||
#
|
||||
# DESCRIPTION: Sample implementation of Web Authentication and
|
||||
# Delegated Authentication protocol in Ruby. Also
|
||||
# includes trusted sign-in and application verification
|
||||
# sample implementations.
|
||||
#
|
||||
# VERSION: 1.1
|
||||
|
@ -26,7 +26,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
# By default, debug information will be printed to the standard
|
||||
# error output and should be visible in the web server logs.
|
||||
#####################################################################
|
||||
def setDebug(flag)
|
||||
def setDebug(flag)
|
||||
@debug = flag
|
||||
end
|
||||
|
||||
|
@ -39,7 +39,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
return unless @debug
|
||||
return if error.nil? or error.empty?
|
||||
warn("Windows Live ID Authentication SDK #{error}")
|
||||
nil
|
||||
nil
|
||||
end
|
||||
|
||||
#####################################################################
|
||||
|
@ -52,7 +52,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
|
||||
#####################################################################
|
||||
# Initialize the WindowsLiveLogin module with the application ID,
|
||||
# secret key, and security algorithm.
|
||||
# secret key, and security algorithm.
|
||||
#
|
||||
# We recommend that you employ strong measures to protect the
|
||||
# secret key. The secret key should never be exposed to the Web
|
||||
|
@ -65,16 +65,16 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
# For Delegated Authentication, you may optionally specify the
|
||||
# privacy policy URL and return URL. If you do not specify these
|
||||
# values here, the default values that you specified when you
|
||||
# registered your application will be used.
|
||||
# registered your application will be used.
|
||||
#
|
||||
# The 'force_delauth_nonprovisioned' flag also indicates whether
|
||||
# your application is registered for Delegated Authentication
|
||||
# (that is, whether it uses an application ID and secret key). We
|
||||
# recommend that your Delegated Authentication application always
|
||||
# your application is registered for Delegated Authentication
|
||||
# (that is, whether it uses an application ID and secret key). We
|
||||
# recommend that your Delegated Authentication application always
|
||||
# be registered for enhanced security and functionality.
|
||||
#####################################################################
|
||||
def initialize(appid=nil, secret=nil, securityalgorithm=nil,
|
||||
force_delauth_nonprovisioned=nil,
|
||||
def initialize(appid=nil, secret=nil, securityalgorithm=nil,
|
||||
force_delauth_nonprovisioned=nil,
|
||||
policyurl=nil, returnurl=nil)
|
||||
self.force_delauth_nonprovisioned = force_delauth_nonprovisioned
|
||||
self.appid = appid if appid
|
||||
|
@ -85,7 +85,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Initialize the WindowsLiveLogin module from a settings file.
|
||||
# Initialize the WindowsLiveLogin module from a settings file.
|
||||
#
|
||||
# 'settingsFile' specifies the location of the XML settings file
|
||||
# that contains the application ID, secret key, and security
|
||||
|
@ -102,7 +102,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
# Delegated Authentication samples.
|
||||
#
|
||||
# We recommend that you store the WindowsLiveLogin settings file
|
||||
# in an area on your server that cannot be accessed through the
|
||||
# in an area on your server that cannot be accessed through the
|
||||
# Internet. This file contains important confidential information.
|
||||
#####################################################################
|
||||
def self.initFromXml(settingsFile)
|
||||
|
@ -110,7 +110,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
settings = o.parseSettings(settingsFile)
|
||||
|
||||
o.setDebug(settings['debug'] == 'true')
|
||||
o.force_delauth_nonprovisioned =
|
||||
o.force_delauth_nonprovisioned =
|
||||
(settings['force_delauth_nonprovisioned'] == 'true')
|
||||
|
||||
o.appid = settings['appid']
|
||||
|
@ -133,7 +133,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
def appid=(appid)
|
||||
if (appid.nil? or appid.empty?)
|
||||
return if force_delauth_nonprovisioned
|
||||
fatal("Error: appid: Null application ID.")
|
||||
fatal("Error: appid: Null application ID.")
|
||||
end
|
||||
if (not appid =~ /^\w+$/)
|
||||
fatal("Error: appid: Application ID must be alpha-numeric: " + appid)
|
||||
|
@ -142,7 +142,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Returns the application ID.
|
||||
# Returns the application ID.
|
||||
#####################################################################
|
||||
def appid
|
||||
if (@appid.nil? or @appid.empty?)
|
||||
|
@ -158,10 +158,10 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
def secret=(secret)
|
||||
if (secret.nil? or secret.empty?)
|
||||
return if force_delauth_nonprovisioned
|
||||
fatal("Error: secret=: Secret must be non-null.")
|
||||
fatal("Error: secret=: Secret must be non-null.")
|
||||
end
|
||||
if (secret.size < 16)
|
||||
fatal("Error: secret=: Secret must be at least 16 characters.")
|
||||
fatal("Error: secret=: Secret must be at least 16 characters.")
|
||||
end
|
||||
@signkey = derive(secret, "SIGNATURE")
|
||||
@cryptkey = derive(secret, "ENCRYPTION")
|
||||
|
@ -171,20 +171,20 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
# Sets your old secret key.
|
||||
#
|
||||
# Use this property to set your old secret key if you are in the
|
||||
# process of transitioning to a new secret key. You may need this
|
||||
# property because the Windows Live ID servers can take up to
|
||||
# 24 hours to propagate a new secret key after you have updated
|
||||
# process of transitioning to a new secret key. You may need this
|
||||
# property because the Windows Live ID servers can take up to
|
||||
# 24 hours to propagate a new secret key after you have updated
|
||||
# your application settings.
|
||||
#
|
||||
# If an old secret key is specified here and has not expired
|
||||
# (as determined by the oldsecretexpiry setting), it will be used
|
||||
# as a fallback if token decryption fails with the new secret
|
||||
# as a fallback if token decryption fails with the new secret
|
||||
# key.
|
||||
#####################################################################
|
||||
def oldsecret=(secret)
|
||||
return if (secret.nil? or secret.empty?)
|
||||
if (secret.size < 16)
|
||||
fatal("Error: oldsecret=: Secret must be at least 16 characters.")
|
||||
fatal("Error: oldsecret=: Secret must be at least 16 characters.")
|
||||
end
|
||||
@oldsignkey = derive(secret, "SIGNATURE")
|
||||
@oldcryptkey = derive(secret, "ENCRYPTION")
|
||||
|
@ -197,7 +197,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
# used even if token decryption fails with the new secret key.
|
||||
#
|
||||
# The old secret expiry time is represented as the number of seconds
|
||||
# elapsed since January 1, 1970.
|
||||
# elapsed since January 1, 1970.
|
||||
#####################################################################
|
||||
def oldsecretexpiry=(timestamp)
|
||||
return if (timestamp.nil? or timestamp.empty?)
|
||||
|
@ -255,10 +255,10 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Sets the return URL--the URL on your site to which the consent
|
||||
# service redirects users (along with the action, consent token,
|
||||
# and application context) after they have successfully provided
|
||||
# consent information for Delegated Authentication. This value will
|
||||
# Sets the return URL--the URL on your site to which the consent
|
||||
# service redirects users (along with the action, consent token,
|
||||
# and application context) after they have successfully provided
|
||||
# consent information for Delegated Authentication. This value will
|
||||
# override the return URL specified during registration.
|
||||
#####################################################################
|
||||
def returnurl=(returnurl)
|
||||
|
@ -281,7 +281,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
|
||||
#####################################################################
|
||||
# Sets or gets the base URL to use for the Windows Live Login server. You
|
||||
# should not have to change this property. Furthermore, we recommend
|
||||
# should not have to change this property. Furthermore, we recommend
|
||||
# that you use the Sign In control instead of the URL methods
|
||||
# provided here.
|
||||
#####################################################################
|
||||
|
@ -296,7 +296,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Sets or gets the secure (HTTPS) URL to use for the Windows Live Login
|
||||
# Sets or gets the secure (HTTPS) URL to use for the Windows Live Login
|
||||
# server. You should not have to change this property.
|
||||
#####################################################################
|
||||
attr_accessor :secureurl
|
||||
|
@ -310,7 +310,7 @@ module OmniAuth; module Strategies; class WindowsLive; class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Sets or gets the Consent Base URL to use for the Windows Live Consent
|
||||
# Sets or gets the Consent Base URL to use for the Windows Live Consent
|
||||
# server. You should not have to use or change this property directly.
|
||||
#####################################################################
|
||||
attr_accessor :consenturl
|
||||
|
@ -329,9 +329,9 @@ end
|
|||
#######################################################################
|
||||
class WindowsLiveLogin
|
||||
#####################################################################
|
||||
# Returns the sign-in URL to use for the Windows Live Login server.
|
||||
# Returns the sign-in URL to use for the Windows Live Login server.
|
||||
# We recommend that you use the Sign In control instead.
|
||||
#
|
||||
#
|
||||
# If you specify it, 'context' will be returned as-is in the sign-in
|
||||
# response for site-specific use.
|
||||
#####################################################################
|
||||
|
@ -344,7 +344,7 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Returns the sign-out URL to use for the Windows Live Login server.
|
||||
# Returns the sign-out URL to use for the Windows Live Login server.
|
||||
# We recommend that you use the Sign In control instead.
|
||||
#####################################################################
|
||||
def getLogoutUrl(market=nil)
|
||||
|
@ -360,8 +360,8 @@ class WindowsLiveLogin
|
|||
# 'id' is the pairwise unique ID for the user.
|
||||
# 'context' is the application context that was originally passed to
|
||||
# the sign-in request, if any.
|
||||
# 'token' is the encrypted Web Authentication token that contains the
|
||||
# UID. This can be cached in a cookie and the UID can be retrieved by
|
||||
# 'token' is the encrypted Web Authentication token that contains the
|
||||
# UID. This can be cached in a cookie and the UID can be retrieved by
|
||||
# calling the processToken method.
|
||||
# 'usePersistentCookie?' indicates whether the application is
|
||||
# expected to store the user token in a session or persistent
|
||||
|
@ -373,8 +373,8 @@ class WindowsLiveLogin
|
|||
def usePersistentCookie?
|
||||
@usePersistentCookie
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Initialize the User with time stamp, userid, flags, context and token.
|
||||
#####################################################################
|
||||
|
@ -426,7 +426,7 @@ class WindowsLiveLogin
|
|||
# returned by CGI.params or Rails. (The unprocessed POST string
|
||||
# could also be used here but we do not recommend it).
|
||||
#
|
||||
# This method returns a User object on successful sign-in; otherwise
|
||||
# This method returns a User object on successful sign-in; otherwise
|
||||
# it returns nil.
|
||||
#####################################################################
|
||||
def processLogin(query)
|
||||
|
@ -446,8 +446,8 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Decodes and validates a Web Authentication token. Returns a User
|
||||
# object on success. If a context is passed in, it will be returned
|
||||
# Decodes and validates a Web Authentication token. Returns a User
|
||||
# object on success. If a context is passed in, it will be returned
|
||||
# as the context field in the User object.
|
||||
#####################################################################
|
||||
def processToken(token, context=nil)
|
||||
|
@ -467,7 +467,7 @@ class WindowsLiveLogin
|
|||
return
|
||||
end
|
||||
begin
|
||||
user = User.new(stoken['ts'], stoken['uid'], stoken['flags'],
|
||||
user = User.new(stoken['ts'], stoken['uid'], stoken['flags'],
|
||||
context, token)
|
||||
return user
|
||||
rescue Exception => e
|
||||
|
@ -477,10 +477,10 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Returns an appropriate content type and body response that the
|
||||
# application handler can return to signify a successful sign-out
|
||||
# Returns an appropriate content type and body response that the
|
||||
# application handler can return to signify a successful sign-out
|
||||
# from the application.
|
||||
#
|
||||
#
|
||||
# When a user signs out of Windows Live or a Windows Live
|
||||
# application, a best-effort attempt is made at signing the user out
|
||||
# from all other Windows Live applications the user might be signed
|
||||
|
@ -511,7 +511,7 @@ class WindowsLiveLogin
|
|||
# If you specify it, 'context' will be returned as-is in the consent
|
||||
# response for site-specific use.
|
||||
#
|
||||
# The registered/configured return URL can also be overridden by
|
||||
# The registered/configured return URL can also be overridden by
|
||||
# specifying 'ru' here.
|
||||
#
|
||||
# You can change the language in which the consent page is displayed
|
||||
|
@ -534,9 +534,9 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Returns the URL to use to download a new consent token, given the
|
||||
# Returns the URL to use to download a new consent token, given the
|
||||
# offers and refresh token.
|
||||
# The registered/configured return URL can also be overridden by
|
||||
# The registered/configured return URL can also be overridden by
|
||||
# specifying 'ru' here.
|
||||
#####################################################################
|
||||
def getRefreshConsentTokenUrl(offers, refreshtoken, ru)
|
||||
|
@ -546,7 +546,7 @@ class WindowsLiveLogin
|
|||
if (refreshtoken.nil? or refreshtoken.empty?)
|
||||
fatal("Error: getRefreshConsentTokenUrl: Invalid refresh token.")
|
||||
end
|
||||
url = consenturl + "RefreshToken.aspx?ps=#{CGI.escape(offers)}"
|
||||
url = consenturl + "RefreshToken.aspx?ps=#{CGI.escape(offers)}"
|
||||
url += "&reft=#{refreshtoken}"
|
||||
ru = returnurl if (ru.nil? or ru.empty?)
|
||||
url += "&ru=#{CGI.escape(ru)}" if ru
|
||||
|
@ -578,9 +578,9 @@ class WindowsLiveLogin
|
|||
return false unless delegationtoken
|
||||
return ((Time.now.to_i-300) < expiry.to_i)
|
||||
end
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Refreshes the current token and replace it. If operation succeeds
|
||||
# Refreshes the current token and replace it. If operation succeeds
|
||||
# true is returned to signify success.
|
||||
#####################################################################
|
||||
def refresh
|
||||
|
@ -591,9 +591,9 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Initialize the ConsentToken module with the WindowsLiveLogin,
|
||||
# delegation token, refresh token, session key, expiry, offers,
|
||||
# location ID, context, decoded token, and raw token.
|
||||
# Initialize the ConsentToken module with the WindowsLiveLogin,
|
||||
# delegation token, refresh token, session key, expiry, offers,
|
||||
# location ID, context, decoded token, and raw token.
|
||||
#####################################################################
|
||||
def initialize(wll, delegationtoken, refreshtoken, sessionkey, expiry,
|
||||
offers, locationid, context, decodedtoken, token)
|
||||
|
@ -608,7 +608,7 @@ class WindowsLiveLogin
|
|||
self.decodedtoken = decodedtoken
|
||||
self.token = token
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
attr_writer :delegationtoken, :refreshtoken, :sessionkey, :expiry
|
||||
attr_writer :offers, :offers_string, :locationid, :context
|
||||
|
@ -619,7 +619,7 @@ class WindowsLiveLogin
|
|||
#####################################################################
|
||||
def delegationtoken=(delegationtoken)
|
||||
if (delegationtoken.nil? or delegationtoken.empty?)
|
||||
raise("Error: ConsentToken: Null delegation token.")
|
||||
raise("Error: ConsentToken: Null delegation token.")
|
||||
end
|
||||
@delegationtoken = delegationtoken
|
||||
end
|
||||
|
@ -694,10 +694,10 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Processes the POST response from the Delegated Authentication
|
||||
# Processes the POST response from the Delegated Authentication
|
||||
# service after a user has granted consent. The processConsent
|
||||
# function extracts the consent token string and returns the result
|
||||
# of invoking the processConsentToken method.
|
||||
# function extracts the consent token string and returns the result
|
||||
# of invoking the processConsentToken method.
|
||||
#####################################################################
|
||||
def processConsent(query)
|
||||
query = parse query
|
||||
|
@ -721,8 +721,8 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Processes the consent token string that is returned in the POST
|
||||
# response by the Delegated Authentication service after a
|
||||
# Processes the consent token string that is returned in the POST
|
||||
# response by the Delegated Authentication service after a
|
||||
# user has granted consent.
|
||||
#####################################################################
|
||||
def processConsentToken(token, context=nil)
|
||||
|
@ -747,7 +747,7 @@ class WindowsLiveLogin
|
|||
decodedtoken = CGI.escape(decodedtoken)
|
||||
end
|
||||
begin
|
||||
consenttoken = ConsentToken.new(self,
|
||||
consenttoken = ConsentToken.new(self,
|
||||
parsedtoken['delt'],
|
||||
parsedtoken['reft'],
|
||||
parsedtoken['skey'],
|
||||
|
@ -763,7 +763,7 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Attempts to obtain a new, refreshed token and return it. The
|
||||
# Attempts to obtain a new, refreshed token and return it. The
|
||||
# original token is not modified.
|
||||
#####################################################################
|
||||
def refreshConsentToken(consenttoken, ru=nil)
|
||||
|
@ -853,7 +853,7 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Creates a signature for the given string by using the signature
|
||||
# Creates a signature for the given string by using the signature
|
||||
# key.
|
||||
#####################################################################
|
||||
def signToken(token, signkey=@signkey)
|
||||
|
@ -890,12 +890,12 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#######################################################################
|
||||
# Implementation of the methods needed to perform Windows Live
|
||||
# Implementation of the methods needed to perform Windows Live
|
||||
# application verification as well as trusted sign-in.
|
||||
#######################################################################
|
||||
class WindowsLiveLogin
|
||||
#####################################################################
|
||||
# Generates an application verifier token. An IP address can
|
||||
# Generates an application verifier token. An IP address can
|
||||
# optionally be included in the token.
|
||||
#####################################################################
|
||||
def getAppVerifier(ip=nil)
|
||||
|
@ -906,16 +906,16 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Returns the URL that is required to retrieve the application
|
||||
# Returns the URL that is required to retrieve the application
|
||||
# security token.
|
||||
#
|
||||
# By default, the application security token is generated for
|
||||
# the Windows Live site; a specific Site ID can optionally be
|
||||
# specified in 'siteid'. The IP address can also optionally be
|
||||
# By default, the application security token is generated for
|
||||
# the Windows Live site; a specific Site ID can optionally be
|
||||
# specified in 'siteid'. The IP address can also optionally be
|
||||
# included in 'ip'.
|
||||
#
|
||||
# If 'js' is nil, a JavaScript Output Notation (JSON) response is
|
||||
# returned in the following format:
|
||||
# If 'js' is nil, a JavaScript Output Notation (JSON) response is
|
||||
# returned in the following format:
|
||||
#
|
||||
# {"token":"<value>"}
|
||||
#
|
||||
|
@ -935,7 +935,7 @@ class WindowsLiveLogin
|
|||
|
||||
#####################################################################
|
||||
# Retrieves the application security token for application
|
||||
# verification from the application sign-in URL.
|
||||
# verification from the application sign-in URL.
|
||||
#
|
||||
# By default, the application security token will be generated for
|
||||
# the Windows Live site; a specific Site ID can optionally be
|
||||
|
@ -962,7 +962,7 @@ class WindowsLiveLogin
|
|||
debug("Error: getAppSecurityToken: Failed to extract token: #{body}")
|
||||
rescue Exception => e
|
||||
debug("Error: getAppSecurityToken: Failed to get token: #{e}")
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -983,13 +983,13 @@ class WindowsLiveLogin
|
|||
# may have to be escaped if you are inserting them in code such as
|
||||
# an HTML form.
|
||||
#
|
||||
# The user to be trusted on the local site is passed in as string
|
||||
# The user to be trusted on the local site is passed in as string
|
||||
# 'user'.
|
||||
#
|
||||
# Optionally, 'retcode' specifies the resource to which successful
|
||||
# sign-in is redirected, such as Windows Live Mail, and is typically
|
||||
# a string in the format 'id=2000'. If you pass in the value from
|
||||
# getAppRetCode instead, sign-in will be redirected to the
|
||||
# getAppRetCode instead, sign-in will be redirected to the
|
||||
# application. Otherwise, an HTTP 200 response is returned.
|
||||
#####################################################################
|
||||
def getTrustedParams(user, retcode=nil)
|
||||
|
@ -1022,7 +1022,7 @@ class WindowsLiveLogin
|
|||
|
||||
#####################################################################
|
||||
# Returns the trusted sign-in URL to use for the Windows Live Login
|
||||
# server.
|
||||
# server.
|
||||
#####################################################################
|
||||
def getTrustedLoginUrl
|
||||
secureurl + "wlogin.srf"
|
||||
|
@ -1041,10 +1041,10 @@ end
|
|||
# Helper methods.
|
||||
#######################################################################
|
||||
class WindowsLiveLogin
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Function to parse the settings file.
|
||||
#######################################################################
|
||||
#######################################################################
|
||||
def parseSettings(settingsFile)
|
||||
settings = {}
|
||||
begin
|
||||
|
@ -1077,12 +1077,12 @@ class WindowsLiveLogin
|
|||
end
|
||||
|
||||
#####################################################################
|
||||
# Parses query string and return a table
|
||||
# Parses query string and return a table
|
||||
# {String=>String}
|
||||
#
|
||||
# If a table is passed in from CGI.params, we convert it from
|
||||
# {String=>[]} to {String=>String}. I believe Rails uses symbols
|
||||
# instead of strings in general, so we convert from symbols to
|
||||
# instead of strings in general, so we convert from symbols to
|
||||
# strings here also.
|
||||
#####################################################################
|
||||
def parse(input)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
require File.expand_path('../../../spec_helper', __FILE__)
|
||||
|
||||
describe OmniAuth::Strategies::Gowalla do
|
||||
it_should_behave_like "an oauth2 strategy"
|
||||
it_should_behave_like "an oauth2 strategy"
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
require File.expand_path('../../../spec_helper', __FILE__)
|
||||
|
||||
describe OmniAuth::Strategies::Miso do
|
||||
it_should_behave_like 'an oauth strategy'
|
||||
it_should_behave_like 'an oauth strategy'
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@ require File.expand_path('../../../spec_helper', __FILE__)
|
|||
|
||||
describe OmniAuth::Strategies::Twitter do
|
||||
it_should_behave_like 'an oauth strategy'
|
||||
|
||||
|
||||
it 'should use the authenticate (sign in) path by default' do
|
||||
s = strategy_class.new(app, 'abc', 'def')
|
||||
s.consumer.options[:authorize_path].should == '/oauth/authenticate'
|
||||
|
@ -12,7 +12,7 @@ describe OmniAuth::Strategies::Twitter do
|
|||
s = strategy_class.new(app, 'abc', 'def', :force_login => true)
|
||||
s.options[:authorize_params].should == { :force_login => 'true' }
|
||||
end
|
||||
|
||||
|
||||
it 'should use the authorize path if :sign_in is false' do
|
||||
s = strategy_class.new(app, 'abc', 'def', :sign_in => false)
|
||||
s.consumer.options[:authorize_path].should == '/oauth/authorize'
|
||||
|
|
|
@ -2,7 +2,7 @@ shared_examples_for "an oauth strategy" do
|
|||
it 'should be initializable with only three arguments' do
|
||||
lambda{ strategy_class.new(lambda{|env| [200, {}, ['Hello World']]}, 'key', 'secret') }.should_not raise_error
|
||||
end
|
||||
|
||||
|
||||
it 'should be initializable with a block' do
|
||||
lambda{ strategy_class.new(lambda{|env| [200, {}, ['Hello World']]}){|s| s.consumer_key = 'abc'} }.should_not raise_error
|
||||
end
|
||||
|
@ -17,7 +17,7 @@ shared_examples_for "an oauth2 strategy" do
|
|||
it 'should be initializable with only three arguments' do
|
||||
lambda{ strategy_class.new(lambda{|env| [200, {}, ['Hello World']]}, 'key', 'secret') }.should_not raise_error
|
||||
end
|
||||
|
||||
|
||||
it 'should be initializable with a block' do
|
||||
lambda{ strategy_class.new(lambda{|env| [200, {}, ['Hello World']]}){|s| s.client_id = 'abc'} }.should_not raise_error
|
||||
end
|
||||
|
|
|
@ -2,56 +2,56 @@ require 'omniauth/core'
|
|||
|
||||
module OmniAuth
|
||||
# OmniAuth::OpenID provides strategies for authenticating to providers
|
||||
# using the OpenID standard.
|
||||
#
|
||||
# using the OpenID standard.
|
||||
#
|
||||
# # Installation
|
||||
#
|
||||
#
|
||||
# To get just OpenID functionality:
|
||||
#
|
||||
#
|
||||
# gem install oa-openid
|
||||
#
|
||||
#
|
||||
# For the full auth suite:
|
||||
#
|
||||
#
|
||||
# gem install omniauth
|
||||
#
|
||||
#
|
||||
# # Stand-Alone Example
|
||||
#
|
||||
#
|
||||
# Use the strategy as a middleware in your application:
|
||||
#
|
||||
#
|
||||
# require 'omniauth/openid'
|
||||
# require 'openid/store/filesystem'
|
||||
#
|
||||
#
|
||||
# use Rack::Session::Cookie
|
||||
# use OmniAuth::Strategies::OpenID, OpenID::Store::Filesystem.new('/tmp')
|
||||
#
|
||||
#
|
||||
# Then simply direct users to '/auth/open_id' to prompt them for their OpenID identifier. You may also pre-set the identifier by passing an <tt>identifier</tt> parameter to the URL (Example: <tt>/auth/open_id?openid_url=yahoo.com</tt>).
|
||||
#
|
||||
#
|
||||
# A list of all OpenID stores is available at http://github.com/openid/ruby-openid/tree/master/lib/openid/store/
|
||||
#
|
||||
#
|
||||
# # OmniAuth Builder
|
||||
#
|
||||
#
|
||||
# If OpenID is one of several authentication strategies, use the OmniAuth Builder:
|
||||
#
|
||||
#
|
||||
# require 'omniauth/openid'
|
||||
# require 'omniauth/basic' # for Campfire
|
||||
# require 'openid/store/filesystem'
|
||||
#
|
||||
#
|
||||
# use OmniAuth::Builder do
|
||||
# provider :open_id, OpenID::Store::Filesystem.new('/tmp')
|
||||
# provider :campfire
|
||||
# end
|
||||
#
|
||||
#
|
||||
# # Configured Identifiers
|
||||
#
|
||||
#
|
||||
# You may pre-configure an OpenID identifier. For example, to use Google's main OpenID endpoint:
|
||||
#
|
||||
#
|
||||
# use OmniAuth::Builder do
|
||||
# provider :open_id, nil, :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
|
||||
# end
|
||||
#
|
||||
#
|
||||
# Note the use of nil, which will trigger ruby-openid's default Memory Store.
|
||||
module OpenID; end
|
||||
|
||||
|
||||
module Strategies
|
||||
autoload :OpenID, 'omniauth/strategies/open_id'
|
||||
autoload :GoogleApps, 'omniauth/strategies/google_apps'
|
||||
|
|
|
@ -8,25 +8,25 @@ module OpenID
|
|||
# with others.
|
||||
def self.discover(uri)
|
||||
discovered = self.default_discover(uri)
|
||||
|
||||
|
||||
if discovered.last.empty?
|
||||
info = discover_google_apps(uri)
|
||||
info = discover_google_apps(uri)
|
||||
return info if info
|
||||
end
|
||||
|
||||
|
||||
return discovered
|
||||
rescue OpenID::DiscoveryFailure => e
|
||||
info = discover_google_apps(uri)
|
||||
|
||||
|
||||
if info.nil?
|
||||
raise e
|
||||
else
|
||||
return info
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.discover_google_apps(uri)
|
||||
discovery = GoogleDiscovery.new
|
||||
discovery.perform_discovery(uri)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,14 +7,14 @@ module OmniAuth
|
|||
options[:name] ||= 'google_apps'
|
||||
super(app, store, options, &block)
|
||||
end
|
||||
|
||||
|
||||
def get_identifier
|
||||
OmniAuth::Form.build(:title => 'Google Apps Authentication') do
|
||||
label_field('Google Apps Domain', 'domain')
|
||||
input_field('url', 'domain')
|
||||
end.to_response
|
||||
end
|
||||
|
||||
|
||||
def identifier
|
||||
options[:domain] || request['domain']
|
||||
end
|
||||
|
|
|
@ -8,11 +8,11 @@ module OmniAuth
|
|||
# to a wide variety of sites, some of which are listed [on the OpenID website](http://openid.net/get-an-openid/).
|
||||
class OpenID
|
||||
include OmniAuth::Strategy
|
||||
|
||||
|
||||
attr_accessor :options
|
||||
|
||||
|
||||
IDENTIFIER_URL_PARAMETER = 'openid_url'
|
||||
|
||||
|
||||
AX = {
|
||||
:email => 'http://axschema.org/contact/email',
|
||||
:name => 'http://axschema.org/namePerson',
|
||||
|
@ -24,13 +24,13 @@ module OmniAuth
|
|||
:website => 'http://axschema.org/contact/web/default',
|
||||
:image => 'http://axschema.org/media/image/aspect11'
|
||||
}
|
||||
|
||||
|
||||
# Initialize the strategy as a Rack Middleware.
|
||||
#
|
||||
# @param app [Rack Application] Standard Rack middleware application argument.
|
||||
# @param store [OpenID Store] The [OpenID Store](http://github.com/openid/ruby-openid/tree/master/lib/openid/store/)
|
||||
# you wish to use. Defaults to OpenID::MemoryStore.
|
||||
# @option options [Array] :required The identity fields that are required for the OpenID
|
||||
# @option options [Array] :required The identity fields that are required for the OpenID
|
||||
# request. May be an ActiveExchange schema URL or an sreg identifier.
|
||||
# @option options [Array] :optional The optional attributes for the OpenID request. May
|
||||
# be ActiveExchange or sreg.
|
||||
|
@ -42,9 +42,9 @@ module OmniAuth
|
|||
@options[:optional] ||= [AX[:nickname], AX[:city], AX[:state], AX[:website], AX[:image], 'postcode', 'nickname']
|
||||
@store = store
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
|
||||
|
||||
def dummy_app
|
||||
lambda{|env| [401, {"WWW-Authenticate" => Rack::OpenID.build_header(
|
||||
:identifier => identifier,
|
||||
|
@ -54,15 +54,15 @@ module OmniAuth
|
|||
:method => 'post'
|
||||
)}, []]}
|
||||
end
|
||||
|
||||
|
||||
def identifier
|
||||
options[:identifier] || request[IDENTIFIER_URL_PARAMETER]
|
||||
end
|
||||
|
||||
|
||||
def request_phase
|
||||
identifier ? start : get_identifier
|
||||
end
|
||||
|
||||
|
||||
def start
|
||||
openid = Rack::OpenID.new(dummy_app, @store)
|
||||
response = openid.call(env)
|
||||
|
@ -73,14 +73,14 @@ module OmniAuth
|
|||
response
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def get_identifier
|
||||
OmniAuth::Form.build(:title => 'OpenID Authentication') do
|
||||
label_field('OpenID Identifier', IDENTIFIER_URL_PARAMETER)
|
||||
input_field('url', IDENTIFIER_URL_PARAMETER)
|
||||
end.to_response
|
||||
end
|
||||
|
||||
|
||||
def callback_phase
|
||||
openid = Rack::OpenID.new(lambda{|env| [200,{},[]]}, @store)
|
||||
openid.call(env)
|
||||
|
@ -91,18 +91,18 @@ module OmniAuth
|
|||
fail!(:invalid_credentials)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def auth_hash
|
||||
OmniAuth::Utils.deep_merge(super(), {
|
||||
'uid' => @openid_response.display_identifier,
|
||||
'user_info' => user_info(@openid_response)
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
def user_info(response)
|
||||
sreg_user_info(response).merge(ax_user_info(response))
|
||||
end
|
||||
|
||||
|
||||
def sreg_user_info(response)
|
||||
sreg = ::OpenID::SReg::Response.from_success_response(response)
|
||||
return {} unless sreg
|
||||
|
@ -113,7 +113,7 @@ module OmniAuth
|
|||
'nickname' => sreg['nickname']
|
||||
}.reject{|k,v| v.nil? || v == ''}
|
||||
end
|
||||
|
||||
|
||||
def ax_user_info(response)
|
||||
ax = ::OpenID::AX::FetchResponse.from_success_response(response)
|
||||
return {} unless ax
|
||||
|
|
|
@ -5,33 +5,33 @@ describe OmniAuth::Strategies::OpenID do
|
|||
end
|
||||
|
||||
# require File.dirname(__FILE__) + '/../../spec_helper'
|
||||
#
|
||||
#
|
||||
# describe OmniAuth::Strategies::OpenID, :type => :strategy do
|
||||
#
|
||||
#
|
||||
# include OmniAuth::Test::StrategyTestCase
|
||||
#
|
||||
#
|
||||
# def strategy
|
||||
# [OmniAuth::Strategies::OpenID]
|
||||
# end
|
||||
#
|
||||
#
|
||||
# describe '/auth/open_id without an identifier URL' do
|
||||
# before do
|
||||
# get '/auth/open_id'
|
||||
# end
|
||||
#
|
||||
#
|
||||
# it 'should respond with OK' do
|
||||
# last_response.should be_ok
|
||||
# end
|
||||
#
|
||||
#
|
||||
# it 'should respond with HTML' do
|
||||
# last_response.content_type.should == 'text/html'
|
||||
# end
|
||||
#
|
||||
#
|
||||
# it 'should render an identifier URL input' do
|
||||
# last_response.body.should =~ %r{<input[^>]*#{OmniAuth::Strategies::OpenID::IDENTIFIER_URL_PARAMETER}}
|
||||
# end
|
||||
# end
|
||||
#
|
||||
#
|
||||
# describe '/auth/open_id with an identifier URL' do
|
||||
# before do
|
||||
# @identifier_url = 'http://me.example.org'
|
||||
|
@ -39,19 +39,19 @@ end
|
|||
# stub_request(:get, @identifier_url)
|
||||
# get '/auth/open_id?openid_url=' + @identifier_url
|
||||
# end
|
||||
#
|
||||
#
|
||||
# it 'should redirect to the OpenID identity URL' do
|
||||
# last_response.should be_redirect
|
||||
# last_response.headers['Location'].should =~ %r{^#{@identifier_url}.*}
|
||||
# end
|
||||
#
|
||||
#
|
||||
# it 'should tell the OpenID server to return to the callback URL' do
|
||||
# return_to = CGI.escape(last_request.url + '/callback')
|
||||
# last_response.headers['Location'].should =~ %r{[\?&]openid.return_to=#{return_to}}
|
||||
# end
|
||||
#
|
||||
#
|
||||
# end
|
||||
#
|
||||
#
|
||||
# describe 'followed by /auth/open_id/callback' do
|
||||
# before do
|
||||
# @identifier_url = 'http://me.example.org'
|
||||
|
@ -59,11 +59,11 @@ end
|
|||
# stub_request(:get, @identifier_url)
|
||||
# get '/auth/open_id/callback'
|
||||
# end
|
||||
#
|
||||
#
|
||||
# sets_an_auth_hash
|
||||
# sets_provider_to 'open_id'
|
||||
# sets_uid_to 'http://me.example.org'
|
||||
#
|
||||
#
|
||||
# it 'should call through to the master app' do
|
||||
# last_response.body.should == 'true'
|
||||
# end
|
||||
|
|
Loading…
Reference in a new issue