From 0a5ca67d0894f8fc717b40a78d23e495360c21bd Mon Sep 17 00:00:00 2001
From: Derek Lindahl <dlindahl@customink.com>
Date: Tue, 3 Jan 2012 12:42:21 -0500
Subject: [PATCH] Fixed #1 - The return URL can now be explicitly set, falling
 back to the `referrer` if absent.

---
 lib/omniauth/strategies/cas.rb       | 13 ++++++++++++-
 spec/omniauth/strategies/cas_spec.rb | 26 ++++++++++++++++++++------
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/lib/omniauth/strategies/cas.rb b/lib/omniauth/strategies/cas.rb
index e6c1f65..20dfce0 100644
--- a/lib/omniauth/strategies/cas.rb
+++ b/lib/omniauth/strategies/cas.rb
@@ -68,10 +68,12 @@ module OmniAuth
       end
 
       def request_phase
+        service_url = append_params( callback_url, return_url )
+
         [
           302,
           {
-            'Location' => login_url( append_params(callback_url, :url => request.referer) ),
+            'Location' => login_url( service_url ),
             'Content-Type' => 'text/plain'
           },
           ["You are being redirected to CAS for sign-in."]
@@ -167,6 +169,15 @@ module OmniAuth
       #   ap "CREDENTIALS"
       # end
 
+      def return_url
+        # If the request already has a `url` parameter, then it will already be appended to the callback URL.
+        if request.params and request.params['url']
+          {}
+        else
+          { :url => request.referer }
+        end
+      end
+
     end
   end
 end
diff --git a/spec/omniauth/strategies/cas_spec.rb b/spec/omniauth/strategies/cas_spec.rb
index 6e2a07c..cbb60b1 100644
--- a/spec/omniauth/strategies/cas_spec.rb
+++ b/spec/omniauth/strategies/cas_spec.rb
@@ -12,20 +12,34 @@ describe OmniAuth::Strategies::CAS, :type => :strategy do
     }.to_app
   end
 
-  describe 'GET /auth/cas' do
+  shared_examples_for "a CAS redirect response" do
+    let(:redirect_params) { "service=" + CGI.escape("http://example.org/auth/cas/callback?url=#{return_url}") }
     before do
-      get '/auth/cas', nil, { 'HTTP_REFERER' => 'http://myapp.com/admin/foo'}
-    end
-
-    let(:redirect_params) { "service=" + CGI.escape("http://example.org/auth/cas/callback?url=http://myapp.com/admin/foo") }
+      get url, nil, request_env
+    end    
     subject { last_response }
-
     it { should be_redirect }
     it "should redirect to the CAS server" do
       subject.headers['Location'].should == "https://cas.example.org/login?" + redirect_params
     end
   end
 
+  describe 'GET /auth/cas' do
+    let(:return_url) { 'http://myapp.com/admin/foo' }
+
+    context "with a referer" do
+      let(:url) { '/auth/cas' }
+      let(:request_env) { { 'HTTP_REFERER' => return_url } }
+      it_behaves_like "a CAS redirect response"
+    end
+    context "with an explicit return URL", :focus => true do
+      let(:url) { "/auth/cas?url=#{return_url}" }
+      let(:request_env) { {} }
+    
+      it_behaves_like "a CAS redirect response"
+    end
+  end
+
   describe 'GET /auth/cas/callback without a ticket' do
     before do
       get '/auth/cas/callback'
-- 
GitLab