After quite a bit of staring at the code, I'm becoming convinced that the Shibboleth plugin (and in fact the whole implicitAuth category) is not for us. It appears (please correct me!) that enabling implicit login DISables username/password login. I can't have that -- we have many external users who will never be known by our internal SSO service.
Here's the way I think it ought to work. Somebody tell me if I'm nuts:
When a user comes to the login page (LoginHandler::index()) the Handler should test whether the user has an implicit login ticket. (CAS can do this; I don't yet know whether Shibboleth can, but don't see how it could not.) That is, call HookRegistry::call() for a new hookName that names this test. If true is returned, realize the OJS login by looking up the user and setting the session attributes appropriately. (I'm leaving out the case that an implicitly authenticated user is not yet known to OJS, for simplicity, but I know it has to be handled).
Otherwise, present the login page with a "slot" for each enabled login method. SSO methods would present just a link or a button; token or biometric methods would prompt for the appropriate action ("If you want to use a smart card, insert it now."); the built-in username/password method would present its existing controls. The user has to choose one, but this really needn't require any more action than the existing login form already does.
I haven't yet worked out how login methods provide their UI "slots" to the login page, but the templating system ought to be a big help.
To reproduce the current Shibboleth behavior, one would need a way to disable the built-in login method. That's what the "enable implicit login" configuration item really does, that wasn't available before.