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.
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.
These beans are as described in the Discovery Service Protocol.
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
<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)
This is the information which the DS provides to the JSP.
The jsp communicates back to the DS via the Mode specific parameters listed above, and:
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.
This information will change in later versions. We expect to have to make substantial alterations to support these changes. |
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.*"%> |
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"; } %> |
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> |
This should be a relatively simple extension of the code samples above. Interested parties are encouraged to add to this code page.