+
+
+
+
+
+ #springMessageText("hello-world.greeting", "Greetings"), $encoder.encodeForHTML($subjectContext.getPrincipalName())
+ Authenticated by
+ #foreach ($result in $subjectContext.getAuthenticationResults().entrySet())
+ $encoder.encodeForHTML($result.getKey())
+ #end
+
+ Java Principals in Subjects
+ #foreach ($s in $subjectContext.getSubjects())
+ #foreach ($p in $s.getPrincipals())
+ $encoder.encodeForHTML($p)
+ #end
+ #end
+
+ #if ($attributeContext && !$attributeContext.getUnfilteredIdPAttributes().isEmpty())
+
+ Attributes
+ #foreach ($a in $attributeContext.getUnfilteredIdPAttributes())
+ #if (!$a.getValues().isEmpty())
+ $encoder.encodeForHTML($a.getId())
+ #foreach ($v in $a.getValues())
+ $encoder.encodeForHTML($v.getDisplayValue())
+ #end
+ #end
+ #end
+ #end
+
+
+ #springMessageText("hello-world.reload", "Reload the Page")
+
+
+
+
+
diff --git a/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/client-storage/client-storage-read.vm b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/client-storage/client-storage-read.vm
new file mode 100644
index 0000000..1afe818
--- /dev/null
+++ b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/client-storage/client-storage-read.vm
@@ -0,0 +1,48 @@
+##
+## Velocity template to read from local storage.
+##
+## Velocity context will contain the following properties
+## flowExecutionUrl - the form action location
+## flowRequestContext - the Spring Web Flow RequestContext
+## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl)
+## profileRequestContext - root of context tree
+## loadContext - context with details about the storage keys to load
+## encoder - HTMLEncoder class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## environment - Spring Environment object for property resolution
+#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service"))
+#set ($titleSuffix = $springMacroRequestContext.getMessage("idp.client-storage-read.suffix", "Loading Session Information"))
+##
+
+
+
+
+
+ $title - $titleSuffix
+ $springMacroRequestContext.getMessage("idp.client-storage-read.text", "Loading login session information from the browser...")
+
+ #parse("client-storage/read.vm")
+
+
+
+
+
diff --git a/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/client-storage/client-storage-write.vm b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/client-storage/client-storage-write.vm
new file mode 100644
index 0000000..066cbdb
--- /dev/null
+++ b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/client-storage/client-storage-write.vm
@@ -0,0 +1,50 @@
+##
+## Velocity template to write to local storage.
+##
+## Velocity context will contain the following properties
+## flowExecutionUrl - the form action location
+## flowRequestContext - the Spring Web Flow RequestContext
+## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl)
+## profileRequestContext - root of context tree
+## saveContext - context with details about the storage data to save
+## encoder - HTMLEncoder class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## environment - Spring Environment object for property resolution
+#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service"))
+#set ($titleSuffix = $springMacroRequestContext.getMessage("idp.client-storage-write.suffix", "Saving Session Information..."))
+##
+
+
+
+
+
+ $title - $titleSuffix
+ $springMacroRequestContext.getMessage("idp.client-storage-write.text", "Saving login session information to the browser...")
+
+ #parse("client-storage/write.vm")
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/error.vm b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/error.vm
new file mode 100644
index 0000000..0f01e89
--- /dev/null
+++ b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/error.vm
@@ -0,0 +1,74 @@
+##
+## Velocity Template for error end-state
+##
+## Velocity context will contain the following variables during controlled errors.
+## Some error paths involve runtime exceptions handled outside Spring Web Flow by the
+## MVC layer and will not generally populate most of these variables.
+##
+## flowRequestContext - the Spring Web Flow RequestContext
+## profileRequestContext - root of context tree
+## encoder - HTMLEncoder class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## environment - Spring Environment object for property resolution
+## custom - arbitrary object injected by deployer
+##
+#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service"))
+#set ($defaultTitleSuffix = $springMacroRequestContext.getMessage("idp.title.suffix", "Error"))
+##
+#if ($flowRequestContext)
+ ## This handles flow events, the most common case.
+ #set ($eventId = $flowRequestContext.getCurrentEvent().getId())
+ #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "error"))
+ #set ($titleSuffix = $springMacroRequestContext.getMessage("${eventKey}.title", "$defaultTitleSuffix"))
+ #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "$defaultTitleSuffix: $eventId"))
+ #if ($eventId == "AccessDenied" or $eventId == "ContextCheckDenied")
+ $response.setStatus(403)
+ #elseif ($eventId == "AttributeReleaseRejected" || $eventId == "TermsRejected")
+ $response.setStatus(200)
+ #elseif ($eventKey == "unexpected" || $eventKey == "runtime-error" || $eventKey == "error")
+ $response.setStatus(500)
+ #else
+ $response.setStatus(400)
+ #end
+#elseif ($exception)
+ ## This handles exceptions that reach the Spring-MVC exception handler.
+ #set ($eventId = $exception.getClass().getSimpleName())
+ #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "error"))
+ #set ($titleSuffix = $springMacroRequestContext.getMessage("${eventKey}.title", "$defaultTitleSuffix"))
+ #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "$defaultTitleSuffix: $eventId"))
+ $response.setStatus(500)
+#else
+ ## This is a catch-all that theoretically shouldn't happen?
+ #set ($titleSuffix = $defaultTitleSuffix)
+ #set ($message = $springMacroRequestContext.getMessage("idp.message", "An unidentified error occurred."))
+ $response.setStatus(500)
+#end
+##
+
+
+
+
+
+
+
+
+
+ #if ($activeIdPSessions)
+ #springMessageText("idp.logout.cancelled", "Logout has been cancelled.")
+ #elseif ($activeSPSessions)
+ #springMessageText("idp.logout.local", "You elected not to log out of all the applications accessed during your session.")
+ #else
+ #springMessageText("idp.logout.complete", "The logout operation is complete, and no other services appear to have been accessed during this session.")
+ #end
+
+
+
+
+ #if ( $profileRequestContext.getProfileId().contains("saml2/logout") )
+
+ #end
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/logout-propagate.vm b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/logout-propagate.vm
new file mode 100644
index 0000000..ab73382
--- /dev/null
+++ b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/logout-propagate.vm
@@ -0,0 +1,57 @@
+##
+## Velocity Template for logout flow's concluding view-state (with propagation)
+##
+## Velocity context will contain the following properties
+## flowExecutionUrl - the form action location
+## flowRequestContext - the Spring Web Flow RequestContext
+## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl)
+## profileRequestContext - root of context tree
+## logoutContext - context with SPSession details for logout operation
+## multiRPContext - context with RelyingPartyContexts and possibly SP UI information from the metadata
+## htmlEncoder - HTMLEncoder class
+## urlEncoder - urlEncoder class
+## codecUtil - CodecUtil class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## environment - Spring Environment object for property resolution
+## custom - arbitrary object injected by deployer
+##
+#set ($hidden = $environment.getProperty("idp.logout.propagationHidden", "false"))
+
+
+
+
+
+
+
+
+
+ #if($hidden == "true")
+ #springMessageText("idp.logout.hidden", "Your single sign-on session has been terminated, but you are still logged into many of the services you have accessed during your session.")
+ #else
+ #springMessageText("idp.logout.attempt", "Attempting to log out of the following services:")
+ #end
+ #parse("logout/propagate.vm")
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/logout.vm b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/logout.vm
new file mode 100644
index 0000000..ab01600
--- /dev/null
+++ b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/views/logout.vm
@@ -0,0 +1,118 @@
+##
+## Velocity Template for logout flow's starting view-state
+##
+## Velocity context will contain the following properties
+## flowExecutionUrl - the form action location
+## flowRequestContext - the Spring Web Flow RequestContext
+## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl)
+## profileRequestContext - root of context tree
+## logoutContext - context with SPSession details for logout operation
+## multiRPContext - context with RelyingPartyContexts and possibly SP UI information from the metadata
+## encoder - HTMLEncoder class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## environment - Spring Environment object for property resolution
+## custom - arbitrary object injected by deployer
+##
+#set ($rpContext = $profileRequestContext.getSubcontext("net.shibboleth.profile.context.RelyingPartyContext"))
+#if ($rpContext)
+#set ($rpUIContext = $rpContext.getSubcontext("net.shibboleth.idp.ui.context.RelyingPartyUIContext"))
+#end
+#set ($promptForIdP = $logoutContext and !$logoutContext.getIdPSessions().isEmpty())
+#set ($promptForSP = $logoutContext and !$logoutContext.getSessionMap().isEmpty())
+
+
+
+
+
+
+
+
+
+
+
Note for deployers: This page is displayed when a logout operation at the Identity Provider completes.
+ This page is an example and should be customized. It is not fully internationalized because the presentation will be a highly localized decision,
+ and we don't have a good suggestion for a default.
+
+
+ #if ($rpContext)
+ #springMessageText("idp.logout.sp-initiated", "You have been logged out of the following service:")
+
+ #if ($rpUIContext)
+ $encoder.encodeForHTML($rpUIContext.getServiceName())
+ #else
+ $encoder.encodeForHTML($rpContext.getRelyingPartyId())
+ #end
+
+
+ #end
+
+ #if ($promptForIdP or $promptForSP)
+ #springMessageText("idp.logout.prompt", "Choose one of the following, or wait a few seconds for the default.")
+
+
+
+ #else
+ #springMessageText("idp.logout.complete", "The logout operation is complete, and no other services appear to have been accessed during this session.")
+
+
+ #end
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/docker/shibboleth-idp/opt-shibboleth-idp/war/.gitkeep b/src/test/docker/shibboleth-idp/opt-shibboleth-idp/war/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/src/test/docker/shibboleth-idp/tomcat/idp.xml b/src/test/docker/shibboleth-idp/tomcat/idp.xml
new file mode 100644
index 0000000..6262af6
--- /dev/null
+++ b/src/test/docker/shibboleth-idp/tomcat/idp.xml
@@ -0,0 +1,3 @@
+