Background
Please read the operational overview for the SWITCHwayf (page 8) before getting started. It provides some valuable insights into how the WAYF can be called by programs.
HTML Layout
The source:/vendor/SWITCHwayf/1.5/config.php file contains the per-site modifications for the SWITCHwayf. This file also includes all the HTML page layout in 5 function:
The function of printHeader() and printFooter() are self evident for HTML page layout. printHeader() includes in-line CSS to influence layout. The main short comming from our perspective is the page layout is done with tables. Ideally page layout could be templated allowing for any local page construction preferences, a templating tool like [ PHPTemplate] might be a good integration target, but initial work will focus on just modifying the config.php file.
The printWAFY(), printSettings(), and printNotice() functions provide the "content" of the page based on reaction to how the page was invoked.
- printWAYF(): arrive at the page with shib arguments, via a redirect from an SP requesting WAYF service
- printSettings(): arrive at the page with no arguments, letting you save your preferred IdP
- printNotice(): print the currently saved preferred IdP
Note: there are some additional lines starting with the function keyword but they are JavaScript functions included in the HTML output. These functions provide sanity checks for user input and vary
- showConfirmation(): warns the user with an alert before setting a permanent cookie for preferred IdP saving in printSettings(), printNotice() and printWAYF(). The text confirm_permanent_selection is a warning in printSettings() and printWAYF() and permanent_cookie_note an informative note in printNotice().
- checkForm: is used to validate form input on the printWAYF() and printSettings() WAYF selection input
SwitchThemeNotes
Code Walk Through
This WAYF is well implemented and compact. The code is very readable and the logic is well contained in single WAYF file. Given the ease with which it php code can be brought into operation and the cleanliness of this code, it lives up to the promise of a low entry barrier for customization. An overview of the logic flow follows.
- Configuration
- Read config.php
- Read $IDPConfigFile
- Read $languageFile
- Cookie management
- Delete default IdP selection if clear_user_idp posted
- Read previously accessed IdPs
- Read previous accessed SPs
- Add current IdP to list
- Add current SP to list
- Set session or permanent selection preference
- Request Redirection
- redirect the user based on the requested service according to input args and env settings
- Attempt to IdP preselection
- try to guess approapriate IdP based on hints in the request
- Output HTML
- the output the appropriate html accoring to the get/post args
- printWAYF()
- printNotice()
- printSettings()
- the output the appropriate html accoring to the get/post args
The code pretty much follows this layout with utility functions being included after the main logic flow, ie. HTML output.
The subsections provide additional commentary
Configuration
config (gneral, idp, language)
Cookie management
(delete idp select, read previous IdPs, previous SPs, add current idp, add current SP, set remember sate)
Request Redirection
redirect the user based on the requested service according to input args and env settings
Kerberos
The code supports leveraging Kerberos authn contexts to select an IdP. It does this by parsing REMOTE_USER, if it's set to determine the Kerberos realm.
The Kerberos feature could be an interesting way to leverage some default authn attempt loop through one default IdP/SSO so long as that SSO service has a don't prompt the user, just checking for authn type service. This would allow REMOTE_USER to get set for the WAYF which could be used to trigger selection of the IdP. On second thought, this seems like a far to complex approach, given that the main reason for the Kerberos-set REMOTE_USER checking is to determine the realm, ie.IdP, of the user.
Attempt to IdP preselection
try to guess approapriate idp,
Output HTML
All HTML markup is isolated to the print*() functions in config.php. There are two exceptions where minor markup to structure the error message text is generated in the WAYF code. The two places where this markup is generated is for an incomplete shire/target GET argument pair or for an invalid IdP value.
In both cases an error message generated with minor markup code,pre,p,tt and then a call to printError() with the message causes an error page to be generated (with the standard printHeader() and printFooter()).
IdP validation is done in several places through checkIDP(). The IdP is validated against the IdP list from the $IDPProviders list defined in $IDPConfigFile. If the IdP doesn't exist it generates an language specific error message with some paragraph markup. This message also gets sent to printError().
Outside of the message generation and printError it seems the layout and logic are completely seperate.
Triggering the two places where the html markup is contained in the main WAYF code can be done by invoking the WAYF with invalid arguments. There are two types of invalid argument scenarios. Either the target and shire are not both specified or, if they are both specified, the specified IdP (origin) is invalid (doesn't match the IdP list). In most cases the IdP is determined from POST arguments or a redirect cookie, so it's a bit more involved to force this error. But there is a backward compatability mode that allows the origin to be sent as a GET arg, so the error text can be triggered through a simple URL. This is useful for validating the text and look of the error but is unlikely to be the actual scenario that triggers it in production, nontheless it's useful for development.
Triggering the arguments_missing error text can be done by ommiting either the shire or target GET args:
?shire=xxx
Triggering the invalid_user_idp error text can be done by providing an invalid IdP
?shire=xxx&target=yyy&origin=zzz
For a thoughts on isolating all HTML content to the config.php file see the layout and logic separation discussion.
printNotice()
printNotice() comes up if either the user_idp value was posted or if the $redirectCookieName is set. In the layout, if the shire/target get values are also set, it recognizes this as a request in progress and prints the "save and go on" goto_sp message. otherwise it looks just like the user checking their current state and being offered a chance to reset the value. This forcess another form submit during login. One might assume that if the user exposed the settings and selected permanent then this additional confirmation shouldn't come up. It's probably not a bad idea though to avoid accidents.
Pressing reset reloads the request and takes you back to wayf selection. This button might read cancel. (Might a useful option be to have a Don't save but continue on?) Confusion might occur because the settings on mVb login screen won't come up by default, they're hidden. This behavior will remain for now and see how users accept it.
Save and continue basically takes the code through setting the cookie to time+100days because the submitted value of permanent is the text from the button which will cause the isnumber(permanent) test to fail so it goes to the default of now plus 100 days.
Cookie Usage
There are several cookies used by the SWITCHwayf. Most cookie names are defined in config.php. The cookies are used to retain state for remembering a preferred or recently used IdP and SP.
- $redirectCookieName - _redirect_user_idp is set to remember where IdP to automatically select for the user during a login sequence. If this cookie is set then the printNotice() function is triggered and the currently selected IdP is displayed with an option to reset the value. Pressing "Reset" will erase this cookie.
- $SAMLCDominCoookieName = _saml_idp is set to remember the last selected IdP. This is as a convience for pre-selecting the last used IdP during login even if the user chose not to remember the selection. This cookie is not deleted with a reset of $redirectCookieName. It is hard coded to expire after 100 days.
