When using Shibboleth, the IdP returns a SAML assertion to the SP. The following examples simply display the results of the SAML assertion. This gives a very brief introduction which shows how your application might consume the information and use it.
Perl ( 2.x version)
#!/usr/bin/perl print "Content-type: text/html\n\n"; print "<html>\n"; print "<head>"; print " <title>Shibboleth Attributes - ".$ENV{SERVER_NAME}."</title>\n"; print " <META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">\n"; print " <META HTTP-EQUIV=\"Expires\" CONTENT=\"-1\">\n"; print <<__ENDJSCRIPT__; <script language"JavaScript" type="text/JavaScript"> <!-- function decodeAttributeResponse() { var textarea = document.getElementById("attributeResponseArea"); var base64str = textarea.value; var decodedMessage = decode64(base64str); textarea.value = tidyXml(decodedMessage); textarea.rows = 15; document.getElementById("decodeButtonBlock").style.display='none'; } function tidyXml(xmlMessage) { //put newline before closing tags of values inside xml blocks xmlMessage = xmlMessage.replace(/([^>])</g,"\$1\\n<"); //put newline after every tag xmlMessage = xmlMessage.replace(/>/g,">\\n"); var xmlMessageArray = xmlMessage.split("\\n"); xmlMessage=""; var nestedLevel=0; for (var n=0; n < xmlMessageArray.length; n++) { if ( xmlMessageArray[n].search(/<\\//) > -1 ) { nestedLevel--; } for (i=0; i<nestedLevel; i++) { xmlMessage+=" "; } xmlMessage+=xmlMessageArray[n]+"\\n"; if ( xmlMessageArray[n].search(/\\/>/) > -1 ) { //level status the same } else if ( ( xmlMessageArray[n].search(/<\\//) < 0 ) && (xmlMessageArray[n].search(/</) > -1) ) { //only increment if this was a tag, not if it is a value nestedLevel++; } } return xmlMessage; } var base64Key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; function decode64(encodedString) { var decodedMessage = ""; var char1, char2, char3; var enc1, enc2, enc3, enc4; var i = 0; //remove all characters that are not A-Z, a-z, 0-9, +, /, or = encodedString = encodedString.replace(/[^A-Za-z0-9\\+\\/\\=]/g, ""); do { enc1 = base64Key.indexOf(encodedString.charAt(i++)); enc2 = base64Key.indexOf(encodedString.charAt(i++)); enc3 = base64Key.indexOf(encodedString.charAt(i++)); enc4 = base64Key.indexOf(encodedString.charAt(i++)); char1 = (enc1 << 2) | (enc2 >> 4); char2 = ((enc2 & 15) << 4) | (enc3 >> 2); char3 = ((enc3 & 3) << 6) | enc4; decodedMessage = decodedMessage + String.fromCharCode(char1); if (enc3 != 64) { decodedMessage = decodedMessage + String.fromCharCode(char2); } if (enc4 != 64) { decodedMessage = decodedMessage + String.fromCharCode(char3); } } while (i < encodedString.length); return decodedMessage; } // --> </script> __ENDJSCRIPT__ print "</head>\n"; print "\n\n<body>\n"; print "<b>-shib-</b><br/>"; print "<table>"; foreach $var (sort(keys(%ENV))) { if ($var =~ m/SHIB/i || $var =~ m/REMOTE_USER/ || $var =~ m/HTTP_REMOTE_USER/) { $val = $ENV{$var}; $val =~ s|\n|\\n|g; $val =~ s|"|\\"|g; print "<tr>"; print "<td>${var}</td><td>${val}</td>"; print "</tr>\n"; } } print "</table>\n"; print "<br/>\n"; print "attribute response from the IdP (<code>HTTP_SHIB_ATTRIBUTES</code>):<br/>\n"; print "<textarea id=\"attributeResponseArea\" onclick=\"select()\" rows=\"1\" cols=\"130\">"; print $ENV{"HTTP_SHIB_ATTRIBUTES"}; print <<__ENDBLOCK__; </textarea><br/> <span id="decodeButtonBlock"><input type="button" id="decodeButton" value="decode base64 encoded attribute response using JavaScript" onClick="decodeAttributeResponse();"><br/></span> <br/> <small> notes:<br/> The AAP throws away invalid values (eg an unscopedAffiliation of value "myBoss@<yourdomain>" or a value with an invalid scope which scope is checked)<br/> The raw attribute response (<code>HTTP_SHIB_ATTRIBUTES</code>) is NOT filtered by the AAP and should therefore be disabled for most applications (<code>exportAssertion=false</code>).<br/> </small> <br/> <hr/> <br/> __ENDBLOCK__ print "<b>-env-</b><br/>"; print "<pre>"; foreach $var (sort(keys(%ENV))) { $val = $ENV{$var}; $val =~ s|\n|\\n|g; $val =~ s|"|\\"|g; print "${var}=\"${val}\"\n"; } print "</pre>\n"; print "<hr/><b>-end-</b><br/>\n"; print "</body>\n\n"; print "</html>\n";
PHP (2.x version)
<script language"JavaScript" type="text/JavaScript"> <!-- function decodeAttributeResponse() { var textarea = document.getElementById("attributeResponseArea"); var base64str = textarea.value; var decodedMessage = decode64(base64str); textarea.value = tidyXml(decodedMessage); textarea.rows = 15; document.getElementById("decodeButtonBlock").style.display='none'; } function tidyXml(xmlMessage) { //put newline before closing tags of values inside xml blocks xmlMessage = xmlMessage.replace(/([^>])</g,"$1\n<"); //put newline after every tag xmlMessage = xmlMessage.replace(/>/g,">\n"); var xmlMessageArray = xmlMessage.split("\n"); xmlMessage=""; var nestedLevel=0; for (var n=0; n < xmlMessageArray.length; n++) { if ( xmlMessageArray[n].search(/<\//) > -1 ) { nestedLevel--; } for (i=0; i<nestedLevel; i++) { xmlMessage+=" "; } xmlMessage+=xmlMessageArray[n]+"\n"; if ( xmlMessageArray[n].search(/\/>/) > -1 ) { //level status the same } else if ( ( xmlMessageArray[n].search(/<\//) < 0 ) && (xmlMessageArray[n].search(/</) > -1) ) { //only increment if this was a tag, not if it is a value nestedLevel++; } } return xmlMessage; } var base64Key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; function decode64(encodedString) { var decodedMessage = ""; var char1, char2, char3; var enc1, enc2, enc3, enc4; var i = 0; //remove all characters that are not A-Z, a-z, 0-9, +, /, or = encodedString = encodedString.replace(/[^A-Za-z0-9\+\/\=]/g, ""); do { enc1 = base64Key.indexOf(encodedString.charAt(i++)); enc2 = base64Key.indexOf(encodedString.charAt(i++)); enc3 = base64Key.indexOf(encodedString.charAt(i++)); enc4 = base64Key.indexOf(encodedString.charAt(i++)); char1 = (enc1 << 2) | (enc2 >> 4); char2 = ((enc2 & 15) << 4) | (enc3 >> 2); char3 = ((enc3 & 3) << 6) | enc4; decodedMessage = decodedMessage + String.fromCharCode(char1); if (enc3 != 64) { decodedMessage = decodedMessage + String.fromCharCode(char2); } if (enc4 != 64) { decodedMessage = decodedMessage + String.fromCharCode(char3); } } while (i < encodedString.length); return decodedMessage; } // --> </script> <b>-all SHIB headers-</b> (<code>HTTP_SHIB_ATTRIBUTES</code> is not shown in this list) <?php echo '<table>'; foreach ($_SERVER as $key => $value) { $fkey='_'.$key; if ( strpos($fkey,'SHIB')>1 && $key!="HTTP_SHIB_ATTRIBUTES") # if ( strpos($fkey,'SHIB')>1 ) { echo '<tr>'; echo '<td>'.$key.'</td><td>'.$value.'</td>'; echo '</tr>'; } } echo '<tr><td>(REMOTE_USER)</td><td>'.$_SERVER['REMOTE_USER'].'</td></tr>'; echo '<tr><td>(HTTP_REMOTE_USER)</td><td>'.$_SERVER['HTTP_REMOTE_USER'].'</td></tr>'; echo '</table>'; ?> <br/> attribute response from the IdP (<code>HTTP_SHIB_ATTRIBUTES</code>):<br/> <textarea id="attributeResponseArea" onclick="select()" rows="1" cols="130"><?php echo $_SERVER["HTTP_SHIB_ATTRIBUTES"]; ?></textarea><br/> <span id="decodeButtonBlock"><input type="button" id="decodeButton" value="decode base64 encoded attribute response using JavaScript" onClick="decodeAttributeResponse();"><br/></span> <br/> <small> notes:<br/> The AAP throws away invalid values (eg an unscopedAffiliation of value "myBoss@<yourdomain>" or a value with an invalid scope which scope is checked)<br/> The raw attribute response (<code>HTTP_SHIB_ATTRIBUTES</code>) is NOT filtered by the AAP and should therefore be disabled for most applications (<code>exportAssertion=false</code>).<br/> </small> <br/> <hr/> <br/> <b>$_REQUEST</b> <?php echo '<table>'; foreach ($_REQUEST as $key => $value) { echo '<tr>'; echo '<td>'.$key.'</td><td>'.$value.'</td>'; echo '</tr>'; } echo '</table>' ?> <br/> <hr/> <br/> <b>$_SERVER</b> <?php echo '<table>'; foreach ($_SERVER as $key => $value) { echo '<tr>'; echo '<td>'.$key.'</td><td>'.$value.'</td>'; echo '</tr>'; } echo '</table>' ?> <br/> <hr/> <br/> <b>$_SESSION</b> <?php echo '<table>'; foreach ($_SESSION as $key => $value) { echo '<tr>'; echo '<td>'.$key.'</td><td>'.$value.'</td>'; echo '</tr>'; } echo '</table>' ?> <br/> <hr/> <br/>
PHP (1.3 version)
<?php <table> foreach($_SERVER as $key => $value) { $fkey = '_' . $key; if (strpos($fkey, 'SHIB') > 0) { echo '<tr>'; echo "<td>$key</td><td>$value</td>"; echo '</tr>'; } } </table> ?>
Perl (1.3 version)
foreach $var (sort(keys(%ENV))) { if ($var =~ m/SHIB/ || $var =~ m/REMOTE_USER/) { $val = $ENV{$var}; $val =~ s|\n|\\n|g; $val =~ s|"|\\"|g; print "<tr>"; print "<td>${var}</td><td>${val}</td>"; print "</tr>"; } }
SSI - Server Side Includes (1.3 version)
<\!\--\#printenv-\->
or
<\!--#echo var="HTTP_SHIB_EP_PERSONPRINCIPALNAME" \-->
ASP (1.3 version)
<table> <% For Each strKey In Request.ServerVariables %> <tr> <td><%= strKey %></td> <td><%= Request.ServerVariables(strKey) %></td> </tr> <% Next %> </table> </table>
JSP (1.3 version)
<u>HEADERS</u><br /> <table> <% java.util.Enumeration eHeaders = request.getHeaderNames(); while(eHeaders.hasMoreElements()) { String name = (String) eHeaders.nextElement(); Object object = request.getHeader(name); String value = object.toString(); out.println("" + name + "" + value + ""); } %> </table>
Similar samples can be found at Katholieke Universiteit Leuven