DSUIEdit
This section describes what you need to knw in order to change the look and feel of the Discovery Service. To control what is sent to the user interface you should consult DSUserInterface
The look and feel is controlled via a JSP file and an example wayf.jsp
is provided with the standard distribution. This documentation draws on the contents and comments in that file.
Mode specific Beans
The DS can work in two modes. WAYF ("where are you from") or DS (Discovery Service) mode. Although much of the detail available to the jsp is the same in both cases there are a few beans which are specific to each. These beans are usually sent straight back to the DS when the GUI completes.
DS specific beans
These beans are as described in the Discovery Service Protocol.
- entityID The presence of this is used to indicate that the DS is in DiscoverService mode. It should be passed back to the DS as a parameter of the same name.
- returnX This corresponds to the "return" parameter to the DS protocol. It should be passed back to the DS as parameter of the same name.
- returnIDParam This should be passed back to the DS as parameter of the same name.
WAYF specific beans.
The beans are the same as the parameters to the AuthnRequest message. They need to be returned as parameters of the same name. They are
- shire
- target
- providerId
- time (optional)
Example jsp sequence to call back to the DS as part of a <form>
<logic:notPresent name="entityID" scope="request"> <input type="hidden" name="shire" value="<bean:write name="shire" />" /> <input type="hidden" name="target" value="<bean:write name="target" />" /> <input type="hidden" name="providerId" value="<bean:write name="providerId" />" /> <logic:present name="time" scope="request"> <input type="hidden" name="time" value="<bean:write name="time" />" /> </logic:present> </logic:notPresent> <logic:present name="entityID" scope="request"> <input type="hidden" name="entityID" value="<bean:write name="entityID" />" /> <input type="hidden" name="returnX" value="<bean:write name="returnX" />" /> <input type="hidden" name="returnIDParam" value="<bean:write name="returnIDParam" />" /> </logic:present>
This code is taken from the example wayf.jsp
which also has an example of contructing a URL to pass the request directly back to the SP or IdP (depending on the protocol)
Mode independant Beans
This is the information which the DS provides to the JSP.
- cookieList If this exists it represents the contents of the_saml_idp cookie (possibly filtered to remove IdPs whichcannot serve the SP). It is a Collection of IdPSite objects,which themselves have the following properties:
- name The uri for the IdP, which needs to be returned to the WAYF in the origin parameter.
- displayName User friendly name (taken from its alias)
- addressFor The (ungarnished) URL for the IdP. This could be used to create a direct hyperlink to the IdP
- sites If this exists it contains all the possible IdPs for the SP (possibly filtered). It is a Collection of IdPSite Objects which are described above. This is only present if provideList was defined true in the configuration.
- siteLists If this exists it contains all the possible metadata files which can service for the SP (possibly filtered). It is a collection of IdPSiteSetEntry Objects which have two properties:
- name This is the displayName from the Metadata element in the WAYF configuration file
- sites This represents the IdPs. Again it is a collection of IdPSite Objects. It is only present if provideListOfList was defined true as described in DSUserInterface.
- singleSiteList if this is present, then there is only one IdPSiteSetEntry Object in siteLists.
- searchresultempty If this is present then it means that a search was performed, but no suitable IdPs were returned.
- searchresults If this is present it represents the list of IdPs which matched a previous search. It is a Collection of IdPSite Objects described above under cookieList.
Other parameters the JSP has to pass back to the DS
The jsp communicates back to the DS via the Mode specific parameters listed above, and:
- action what the Ds has to do. Possible contents are:
- lookup - refresh the screen.
- search - perform a search on the contents parameter "string"
- selection - redirect to the IdP with the uri origin
- cache preserve any selection in the _saml_idp cookie. A value of "session" makes the cookie last for the browser session, "perm" gives it the lifetime asd as described in DSUserInterface.
Accessing the metadata extension for login and discovery
As a side-effect of updated the supporting libraries in the V1.1.3 release the DS can access the information described in <mdui:UIInfo>
extensions, as described here
This is relatively complex and requires confidence with Java programming, JSP deployment and a reasonable working knowledge of the OpenSAML support for metadata.
The following describes some “recipes” for accessing this information in V1.1.3.
Warning
This information will change in later versions. We expect to have to make substantial alterations to support these changes.
These code segments are provided as is. Remember this is not a supported interface.
Importing the required libraries
The code segment below requires that certain packages are declared:
<%@ page language="java" import="java.util.*, edu.internet2.middleware.shibboleth.wayf.*, java.lang.*, org.opensaml.xml.*, org.opensaml.saml2.common.*, org.opensaml.saml2.metadata.*, org.opensaml.samlext.saml2mdui.*, javax.servlet.http.*, java.net.*"%>
Locating the MDUI information for the SP
In non-error cases, an object representing the SP is available via the attribute named “providerObject”. The code section below shows how to access the SP, and navigate to find the <mdui:DisplayName>
and <mdui:Logo>
. Note that no filtering for size or language is being applied.
Finally, if no name is located, the entity name is inspected to try to generate a “user friendly” display name for the SP.
<% String spName = null; String spLogo = null; EntityDescriptor sp = (EntityDescriptor) request.getAttribute("providerObject"); if (null != sp) { List<RoleDescriptor> roles = sp.getRoleDescriptors(); for (RoleDescriptor r:roles) { Extensions ex = r.getExtensions(); if (null == ex) { continue; } List<XMLObject> splist = ex.getOrderedChildren(); for (XMLObject o:splist) { if (o instanceof UIInfo) { UIInfo info=null; info = (UIInfo) o; if (info.getLogos() != null) { for (Logo logo : info.getLogos()) { if (logo.getHeight() <= 16 && logo.getWidth() <= 16) continue; if (null == spLogo) spLogo = logo.getURL(); break; } for (DisplayName dn : info.getDisplayNames()) { if (null == spName) spName = dn.getName().getLocalString(); break; } } } } } if (spName == null) { try { URI uriId = new URI(sp.getEntityID()); String scheme = uriId.getScheme(); if ("http".equals(scheme) || "https".equals(scheme)) { spName = uriId.getHost(); } else { spName = sp.getEntityID(); } } catch (URISyntaxException e) { // // It wasn't an URI. return full entityId. // spName = sp.getEntityID(); } } } else { spName = "Unknown Service Provider"; } %>
Locating all available Logos for the IdPs
As described in the prototype wayf.jsp file the sites are available via the request attribute terms “sites”. The code segment below sets up a JavaScript associative array of icons (logos of size 16x16) and logos selected for best fit (according to the same rules that the Shibboleth EDS uses). Again language is ignored but could be trivially added.
<% double bestRatio = Math.log(80.0/60.0); sites = (TreeSet<IdPSite>) request.getAttribute("sites"); %> <script type="text/javascript"> var theIcons =[]; var theLogos=[]; <% for (IdPSite site:sites) { if (null == site.getExtensions()) { continue; } List<XMLObject> list = site.getExtensions().getOrderedChildren(); UIInfo info=null; for (XMLObject o:list) { if (o instanceof UIInfo) { info = (UIInfo) o; break; } } if (info == null) { continue;} if (null == info.getLogos() || 0 == info.getLogos().size()) { continue;} String logoUrl = null; String iconUrl = null; double curRatio = 0; for (Logo logo : info.getLogos()) { if (logo.getHeight() <= 16 && logo.getWidth() <= 16) { iconUrl = logo.getURL(); continue; } if (logoUrl == null) { logoUrl = logo.getURL(); curRatio = Math.log(logo.getWidth()/logo.getHeight()); continue; } double ratio = Math.log(logo.getWidth()/logo.getHeight()); double him = Math.abs(bestRatio - curRatio); double me = Math.abs(bestRatio - curRatio); if (him > me) { logoUrl = logo.getURL(); curRatio = ratio; } } if (logoUrl != null) { %> theLogos['<%=site.getName()%>']='<%=logoUrl%>'; <% } if (iconUrl != null) { %> theIcons['<%=site.getName()%>']='<%=iconUrl%>'; <% } } %> </script>
Accessing other information
This should be a relatively simple extension of the code samples above. Interested parties are encouraged to add to this code page.