spec/omniauth/strategies/cas_spec.rb in omniauth-cas-1.1.0.beta.1 vs spec/omniauth/strategies/cas_spec.rb in omniauth-cas-1.1.0.pre.rc.1
- old
+ new
@@ -1,15 +1,18 @@
require 'spec_helper'
describe OmniAuth::Strategies::CAS, type: :strategy do
include Rack::Test::Methods
- class MyCasProvider < OmniAuth::Strategies::CAS; end # TODO: Not really needed. just an alias but it requires the :name option which might confuse users...
- def app
+ let(:my_cas_provider) { Class.new(OmniAuth::Strategies::CAS) }
+ before do
+ stub_const 'MyCasProvider', my_cas_provider
+ end
+ let(:app) do
Rack::Builder.new {
use OmniAuth::Test::PhonySession
- use MyCasProvider, name: :cas, host: 'cas.example.org', ssl: false, port: 8080, uid_key: :employeeid
+ use MyCasProvider, name: :cas, host: 'cas.example.org', ssl: false, port: 8080, uid_field: :employeeid
run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [env.key?('omniauth.auth').to_s]] }
}.to_app
end
# TODO: Verify that these are even useful tests
@@ -20,17 +23,60 @@
subject { last_response }
it { should be_redirect }
- it 'should redirect to the CAS server' do
- subject.headers['Location'].should == 'http://cas.example.org:8080/login?' + redirect_params
+ it 'redirects to the CAS server' do
+ expect(subject.headers).to include 'Location' => "http://cas.example.org:8080/login?#{redirect_params}"
end
end
+ describe '#cas_url' do
+ let(:params) { Hash.new }
+ let(:provider) { MyCasProvider.new(nil, params) }
+
+ subject { provider.cas_url }
+
+ it 'raises an ArgumentError' do
+ expect{subject}.to raise_error ArgumentError, %r{:host and :login_url MUST be provided}
+ end
+
+ context 'with an explicit :url option' do
+ let(:url) { 'https://example.org:8080/my_cas' }
+ let(:params) { super().merge url:url }
+
+ before { subject }
+
+ it { should eq url }
+
+ it 'parses the URL into it the appropriate strategy options' do
+ expect(provider.options).to include ssl:true
+ expect(provider.options).to include host:'example.org'
+ expect(provider.options).to include port:8080
+ expect(provider.options).to include path:'/my_cas'
+ end
+ end
+
+ context 'with explicit URL component' do
+ let(:params) { super().merge host:'example.org', port:1234, ssl:true, path:'/a/path' }
+
+ before { subject }
+
+ it { should eq 'https://example.org:1234/a/path' }
+
+ it 'parses the URL into it the appropriate strategy options' do
+ expect(provider.options).to include ssl:true
+ expect(provider.options).to include host:'example.org'
+ expect(provider.options).to include port:1234
+ expect(provider.options).to include path:'/a/path'
+ end
+ end
+ end
+
describe 'defaults' do
subject { MyCasProvider.default_options.to_hash }
+
it { should include('ssl' => true) }
end
describe 'GET /auth/cas' do
let(:return_url) { 'http://myapp.com/admin/foo' }
@@ -50,104 +96,155 @@
it_behaves_like 'a CAS redirect response'
end
end
- describe 'GET /auth/cas/callback without a ticket' do
- before { get '/auth/cas/callback' }
+ describe 'GET /auth/cas/callback' do
+ context 'without a ticket' do
+ before { get '/auth/cas/callback' }
- subject { last_response }
+ subject { last_response }
- it { should be_redirect }
+ it { should be_redirect }
- it 'should have a failure message' do
- subject.headers['Location'].should == '/auth/failure?message=no_ticket&strategy=cas'
+ it 'redirects with a failure message' do
+ expect(subject.headers).to include 'Location' => '/auth/failure?message=no_ticket&strategy=cas'
+ end
end
- end
- describe 'GET /auth/cas/callback with an invalid ticket' do
- before do
- stub_request(:get, /^http:\/\/cas.example.org:8080?\/serviceValidate\?([^&]+&)?ticket=9391d/).
- to_return( body: File.read('spec/fixtures/cas_failure.xml') )
- get '/auth/cas/callback?ticket=9391d'
- end
+ context 'with an invalid ticket' do
+ before do
+ stub_request(:get, /^http:\/\/cas.example.org:8080?\/serviceValidate\?([^&]+&)?ticket=9391d/).
+ to_return( body: File.read('spec/fixtures/cas_failure.xml') )
+ get '/auth/cas/callback?ticket=9391d'
+ end
- subject { last_response }
+ subject { last_response }
- it { should be_redirect }
+ it { should be_redirect }
- it 'should have a failure message' do
- subject.headers['Location'].should == '/auth/failure?message=invalid_ticket&strategy=cas'
+ it 'redirects with a failure message' do
+ expect(subject.headers).to include 'Location' => '/auth/failure?message=invalid_ticket&strategy=cas'
+ end
end
- end
- describe 'GET /auth/cas/callback with a valid ticket' do
- let(:return_url) { 'http://127.0.0.10/?some=parameter' }
+ describe 'with a valid ticket' do
+ shared_examples :successful_validation do
+ before do
+ stub_request(:get, /^http:\/\/cas.example.org:8080?\/serviceValidate\?([^&]+&)?ticket=593af/)
+ .with { |request| @request_uri = request.uri.to_s }
+ .to_return( body: File.read("spec/fixtures/#{xml_file_name}") )
- before do
- stub_request(:get, /^http:\/\/cas.example.org:8080?\/serviceValidate\?([^&]+&)?ticket=593af/)
- .with { |request| @request_uri = request.uri.to_s }
- .to_return( body: File.read('spec/fixtures/cas_success.xml') )
+ get "/auth/cas/callback?ticket=593af&url=#{return_url}"
+ end
- get "/auth/cas/callback?ticket=593af&url=#{return_url}"
- end
+ it 'strips the ticket parameter from the callback URL' do
+ expect(@request_uri.scan('ticket=').size).to eq 1
+ end
- it 'should strip the ticket parameter from the callback URL' do
- @request_uri.scan('ticket=').length.should == 1
- end
+ it 'properly encodes the service URL' do
+ expect(WebMock).to have_requested(:get, 'http://cas.example.org:8080/serviceValidate')
+ .with(query: {
+ ticket: '593af',
+ service: 'http://example.org/auth/cas/callback?url=' + Rack::Utils.escape('http://127.0.0.10/?some=parameter')
+ })
+ end
- it 'should properly encode the service URL' do
- WebMock.should have_requested(:get, 'http://cas.example.org:8080/serviceValidate')
- .with(query: {
- ticket: '593af',
- service: 'http://example.org/auth/cas/callback?url=' + Rack::Utils.escape('http://127.0.0.10/?some=parameter')
- })
- end
+ context "request.env['omniauth.auth']" do
+ subject { last_request.env['omniauth.auth'] }
- context "request.env['omniauth.auth']" do
- subject { last_request.env['omniauth.auth'] }
+ it { should be_kind_of Hash }
- it { should be_kind_of Hash }
+ it 'identifes the provider' do
+ expect(subject.provider).to eq :cas
+ end
- its(:provider) { should == :cas }
+ it 'returns the UID of the user' do
+ expect(subject.uid).to eq '54'
+ end
- its(:uid) { should == '54'}
+ context 'the info hash' do
+ subject { last_request.env['omniauth.auth']['info'] }
- context 'the info hash' do
- subject { last_request.env['omniauth.auth']['info'] }
+ it 'includes user info attributes' do
+ expect(subject.name).to eq 'Peter Segel'
+ expect(subject.first_name).to eq 'Peter'
+ expect(subject.last_name).to eq 'Segel'
+ expect(subject.nickname).to eq 'psegel'
+ expect(subject.email).to eq 'psegel@intridea.com'
+ expect(subject.location).to eq 'Washington, D.C.'
+ expect(subject.image).to eq '/images/user.jpg'
+ expect(subject.phone).to eq '555-555-5555'
+ end
+ end
- it { should have(6).items }
+ context 'the extra hash' do
+ subject { last_request.env['omniauth.auth']['extra'] }
- its(:name) { should == 'Peter Segel' }
- its(:first_name) { should == 'Peter' }
- its(:last_name) { should == 'Segel' }
- its(:email) { should == 'psegel@intridea.com' }
- its(:location) { should == 'Washington, D.C.' }
- its(:image) { should == '/images/user.jpg' }
- its(:phone) { should == '555-555-5555' }
- end
+ it 'includes additional user attributes' do
+ expect(subject.user).to eq 'psegel'
+ expect(subject.employeeid).to eq '54'
+ expect(subject.hire_date).to eq '2004-07-13'
+ end
+ end
- context 'the extra hash' do
- subject { last_request.env['omniauth.auth']['extra'] }
+ context 'the credentials hash' do
+ subject { last_request.env['omniauth.auth']['credentials'] }
- it { should have(3).items }
+ it 'has a ticket value' do
+ expect(subject.ticket).to eq '593af'
+ end
+ end
+ end
- its(:user) { should == 'psegel' }
- its(:employeeid) { should == '54' }
- its(:hire_date) { should == '2004-07-13' }
+ it 'calls through to the master app' do
+ expect(last_response.body).to eq 'true'
+ end
end
- context 'the credentials hash' do
- subject { last_request.env['omniauth.auth']['credentials'] }
+ let(:return_url) { 'http://127.0.0.10/?some=parameter' }
- it { should have(1).items }
+ context 'with JASIG flavored XML' do
+ let(:xml_file_name) { 'cas_success_jasig.xml' }
- its(:ticket) { should == '593af' }
+ it_behaves_like :successful_validation
end
- end
- it 'should call through to the master app' do
- last_response.body.should == 'true'
+ context 'with classic XML' do
+ let(:xml_file_name) { 'cas_success.xml' }
+
+ it_behaves_like :successful_validation
+ end
end
end
+ describe 'POST /auth/cas/callback' do
+ describe 'with a Single Sign-Out logoutRequest' do
+ let(:logoutRequest) do
+ %Q[
+ <samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion\" ID="123abc-1234-ab12-cd34-1234abcd" Version="2.0" IssueInstant="#{Time.now.to_s}">
+ <saml:NameID>@NOT_USED@</saml:NameID>
+ <samlp:SessionIndex>ST-123456-123abc456def</samlp:SessionIndex>
+ </samlp:LogoutRequest>
+ ]
+ end
+
+ let(:logout_request) { double('logout_request', call:[200,{},'OK']) }
+
+ subject do
+ post 'auth/cas/callback', logoutRequest:logoutRequest
+ end
+
+ before do
+ allow_any_instance_of(MyCasProvider)
+ .to receive(:logout_request_service)
+ .and_return double('LogoutRequest', new:logout_request)
+
+ subject
+ end
+
+ it 'initializes a LogoutRequest' do
+ expect(logout_request).to have_received :call
+ end
+ end
+ end
end