Purpose
ILS Authentication is a framework for authenticating users of a Drupal site against Integrated Library Systems. Each ILS requires a 'driver' to work with this module. A driver is an .inc file that connects to the ILS, queries its user database/API, and returns to the ILS Authentication module:
- a TRUE or FALSE value (depending on whether the current user credentials authenticate against the ILS); and
- optionally, an email address from the ILS account.
Since ILS Authentication uses standard hooks to integrate with Drupal's account registration and authentication subsystems, existing and new local Drupal accounts (i.e., those created by the core user module) and accounts created by other contributed modules are unaffected by this module.
Site admins who install ILS Authentication must select which driver to use. The 'sample' driver is installed by default. Only one driver can be active. The module only supports authentication against a single external source.
Please note that this module will create accounts for users if they authenticate against the configured external source, regardless of whether the site administrator has choosen "Visitors can create accounts and no administrator approval is "required" under "Public registrations" at admin/user/settings. Local Drupal accounts are governed by the this setting as usual.
Features
- supports new authentication sources by using 'drivers', which are PHP .inc files that contain only a few functions (documented below). This modular approach allow new drivers to be added without needing to modify the .module file.
- allows drivers to
- add their own admin settings
- modify Drupal forms for their own purposes, such as the login form or the module settings form
- perform their own validation on the login form
- allows site admins to
- tell users (when they log in) that they must add an email address to their profile, since not all external authentication sources can provide an email address for the user.
- define driver-specific messages to be displayed when an external user requests a new password, and also to be displayed in external users' account pages. Since external users may not have email addresses (something core Drupal does not allow), external users do not receive an email when they request a new password. Instead, they see a driver-specific message telling them where to change their password (i.e., at the remote ILS). Drupal's default behavior of sending an email to users requesting new passwords still applies to local accounts.
- define default roles for user accounts created with this module.
- log usernames/passwords routed to external sources. This feature is intended to assist driver developers and should be turned off at all times other then during testing and debugging.
Prerequisites
The module itself has no particular PHP, database, or Drupal requirements, other than it only works with Drupal 7.x.
Certain PHP configuration options must be enabled to allow drivers to connect to their authentication targets. For example, if a driver connects using a URL, file_get_contents or cURL must be enabled, depending on how the driver is written.
More information on the Project Page
Git access:
git clone --branch master http://git.drupal.org/sandbox/jsherman/1418010.git ilsauthen
Miscellaneous
The 6.x version of this module was developed by Mark Jordan, who will be a co-maintainer of this project.
See the 6.x version here
I updated the module for 7.x and added a sip2 driver based on John Wohlers' GPL3 php-sip2 class library, which is included in this module, but may also be downloaded separately through svn:
svn checkout http://php-sip2.googlecode.com/svn/trunk/ php-sip2-read-only
| Comment | File | Size | Author |
|---|---|---|---|
| #13 | drupalcs-result.txt | 6.17 KB | klausi |
Comments
Comment #1
jsherman commentedThe markup warning for drivers/iii.inc is a false positive. The driver is parsing information from an external API that outputs uppercase HTML-style markup.
Review of the 7.x-1.x branch:
This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. Get a review bonus and we will come back to your application sooner.
Source: http://ventral.org/pareview - PAReview.sh online service
Comment #2
jsherman commentedComment #3
Robertas commentedReview of the 7.x-1.x branch:
Run coder to check your style, some issues were found (please check the Drupal coding standards). See attachment.
This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. Get a review bonus and we will come back to your application sooner.
Severity minor, Drupal Commenting Standards, Internationalization, Drupal Security Checks, Drupal SQL Standards, Drupal Coding Standards
sites/all/modules/pareview_temp/./test_candidate/drivers/iii.inc:
+104: [minor] use lowercase html tags to comply with XHTML
+108: [minor] use lowercase html tags to comply with XHTML
Status Messages:
Coder found 7 projects, 7 files, 2 minor warnings, 0 warnings were flagged to be ignored
Source: http://ventral.org/pareview - PAReview.sh online service
Comment #4
klausiNo manual review given, and the minor coding style issues do not justify the "needs work" status.
The response time for a review is now approaching 4 weeks. Get a review bonus and we will come back to your application sooner.
Comment #5
jsherman commentedComment #6
firebird commentedReview of ILS Authentication:
Licensing:
- File /drivers/sip2_class.inc appears to be a 3rd party library. These should not be included in Drupal modules. Instead, you should add instructions in the modules installation instructions on how the users may download the library. See http://drupal.org/node/422996 .
Module duplication
- Surprisingly, I can't seem to find a module that does external authentication in a modular way. There are a lot of modules that do _one_ kind of external authentication. A modular approach would reduce the amount of duplicated code in the contrib module space. Have you considered making your module more generic? As it is, the module seems to be aimed only for ILS integration, but it looks to me like it would work with just about any external authentication source.
Drupal APIs
- In ilsauthen.module, you're including the driver file with a call to module_load_include() in the global context. You shouldn't do that.
- In function ilsauthen_savesettings_js, you may want to leave the div-markup outside the translated string. Instead of this:
Do this:
See http://drupal.org/node/322774 .
Security
- No immediate problems found, but I didn't go into that much detail. Being an authentication module, an in-depth security review should be done.
Drupal coding standards
- Some minor problems found with PAReview:
Code documentation
- The code is well documented.h2
Comment #7
jsherman commentedFirst of all, thank you so much for taking the time to look at our project! I've addressed your input on a per-section basis below:
Licensing
The SIP2 class is indeed third-party GPL code, but it is not "easily accessible" as defined here:
http://drupal.org/node/66113
I interpreted that as making it eligible for an exception. It wasn't clear to me that I can ask for and be granted an exception for this before ILS Authentication becomes a full project. If you think that I should be pursuing an exception while still in sandbox, then I will.
Module duplication
I see positioning the project more broadly as a down-the-road possibility. There is no techical reason preventing somebody from writing a driver that authenticates against non-library-related services. Positioning the project as library-related has more to do with the technical expertise of the project maintainers and the group of people we are setting out to help. We're librarians trying to help other librarians integrate software and services. Positioning the project more broadly right now might keep us from doing what we do best.
Drupal APIs
Thanks for the advice! Implemented.
Security
Makes sense to me.
Drupal coding standards
Based on klausi's posts, I gather that minor coding issues aren't blockers for approval. The symphony driver was contributed to this project by another librarian, and I have already worked with him to get rid of all of the non-minor issues.
The warnings for the iii driver are more of a false positive; the driver is simply consuming a service that outputs this style of markup.
Comment #8
jsherman commentedComment #9
firebird commentedWell, this reviewing thing is new to me, so don't take me as the final authority on the subject. But:
Licencing
"Download the SIP library from here http://php-sip2.googlecode.com/files/sip2.class.php and add it to your /sites/libraries/ directory ".
That's easily accessible in my book. Unless the version there isn't the right one? The file is listed as deprecated, so maybe the source in SVN is a more recent version?
Drupal coding standards
Not a blocker, no, but I see no reason to fix them anyway.
Comment #10
jsherman commentedYeah, there isn't packaged release, just the library file sitting in SVN. It doesn't really have accompanying documentation, and given that there is only a single deprecated download that hasn't been touched since 2008, it doesn't seem to be maintained. Also, I've altered the code to use Drupal's sanitized versions of PHP functions where available. I think those are good arguments for including the library.
At this point, I feel that I have fully communicated why I think the library should be included. I understand why you believe the library should be excluded. If you still feel certain that this issue is a blocker, then I will respect your opinion and make the change. Given the time that this project has spent in the queue, my primary goal is at this point is to move things along.
I appreciate you taking the time and effort to review this project.
Comment #11
firebird commentedThat sounds like valid reasoning for including the library, so I don't think that should be a blocker.
Comment #12
lucascaro commentedsetting to critical since it's been waiting for a review for more than 5 weeks.
Comment #13
klausiSorry for the delay, but you have not listed any reviews of other project applications in your issue summary as strongly recommended in the application documentation.
Review of the 7.x-1.x branch:
This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. Get a review bonus and we will come back to your application sooner.
manual review:
Comment #14
jsherman commentedI have dealt with these issues, to the best of my knowledge.
Comment #15
mpdonadioThere is still a master branch, make sure to set the correct default branch: http://drupal.org/node/1659588 . Then remove the master branch, see also step 6 and 7 in http://drupal.org/node/1127732
Can't test this, so this is a code walkthrough of 7.x-1.x
ilsauthen_uninstall() does a wildcard delete from {variable}. The will cause problems if the module is ever sub-moduled in the same namespace.
You may want to consider using your own permission instead of 'administer users' for the admin tasks.
ilsauthen_login_validate(), ilsauthen_user_login(), etc, are using db_select() without using the return values???
Comment #16
jsherman commentedMatthew, I really appreciate the review. I need the help.
Default branch is now 7.x, master branch is removed.
Regarding the uninstall: This module is designed to have user-contributed drivers, and this seemed like the obvious way to clean up whatever variables they might use. I suppose drivers could use variables beginning with 'ilsauthen_driver_' or something similar, and to a wildcard cleanup on those. Then I could individually remove variables that the main module uses. Does that seem like a reasonable way to handle that, or is there an even better way?
The 'administer users' permission seemed like an obvious choice to me since this is an authentication module, but this does obviously expose configuration details from other systems. I'll think on that one.
All of those db_selects were part of a failure on my part to wrap my head around the db abstraction stuff. I'm trying to stop thinking the D6 way. I think I've got that pretty well sorted now.
Comment #17
rudiedirkx commentedJust a few minors:
require_once DRUPAL_ROOT ...withmodule_load_include(). No drupal_get_path necessary then.ilsauthen_driver_connect()you usefile_get_contents()to do a HTTP request. Some (many) servers don't support that (allow_url_fopen). I suggest usingdrupal_http_request()or cURL.so with extra white-space for 'next lines', so it's more obvious where the command starts and ends.
ilsauthen_login_validate()) If that was exactly your intention, sure, but it seems a little unsafe. Log tables usually don't contain the sensitive stuff.Implements ...().isn't 'allowed'. I'm talking aboutilsauthen_form_alter(). Put it on the next line (with an empty between) to make the whole more readable. Details.db_query()statements really necessary? They're messy.Looks very good overall! I didn't do a Pareview check, but I like to think I know what I'm talking about.
Comment #18
jsherman commentedrudiedirkx,
Thanks for the review. I have implemented all of your suggestions in the 7.x branch. I'll backport the applicable changes to 6.x soon. The code is more legible and less fragile thanks to your advice. Also, while the option to log users/passes was helpful while tinkering in development, it probably isn't an awesome feature to ship on a module distributed through drupal.org.
Comment #19
rudiedirkx commentedReally all I can think of that's imperfect now is the very, very long comment on line 251 for
ilsauthen_query_driver().Oh and 2 missing spaces before
'pass' => $_hashed_pass,but now I'm just trying.All of it looks really, really good. I haven't actually tested it though, so I don't think I'm allowed to rtbc.
Comment #20
rudiedirkx commentedI don't get it... How does a user end up in {authmap} so it's actually validated through a driver..? I'm adding myself manually and creating a custom driver now. Let's testdrive this badboy!
Comment #21
jsherman commentedIf they aren't in authmap then its up to the driver to either tell us to register the user or tell us that it's a bad login. user_external_login_register calls user_set_authmaps which sticks the account in {authmap} upon registration.
Comment #22
rudiedirkx commentedBut how does an external service know when to register a user? He can't register ALL users that don't have an account... Then how would the service know the user's mail?
$form['logging_warning']should contain#markup, not#valueand the message should probably be a warning, not an error.The "Driver" dropdown in the admin form tries to load something with Ajax.... but doesn't. Why the message? Why not always load it and show it with Javascript?
You're using the driver's validation function only AFTER calling the connect function (so querying the API), which seems silly... The validation function checks user input, so it doesn't have to send it to the API, right?
In iii.inc's
ilsauthen_driver_connect()you're assuming the result ofdrupal_http_request()is a string. It's not. Ever. It's an object where->datais the response body, but you should also check->code.Comment #23
rudiedirkx commented'Everything breaks' if I have Drupal create a user with a username that already exists in Drupal.
I'm Jaap and I have a My Service account (username "jaap"), but not a Drupal account. Another Jaap does have a drupal account (username "jaap_102"). Jaap logs in with My Service and Drupal wants to create an account for him with username "jaap", because that's his My Service username. Auch.
I'm not sure it's an edge case that you want to always handle, but the gross errors should be handled. My guess is somewhere in
ilsauthen_authenticate().Also, the watchdogs are very useful, but should be labeled "ilsauthen", not "user".
Comment #24
rudiedirkx commentedE-mail check in
ilsauthen_user_login()doesn't work, because you're checking if aquery->execute()is empty and it's never, because that returns aDatabaseStatementBaseobject. Check for the field value by adding->fetchField()OR just check the$accountargument...Also, the message will be clearer (to translate) if you add all the text in one string (instead of 2, with an
l()call):Please add your email address to <a href="@url">your profile</a>.@urlshould then be a fully qualified url (usingurl()).And I don't think the comment above applies anymore..? "Show the message on every page except user/xx/edit, since ...."
Good thing I did testdrive it =)
Comment #25
jsherman commentedWell, crud! It looks like I have some homework to do...
Comment #26
jsherman commentedRudie,
Thank your for your testing and your feedback. In addition to fixing many of my silly mistakes, I've done quite a bit of work on the email handling front (thanks sambonner for pointing out your need for more functionality).
As for colliding usernames, I've added a warning into the optional logging when we pick up a uid with an authmap entry for some other module. Since they would be coming through our form, I imagine that would catch users who were registered my another auth module that is now turned off. I'm not really sure what more there is to do on that front. I suppose I could try to authenticate them against our module anyway to see for sure that we have a username collision, but that seems rude and messy.
Speaking of logging, I was thinking of making at least the email collision logging mandatory instead of optional. Also, think I might switch it back to usernames instead of uids since that is how drupal's inbuilt logging reports user stuff.
Comment #27
rudiedirkx commentedA quick glance (it needs more reviewing):
* The $form agument in validation handlers isn't usually by-reference. It can be (apparently, I didn't know until just now), but usually isn't.
*
} else {isn't according to the coding standards.* Why all the
absolute => trueinurl()?Comment #28
jsherman commentedThanks for taking a look
1) I'm using a form reference in validation to prevent user_login_submit from being called twice, which I noticed while I was working on logging. It's an issue another auth modules seems to deal with similarly. See:
http://drupal.org/node/1177868
Still, it wasn't very obvious, so I shuffled things around to make it more clear what's happening there.
2) styling from a non-drupal project seeping in. Fixed.
3) Leftovers from playing with the different url() options. Gone now.
Comment #29
rudiedirkx commentedI like it. Better than many existing modules out there.
Always keep in mind Drupal modules must be extendable, so add
drupal_alters andmodule_invoke(_all)s wherever it's useful. (And don't forget to cache it.) In this case that might be using a_infohook to collect auth adapters/drivers instead of scanning a folder. Without it would be fine for a v1 though IMO.Now it's up to the big dogs to review and approve your module/pro status.
Comment #30
rudiedirkx commentedActually there's a few minors from PAReview:
Only the one about "If this is a new mail" is important IMO. The comment is on the wrong line I think. It should be inside the next
elseblock, a few lines later.You can use PAReview yourself online: http://ventral.org/node/562/repeat
Comment #31
jsherman commentedThanks rudiedirkx,
I'll have a look at that. I actually have made some additional logging changes that I need to push as well, so I'll do those as well as the comment fixes in one go later this week.
Comment #32
jsherman commentedI've pushed my changes to logging and cleaned up comments as well. Currently getting 0 PAReview errors. Thanks for your feedback Rudie, it has been truly constructive criticism. You can bet that I'll be researching your suggestions for improved extensibility and performance.
Comment #33
jthorson commentedjsherman,
Apologies for bringing this full circle back to where it started ... but I've asked a few people, and so far, the general consensus is that inclusion of the sip2_class.inc file inside your module would be in contravention of the licensing guidelines. The motivation behind this opinion is that all code hosted on Drupal.org is carried under a GPLv2 license; and the sip2_class.inc was originally released as GPLv3. I'm told that moving from GPLv3 to GPLv2 is considered a license incompatibility (though the other way would be acceptable).
The next step therefore become i) contacting the author and asking if they would release the code as GPLv2, or ii) leave the code out, and give end users instructions as to where to obtain it, as firebird suggested in comment #9.
Otherwise, the excellent reviews by rudiedirkx look to have addressed any other potential concerns, and a quick scan of the code looked okay, other than the message on line 375 of the main module (appears to have a check_plain() in the string body ... and see http://drupal.org/node/322774 for the recommended way to include links in translatable strings) and a generic uneasy feeling about any code that updates user password entries in the db, just on principle. ;)
Setting back to 'needs work' on the licensing issue.
Comment #34
jsherman commentedjthorson,
Thanks for the update. As you have noticed, Rudiedirkx has indeed been a huge help!
Regarding the SIP2 class: I have contacted the author to see if he is willing to re-license under GPLv2. If not, I will follow firebird's advice. If that's the case, I will probably do a fork on github or google code since I have modified the class to take better advantage of the drupal environment.
I will say that as a new contributor I haven't found the documentation on this issue to match up with community expectations. By my reading, I thought this code pretty clearly met the requirements for an exception as written here:
http://drupal.org/node/422996
which seems to indicate that gpl v2 or later is fine for inclusion.
In addition the drupal licensing faq also seems to indicate that gpl v2 or later is fine:
http://drupal.org/licensing/faq#q4
At the same time, I understand that the documentation can't get our project packaged releases on d.o., but you (and fellow reviewers) can.
Regarding the password updating: Old habits die hard, but now is as good a time to break them as any. Is this something I should be doing through user_save?
Comment #35
jthorson commentedThe code might meet the requirements for an exception, but those exceptions are handled at a higher level than you'll find within the project applications queue ... the exceptions need to be explicitly granted (by the webmasters team, perhaps?).
I think (and I'm speculating here) that the "GPLv2+" in the documentation refers to code that is explicitly released as "GPL version 2 or greater" ... The subtle difference is that this wording includes the GPLv2 *and* GPLv3 licenses, and is thus compatible with the drupal.org licensing, whereas an explicit "GPLv3" license is v3 only (and thus not compatible with the drupal.org licensing).
There's been some fluctuation in this policy over the last couple months, but the latest revision of the documentation includes a comment that the research could not find actual evidence that the policy had changed yet ... I suspect that this item will be put forward to one of the Drupal.org governance working groups for an 'official' decision, once they are established later this year.
On the password change, user_save() would be the preferred way to modify the password. Generally, we nudge people to use the available APIs at every opportunity ... which ensures that your module is protected against underlying database changes if they occur (as the API would be updated at the same time). I probably should have stressed that in the review ... but in this case, I missed one. :)
Comment #36
PA robot commentedClosing due to lack of activity. Feel free to reopen if you are still working on this application.
I'm a robot and this is an automated message from Project Applications Scraper.
Comment #37
jsherman commentedYep, definitely still open. I suppose this is as good of a sign as any that I probably won't hear back from the original php-sip2 library any time soon and should therefor go down the external download path to get the module's licensing in good standing.
Comment #38
PA robot commentedClosing due to lack of activity. Feel free to reopen if you are still working on this application.
I'm a robot and this is an automated message from Project Applications Scraper.
Comment #39
jsherman commentedOkay,
I made time to come back around to this project. I have moved the sip2 class file out off of drupal.org and on to github. I created a very straightforward message directing users to the download if they select the sip2 driver. Note that I've only made these changes on the 7.x branch since I'm unsure if this will fly. I'll happily backport if the reviewers think I'm handling this well enough.
Comment #40
kscheirerSetting to needs work for the last 2 points. We only need to review one branch, so just 7.x is fine. Nice module!
----
Top Shelf Modules - Crafted, Curated, Contributed.
Comment #41
jsherman commentedI think I've got something quite a bit better in terms of checking and loading the php library that will also work pretty well for contributed drivers. Basically, I'm only checking the requirements of the currently loaded driver. Pareview complains because I'm defining hook_requirements() in the .module file instead of the .install file, but I'm only interested in the runtime phase since the audience is comprised of other systems librarians who may be adding their own drivers and libraries independently of installing or updating the module. hook_requirements() is used similarly in core via node. I realize I still need to work up the api, but I was hoping to get some feedback on this issue.
Comment #42
kscheirerSeems reasonable, thanks. What kind of feedback are you looking for on the api?
----
Top Shelf Modules - Crafted, Curated, Contributed.
Comment #43
jsherman commentedMy apologies, I was being grammatically unclear. I was hoping for feedback on the way I was using hook_requirements(); it sounds like it didn't raise any red flags, so I'll get a first go at ilsauthen.api.php up tomorrow.
Comment #44
jsherman commentedOkay, I think I've got ilsauthen.api.php handled reasonably well.
Comment #45
klausiSorry for the delay, but you have not listed any reviews of other project applications in your issue summary as strongly recommended in the application documentation.
Review of the 7.x-1.x branch:
This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. You have to get a review bonus to get a review from me.
manual review:
But otherwise looks good!
Thanks for your contribution, jsherman!
I updated your account so you can promote this to a full project and also create new projects as either a sandbox or a "full" project.
Here are some recommended readings to help with excellent maintainership:
You can find lots more contributors chatting on IRC in #drupal-contribute. So, come hang out and stay involved!
Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.
Thanks to the dedicated reviewer(s) as well.