CAS Attribute Support
| Project: | CAS |
| Version: | HEAD |
| Component: | Code |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | needs review |
We've configured our CAS server to include attributes of user objects in the authentication response using the suggestions posted to the cas-user mailing list here http://www.nabble.com/CAS-attributes-and-how-they-appear-in-the-CAS-resp... . We'd like to include these attributes in the Drupal database and update them on each authentication in the case of changes. We've extended phpCAS to include two additional functions, getAttribute and getAttributes for the purpose of returning attribute values included in the auth response to applications. These changes to phpCAS are available here: http://github.com/adamfranco/phpcas/zipball/AttributeSupport . Also, the latest update of phpCAS includes a getAttributes function to return attributes from SAML and we plan to submit a patch to that project to extend that function to work with CAS responses as well. We have additional documentation on our changes available here: https://mediawiki.middlebury.edu/wiki/LIS/CAS
The attached patch extends the administration form to include four additional fields: one to turn on attribute support and three for each of the attributes to map to the uid, name, and mail fields in the Drupal database. After enabling attribute support, you enter the name of the attribute field from the CAS response into each of these fields. You can also assign multiple attributes to a field by entering them as a comma separated list which is translated to a space separated (by default) value in the database field (e.g. FirstName,LastName would be entered as Ian McBride in my case). None of these fields appear unless the phpCAS::getAttributes method exists, nor should any other operations of the module be affected in that case.
We're running this against CAS 2.0 with a rather recent version of phpCAS and haven't been able to test against previous versions.
(Also, this is my first code submission to a contrib module, so let me know if I messed anything up).
| Attachment | Size |
|---|---|
| cas-00.patch | 5.96 KB |

#1
This looks great. We just moved to CAS3 and our starting to use release attributes and I just began testing phpcas 1.1 which has a getAttributes method. So in theory this should work with phpCAS 1.1. I'm going to try and look at this very soon and hopefully have a good review.
#2
Let's start out with a re-roll to allow for some changes.
#3
How is name supposed to be used? I don't think in a default installation of drupal do we have a place for a full name of the user.
#4
You can use the drupal name field if you don't have drupal be the user repository, and automatically change the name of the user. The load third party stuff should find the user in a way that's sane. So you could use $user->name for the full name. That would be nice since $user->name is displayed as the field. The patch should definitely check to make sure that the CAS settings are right before mucking with $user->name .
I'm with redndhead, that I don't think we should just be concatenating attributes onto the end of cas_name. That seems like a mistake. I'd like to see these attributes loaded into the user object in some kind of standard way so that they could be used by the
theming layer.
One way to accomplish this would be to store the attributes in a session variable that got loaded all the time? However, It would be nice to see the ability to update matching profile fields with the profile module enabled, so that these values persist at login time.
Do I understand this correctly that this patch will work against Relase 1.1 of phpCAS and no longer requires a hacked version of that library?
#5
Either CAS 3 or phpcas loads the attributes in a session variable called attributes.
#6
I'm working on this today so metzlerd, i.mcbride if you are on IRC ping me. I currently have the admin area enumerating all profile module fields if the profile module is enabled, so we can populate profile fields as users sign on. We can add support for other modules as they come up.
I think drupal supports numerous ways of changing the display name. I think we should support those modules and not implement our own for now at least.
i.mcbride: I'm going to remove the concatenation for now. I would love to hear your feedback on how your implementation works for you and how removing concatenation will affect your sites.
#7
Sounds great redndahead. We may want to break up the profile administration to a separate tab. The admin settings screen is getting kind of cluttered. Feel free to start the tab creation, and I'll work on reorganizing the administration at a later date.
Do you have some examples of modules that alter display names that I can browse?
Rednhead, are you thinking of role syncronization with this? I'd love to eventually drop the LDAP integeration support from CAS and this might be a great step in that direction. Sent you a message via your contact form about how to get ahold of me. But will be monitoring this queue as well.
Thanks for the work!
Dave
#8
Here is a newer version with these changes
* Name and Concat pieces removed. We can add that back in easily if necessary. This may need more thought.
* Added support for the profile module. You can map attributes from the CAS to the profile modules fields.
* Added support for SAML_VERSION_1_1. For some reason I don't receive any attributes without using this. It may be just on my end, but I went ahead and added that option.
That should be it.
@metzlerd, Auto-assigning roles based on attribute could be done, but the role would already have to exist. This would need more thought as it's not necessarily a 1 to 1 relationship as profile fields are.
#9
There is a bug in this one. I think I needed to keep cas_attributes_name and not cas_attributes_uid. The problem I'm having is it's not setting the email address correctly. Any insight as to why that may be would be helpful.
#10
the following code looks wrong to me:
<?php$cas_uid = "name";
if ($cas_attributes && $cas_attributes_uid) {
if ($cas_authmap) {
$cas_uid = "init";
}
else {
$cas_uid = "uid";
}
}
?>
What the devil is "init" ? That's not a valid loadable username attribute. I think the dynamic attribute naming is confusing. I'd rather just see an if then. It's not like there are a large number of ways that you can execute user_load. It needs either a name or a uid, end of story. I'd like to see this snippet of code changed as well:
<?php$user = user_load(array($cas_uid => $cas_name));
?>
#11
I've killed the first block of code in my latest version. I'm still rummaging through this, but I'll send something up once I get email working.
#12
Alright here is another one. My email problem was because I wasn't actually getting the attribute. CAS 3.3 it's a little bit of a pain to configure.
#13
There is a bug with saving profile fields that don't have attributes. user_save() erases them unless you update them in the table. I don't quite have time to write a patch at the moment, but here is the actual code change.
// We need to re-add profile values after save. Fixes issue where
// user_save() erases profile values.
if (module_exists('profile')) {
$profile_fields = db_query('SELECT `fid`, `name` FROM {profile_fields} ORDER BY `weight` ASC');
if ($profile_fields != FALSE) {
while ($row = db_fetch_array($profile_fields)) {
$profile_values[$row['fid']] = $user->$row['name'];
}
}
}
$user = user_save($user, $user_up);
// Add our profile module values.
if (module_exists('profile')) {
foreach ($profile_values AS $fid => $value) {
db_query("UPDATE {profile_values} SET value = '%s' WHERE fid = %d AND uid = %d", $value, $fid, $user->uid);
}
$user = user_load($user->uid);
}