Search code examples
ruby-on-railsxmljrubycasrubycas-client

rubycas-client XML parsing


When using CAS-client following the instructions, I've reached a point where I've got a positive response from an external CAS server:

CAS server responded with #<Net::HTTPOK 200 OK readbody=true>:

And the XML is like this:

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
  <cas:authenticationSuccess>
    <cas:attributes>
      <cas:user>4oaz8QMucIrlFOU7dr3QpWkqbRY=</cas:user>
      <cas:ccc></cas:ccc>
      <cas:tipo>EDITED_OUT</cas:tipo>
      <cas:acceso>cd</cas:acceso>
      <cas:identificador>EDITED_OUT</cas:identificador>
      <cas:txtBienvenida>EDITED_OUT</cas:txtBienvenida>
      <cas:usuarioValidado>S</cas:usuarioValidado>
      <cas:correo>EDITED_OUT</cas:correo>
      <cas:tlf>EDITED_OUT</cas:tlf>
      <cas:tipoAcceso>2</cas:tipoAcceso>
      <cas:xusuario>EDITED_OUT</cas:xusuario>
      <!-- En caso de que el usuario disponga de certificado digital -->

      <cas:nif>EDITED_OUT</cas:nif>
      <cas:email>EDITED_OUT</cas:email>
      <cas:apellido1>EDITED_OUT</cas:apellido1>
      <cas:apellido2>EDITED_OUT</cas:apellido2>
      <cas:anagramaFiscal>EDITED_OUT</cas:anagramaFiscal>
      <cas:nombre>EDITED_OUT</cas:nombre>

      <!-- Faltan las fechas -->

      <cas:tipoCertificado>EDITED_OUT</cas:tipoCertificado>
      <cas:emisor>EDITED_OUT</cas:emisor>
      <cas:usoCertificado>EDITED_OUT</cas:usoCertificado>
      <cas:apellidosResponsable>EDITED_OUT</cas:apellidosResponsable>

      <!-- Faltan las fechas -->

      <cas:politica>1.3.6.1.4.1.5734.3.5</cas:politica>
      <cas:subject>EDITED_OUT</cas:subject>
      <cas:versionPolitica>45</cas:versionPolitica>
      <cas:organizacionEmisora>FNMT</cas:organizacionEmisora>
      <cas:idPolitica>DEFAULT</cas:idPolitica>
      <cas:numSerie>EDITED_OUT</cas:numSerie>
      <cas:clasificacion>FNMT</cas:clasificacion>
      <cas:tipoAfirma>0</cas:tipoAfirma>
    </cas:attributes>
  </cas:authenticationSuccess>
</cas:serviceResponse>

Then I get this log message from rubycas-client:

Ticket "EDITED_OUT" for service "EDITED_OUT" belonging to user nil is VALID.

And then this error dump:

TypeError (can't dup NilClass):
  org/jruby/RubyKernel.java:1894:in `dup'
  ----CUTTED----

Examining the code, I've come to the conclusion that the error is in filter.rb line 64:

controller.session[client.username_session_key] = st.user.dup

Debugging, I examined the contents of the st object:

(rdb:2) st.is_valid?
true
(rdb:2) st.user
nil
(rdb:2) st
#<CASClient::ServiceTicket:0x7e054262
  @renew=nil,
  @extra_attributes={
    "user"=>"4oaz8QMucIrlFOU7dr3QpWkqbRY="
    "ccc"=>nil,
    "tipo"=>"CIUDADANO",
    "acceso"=>"cd",
    "identificador"=>"EDITED_OUT",
    "txtBienvenida"=>"EDITED_OUT",
    "usuarioValidado"=>"S", 
    "correo"=>"EDITED_OUT",
    "tlf"=>"EDITED_OUT",
    "tipoAcceso"=>"2",
    "xusuario"=>"EDITED_OUT",
    "nif"=>"EDITED_OUT", 
    "email"=>"EDITED_OUT",
    "apellido1"=>"EDITED_OUT",
    "apellido2"=>"EDITED_OUT",      
    "anagramaFiscal"=>"EDITED_OUT",         
    "nombre"=>"EDITED_OUT",
    "tipoCertificado"=>"FNMT PF",       
    "emisor"=>"EDITED_OUT",
    "usoCertificado"=>"EDITED_OUT",
    "apellidosResponsable"=>"EDITED_OUT",
    "politica"=>"1.3.6.1.4.1.5734.3.5",
    "subject"=>"EDITED_OUT",
    "versionPolitica"=>"45",
    "organizacionEmisora"=>"FNMT",
    "idPolitica"=>"DEFAULT",
    "numSerie"=>"EDITED_OUT",
    "clasificacion"=>"FNMT",
    "tipoAfirma"=>"0"
  },
  @service="EDITED_OUT",
  @failure_code=nil,
  @ticket="EDITED_OUT",
  @pgt_iou=nil,
  @user=nil,
  @failure_message=nil,
  @success=true
>

Then, researching the xml parsing and responses.rb, I arrived to this in line 55:

cas_user = @xml.elements["cas:user"]

cas_user is always nil because there is no cas:user element in the XML root, but there's one as child of cas:attributes, thus this:

@xml.elements["cas:attributes/cas:user"]

returns something, in my case, something that looks like a digest of some kind, though I don't know how it's encoded or what info is there.

My question is, if that cas:attributes/cas:user attribute is the one that the client is trying to parse from the XML, or if it's something else. Also, I'd like to know if that XML format I pasted above is CAS-2.0 protocol compliant or if the error comes from a badly-formed XML. It's strange that rubycas-client stores all the "useful data" inside the extra_attributes.

I'm using the following:

Thanks your your help.


Solution

  • cas:user is the netid/principal name that is being returned in the response. Your cas:user output leads me to think the CAS server is using an OAUTH provider. CAS also supports anonymizing the username attribute for specific services so that the service is only guaranteed to get the username each instance. It can be (de)selected in the service registry.

    The CAS 2.0 protocol does not officially support attribute release; only the SAML 1.1 protocol officially supports it. (The forth coming CAS 3.0 client will officially support attribute release.) There is an easy modification that many site implement to allow the CAS 2.0 to release attributes, but sites can implement it however they desire.