Using CAS to authenticate web service clients

1,287 views
Skip to first unread message

Matt Zukowski

unread,
May 6, 2008, 3:44:22 PM5/6/08
to RubyCAS
This is from correspondence between myself and Christian R. It may be
useful
to others as it describes the general idea behind using CAS to
authenticate
web service clients.

----

Christian,

Using CAS for web services is not something commonly done... often
it's just
easier to bypass CAS for web service requests, and use some local
authentication system instead (for example just HTTP Basic). The CAS
protocol was never designed with web services in mind, so doing it is
a bit
problematic.

Nevertheless, if you insist on doing this, I think you are on the
right
track. The idea is that your client application (the one accessing the
web
service) must first obtain a proxy granting ticket (PGT) from the
proxy
callback. It can then use that PGT to request proxy tickets (PT's) to
be
used with each subsequent request. As you can imagine, this is not
very
practical because you will have to fetch a new proxy ticket for every
single
call you make to the web service (once a PT is used, it can't be used
again).

An explanation of how CAS proxying works in general is available here:
http://www.ja-sig.org/wiki/display/CAS/Proxy+CAS+Walkthrough. I might
be a
good idea to familiarize yourself with the details of this before
proceeding.

Now, in order to use proxying to authenticate your web service client,
you'll have to do something like this:

1. Your client application (the one that will be accessing the web
service)
must log in to the CAS server. You'll want to use the Client itself
for
this, not the Rails framework adapter. You can use the
login_to_service
method to perform a login (
http://rubycas-client.rubyforge.org/classes/CASClient/Client.html#M00...).
It will return a LoginResponse object from which you can obtain the
service
ticket (see
http://rubycas-client.rubyforge.org/classes/CASClient/LoginResponse.html).

2. Now your client application needs to validate the service ticket.
Use the
Client's validate_service_ticket method for this (
http://rubycas-client.rubyforge.org/classes/CASClient/Client.html#M00...).
Make sure that you've configured your client with the proxy callback
URL.
When the validate_service_ticket method is called, it checks whether
your
client is configured with a proxy callback URL, and if so, it asks the
CAS
server during validation to deposit a PGT in the proxy callback.

3. Once your service ticket has been validated, your PGT is waiting to
be
retrieved at your proxy callback URL. You can use the Client's
retrieve_proxy_granting_ticket method to do do this (
http://rubycas-client.rubyforge.org/classes/CASClient/Client.html#M00...).

4. Once you've got the PGT, you can now start requesting proxy
tickets. You
do this using the client's request_proxy_ticket method (
http://rubycas-client.rubyforge.org/classes/CASClient/Client.html#M00...).
This will give you a proxy ticket, which you can then use as a
parameter in
your request to the CAS-protected web service.

Right now this is all theory. It should work, but in practice there
may be
some problems.... in the future I hope to wrap up all this
functionality
into an adapter/plugin for ActiveResource, so that you wouldn't have
to do
all this work yourself.

Hope that helps,
Matt.

2008/5/6 Christian R* <r*@*.* <ro...@bfpi.de>>:

hi matt,

> i suppose i was misunderstanding a lot. now i'm trying this:
> http://pastie.caboo.se/******** <http://pastie.caboo.se/192317>

> though i suppose there is the problem of communicating via https between
> the cas-proxy and the webservice client.

> best regards
> chris

> Mit freundlichem Gruß

> - Christian R* -
Message has been deleted

Dan Coutu

unread,
May 28, 2008, 3:19:04 PM5/28/08
to RubyCAS
I decided to give the theory a try. Here's my test code:

require "rubycas-client"

client = CASClient::Client.new(:cas_base_url => "https://
development.machine.ofmine.com/")

credentials = { :username => "account-test", :password => "letmein"}

response = client.login_to_service(credentials, "https://
development.machine.ofmine.com")

puts "login response:"
puts response.inspect
# The above steps work wonderfully.
# The next step blows up "service" is not defined within the response
object. service_redirect_url is defined.

validation_response = client.validate_service_ticket(response)

puts "validation response:"
puts validation_response.inspect

pgt = client.retrieve_proxy_granting_ticket(validation_response)

puts "pgt response"
puts pgt.inspect

----------end code------

This is my interpretation of the actual code that follows Matt's
written description. But it doesn't work.
I tried to tweak the cas client code so that validate_service_ticket
looks for service_redirect_url instead of service but that just led to
another error complaining that renew is not defined. That should be
okay though because the code does an if check for st.renew that ought
to skip over things if renew is not defined. So something is wrong
with that line. I commented it out to see how much further I could
get.

Now I'm stuck on an error saying that response= is not defined for a
LoginResponse object. I tried to remove the assignments into
validation_response and pgt in the code but that didn't help.

Something is not quite right here.

Dan
> method to perform a login (http://rubycas-client.rubyforge.org/classes/CASClient/Client.html#M00...).
> It will return a LoginResponse object from which you can obtain the
> service
> ticket (seehttp://rubycas-client.rubyforge.org/classes/CASClient/LoginResponse.html).
>
> 2. Now your client application needs to validate the service ticket.
> Use the
> Client's validate_service_ticket method for this (http://rubycas-client.rubyforge.org/classes/CASClient/Client.html#M00...).
> Make sure that you've configured your client with the proxy callback
> URL.
> When the validate_service_ticket method is called, it checks whether
> your
> client is configured with a proxy callback URL, and if so, it asks the
> CAS
> server during validation to deposit a PGT in the proxy callback.
>
> 3. Once your service ticket has been validated, your PGT is waiting to
> be
> retrieved at your proxy callback URL. You can use the Client's
> retrieve_proxy_granting_ticket method to do do this (http://rubycas-client.rubyforge.org/classes/CASClient/Client.html#M00...).
>
> 4. Once you've got the PGT, you can now start requesting proxy
> tickets. You
> do this using the client's request_proxy_ticket method (http://rubycas-client.rubyforge.org/classes/CASClient/Client.html#M00...).

Dan Coutu

unread,
May 29, 2008, 5:01:24 PM5/29/08
to RubyCAS
In the grand tradition of replying to oneself here's code that
actually works in a Rails context.

Begin by creating a controller. Something like this:

script/generate controller autologin

Now edit the controller code to look like this:

class AutologinController < ApplicationController
def index
cas_base = "https://mycas.server.net/"

client = CASClient::Client.new(
:cas_base_url => cas_base
)

credentials = { :username => "account-test", :password =>
"myaccount"}

@response = client.login_to_service(credentials, "https://
mywebsite.server.net")
redirect_to @response.service_redirect_url
end
end

This proves that it works. Now to actually use this you of course
would use a controller name that makes more sense and would
put the above code into an action other than index. The index action
would actually use a view to provide a login form that then submits to
the action that executes the above code.

Dan
Reply all
Reply to author
Forward
0 new messages