Tuesday 5 October 2021

Properly test a Rails app with shibboleth auth

A Rails app with Shibboleth is not as easy to test as an app with say LDAP authentication. 

Functional tests work, but at a cost: the ENV name changes. In production (mod_passenger) the surname might be 'sn'. In test it is 'HTTP_SN'.

Sometime people write some env-driven if blocks to stub a user's login in development. Each time you need to change user's data you need to fix the controller.

The solution is:

  • outfactor the data fetching from ENV is a custom class;
  • use system test to mock the class above.

Some source code on github shows you the details.

Check the system test:

test/system/login_users_test.rb
The translation class is in:
app/lib

Monday 3 May 2021

Rails6 shibboleth single logout through notify

This is a proof of concept of a Ruby on Rails application with Shibboleth authentication, pure rails session and a working single sign off.

This application follows: SLOWebappAdaptation .

Short things first: it is not worth. There are easier ways to have Ruby on Rails and SAML2 auth to go hand in hand, with single logout included.

The hard part is not the Shibboleth one: you just need to add a Notify

The matter is this setup is completely against a few Rails' conventions:

  • SOAP support has been dropped from Rails since version 1.2;
  • you are not expect to tweak with arbitrary session objects which in turn means:
    • you can't use the trusted cookie session store but you have to switch to the harder database-backed session store, which by the way you need to customize a bit to hold the Shib-Session-ID data;
    • you need to fight against encrypted sessions, the default.

If nevertheless interested, have a look at source code on github.

Sunday 11 April 2021

Shibboleth-Idp4 impersonation: fetch the impersonating user as an attribute.

In the Shibboleth IdP it's possible to enable the impersonation intercept to enable help desk to impersonate users.

The impersonation is an amazing feature very well designed.

You can enable it in three steps:

  • enable the module;
  • add a p:postAuthenticationFlows="#{ {'impersonate'} }" attr to the SAML2 property to the relying party list involved (relying-party.xml);
  • configure it on conf/access-control.xml (legacy configuration file in conf/intercept is useless).

The documentation proposes a workflow where a help desk operator has to be authorized to impersonate johndoe user by adding the johndoe value to a certain operator's attribute.

If your requirements allow any help desk operator to impersonate any user, the configuration can be simply:

The impersonation event is logged on the IdP. But if you want to let the SP to know about it, you can leverage the "populate the impersonated principal name into the attached SubjectContext" phase of the module. What you need is a acript that picks the added Subject and turns it to an attribute:

Add it to attribute-resolver.xml:

Of course the attribute format can be embedded in the declaration or be pulled in from a property file in conf/attributes/custom:

Monday 23 September 2019

Italian health insurance card: read some public data.

Since a few years, Italian health insurance card works as a contactless card as well as a smart card.

In both cases informations are presented in a filesystem-like structure similar to Calypso cards.

Apart certificates and keys, on card there are some cardholder's public data that can be handy to read.

I was successful with a ACR122U NFC reader and a ACS ACR38 smart card reader. Both devices access the same data structure where you can find card ID number, cardholder's name, surname, taxpayer number.

It wasn't easy for me to find the details needed to make sense of data, so I decided to write them in a tessera_sanitaria GitHub repository.

Wednesday 4 February 2015

Groovy as scripting language in Shibboleth-IdPv3

The default language to write ScriptedAttributeDefinition is EcmaScript, but it's easy to switch to groovy.

First of all download latest groovy, unzip it, locate the groovy-x.x.x.jar and groovy-jsr223-x.x.x.jar and copy the in the webapp/WEB-INF/lib/ dir of the unpacked shibboleth-idp source. Install again shibboleth-idp.

As proof of concept, just rewrite the "email" attribute definition which is, in the distribution attribute-resolver.xml, a template attribute.

Modify attribute-resolver.xml to include:

The included script file is:

Copy it in the $IDP_HOME/script/ directory

In order to test it, just add: <logger name="org.example.idp.scripted.groovy" level="DEBUG"/> to logback.xml, be sure to reload both attribute-resolver (./bin/reload-service.sh -id shibboleth.AttributeResolverService) and logger (./bin/reload-service.sh -id shibboleth.LoggingService), and run a aacli call.

DEBUG [org.example.idp.scripted.groovy.email:13] - value: [a_user@example.org]

Tuesday 27 January 2015

A pure ruby Attribute Authority client

Even if you can query IdP Attribute Authority with resolvertest, and you can test the tiny details with a curl call, a ruby attribute authority client is handy should you desire, for instance, to bulk load the IdP with many parallel requests.

Moreover, the curl approach is very slow because you need to modify the request xml file to put a timely IssueInstant and a unique RequestID.

You can browse the source at the github project page

Tuesday 9 September 2014

SASL/DIGEST-MD5 with OpenLDAP-2.4.39

In order to authenticate users with Digest-MD5 the first choice to do is either store passwords in a file (sasldb2) on ldap server or into directory. The olcSaslAuxprops attribute in cn=config defines the path to follow.

Passwords in salsdb2

Start with:
sudo apt-get install sasl2-bin
than create a user:
sudo saslpasswd2 -c francesco
(script prompts for password and confirm password)
sudo chown openldap /etc/sasldb2
Modify cn=config with the following:
dn: cn=config
changetype: modify
replace: olcSaslAuxprops
olcSaslAuxprops: sasldb
create a map for the user:
dn: cn=config
changetype: modify
delete: olcAuthzRegexp
olcAuthzRegexp: "uid=francesco,cn=digest-md5,cn=auth" "cn=joe,dc=example,dc=org"
The entry cn=joe,dc=example,dc=org can be created later, or not created at all, if you simply need a principal to fulfill a ACL rule.
Restart OpenLDAP in order to apply olcAuthzRegexp (required by mine experience on Debian, OpenLDAP-2.4.39).
Test with:
ldapwhoami -U francesco -H ldapi:/// -Y DIGEST-MD5
SASL/DIGEST-MD5 authentication started
Please enter your password: 
SASL username: francesco
SASL SSF: 128
SASL data security layer installed.
dn:cn=joe,dc=example,dc=org
Type the password choosed in the saslpasswd2 step. If by chance you are logged is as 'francesco', the -U francesco switch can be omitted.

Passwords in directory

Create the joe user:
dn: cn=joe,dc=unimore,dc=it
objectClass: inetOrgPerson
cn: joe
sn: user
uid: joe
description: Just plain Joe
userPassword: joesecret
Rollback the olcSaslAuxprops if you changed it (if not, this step is not necessary as it is the default):
dn: cn=config
changetype: modify
replace: olcSaslAuxprops
olcSaslAuxprops: slapd
Add the olcAuthzRegexp rules to map the MD5-DIGEST username to a directory entry, and you are ready:
ldapwhoami -U francesco -H ldapi:/// -Y DIGEST-MD5
then type the joe's password (joesecret in this example).
  • "client response doesn't match what we generated (tried bogus)" means you typed the wrong password.
  • "generic failure: unable to canonify user and get auxprops" could be either userPassword is not CLEARTEXT or userPassword is not readable by joe user (because of ACLs).
You are not going to do much with MD5-DIGEST without reading: OpenLDAP docs about Mapping Authentication Identities