[java-identity-provider] 06/11: IDP-2039 - Add audit logging to login flows

Scott Cantor cantor.2 at osu.edu
Tue Jan 3 22:01:46 UTC 2023


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=325c1fbf2f88d10d55849eeb340b31ff1beb6b6b

commit 325c1fbf2f88d10d55849eeb340b31ff1beb6b6b
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Dec 6 16:10:19 2022 -0500

    IDP-2039 - Add audit logging to login flows
    
    https://shibboleth.atlassian.net/browse/IDP-2039
    
    Add auditing to RemoteUser flows.
    Add context cleanup hooks to use with the external variants.
---
 .../idp/authn/context/UsernameContext.java         |  2 +-
 .../impl/AttemptedUsernameAuditExtractor.java      | 10 ++++-
 .../idp/authn/impl/RemoteUserAuthServlet.java      |  9 ++++
 .../authn/impl/ValidateExternalAuthentication.java | 45 +++++++++++++++++++
 .../idp/authn/impl/ValidateRemoteUser.java         | 16 ++++---
 .../idp/authn/impl/ValidateUserAgentAddress.java   | 10 +++--
 .../shibboleth/idp/authn/impl/X509AuthServlet.java |  1 +
 .../idp/flows/authn/remoteuser-authn-beans.xml     | 51 +++++++++++++++++++++-
 .../authn/remoteuser-internal-authn-beans.xml      | 49 ++++++++++++++++++++-
 .../idp/flows/authn/x509-authn-beans.xml           |  3 ++
 .../module/conf/authn/remoteuser-authn-config.xml  |  4 +-
 .../conf/authn/remoteuser-authn-config.xml         |  4 +-
 12 files changed, 184 insertions(+), 20 deletions(-)

diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/UsernameContext.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/UsernameContext.java
index 51719634b..6e6898c3a 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/UsernameContext.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/UsernameContext.java
@@ -32,7 +32,7 @@ import org.opensaml.messaging.context.BaseContext;
 public final class UsernameContext extends BaseContext {
 
     /** The username. */
-    private String username;
+    @Nullable private String username;
 
     /**
      * Gets the username.
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/audit/impl/AttemptedUsernameAuditExtractor.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/audit/impl/AttemptedUsernameAuditExtractor.java
index 8bba75c16..fcc98440b 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/audit/impl/AttemptedUsernameAuditExtractor.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/audit/impl/AttemptedUsernameAuditExtractor.java
@@ -24,11 +24,12 @@ import javax.annotation.Nullable;
 import org.opensaml.profile.context.ProfileRequestContext;
 
 import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.UsernameContext;
 import net.shibboleth.idp.authn.context.UsernamePasswordContext;
 
 /**
- * {@link Function} that returns the username in a subordinate {@link UsernamePasswordContext},
- * if any.
+ * {@link Function} that returns the username in a subordinate {@link UsernamePasswordContext} or
+ * {@link UsernameContext}, if any.
  * 
  * @since 4.3.0
  */
@@ -43,6 +44,11 @@ public class AttemptedUsernameAuditExtractor implements Function<ProfileRequestC
             if (upContext != null) {
                 return upContext.getUsername();
             }
+            
+            final UsernameContext uContext = authnCtx.getSubcontext(UsernameContext.class);
+            if (uContext != null) {
+                return uContext.getUsername();
+            }
         }
         
         return null;
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/RemoteUserAuthServlet.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/RemoteUserAuthServlet.java
index 73d529f53..4ee08888e 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/RemoteUserAuthServlet.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/RemoteUserAuthServlet.java
@@ -39,6 +39,7 @@ import net.shibboleth.idp.authn.AuthenticationFlowDescriptor;
 import net.shibboleth.idp.authn.ExternalAuthentication;
 import net.shibboleth.idp.authn.ExternalAuthenticationException;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.UsernameContext;
 import net.shibboleth.idp.authn.principal.UsernamePrincipal;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
@@ -283,6 +284,14 @@ public class RemoteUserAuthServlet extends HttpServlet {
                 return;
             }
             
+            // Populate the username into a UsernameContext for auditing.
+            final ProfileRequestContext prc = ExternalAuthentication.getProfileRequestContext(key, httpRequest);
+            final AuthenticationContext authnCtx = prc.getSubcontext(AuthenticationContext.class);
+            if (authnCtx != null) {
+                final UsernameContext uc = authnCtx.getSubcontext(UsernameContext.class, true);
+                uc.setUsername(username);
+            }
+            
             if (authnAuthorityHeader != null) {
                 // Check for proxied authorities.
                 final Enumeration<String> authorities = httpRequest.getHeaders(authnAuthorityHeader);
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java
index 7536fe2d0..55c121c2d 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java
@@ -19,6 +19,7 @@ package net.shibboleth.idp.authn.impl;
 
 import java.util.Collections;
 import java.util.Set;
+import java.util.function.Consumer;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
@@ -42,7 +43,9 @@ import net.shibboleth.idp.attribute.filter.context.AttributeFilterContext.Direct
 import net.shibboleth.idp.authn.AbstractValidationAction;
 import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.CertificateContext;
 import net.shibboleth.idp.authn.context.ExternalAuthenticationContext;
+import net.shibboleth.idp.authn.context.UsernameContext;
 import net.shibboleth.idp.authn.principal.IdPAttributePrincipal;
 import net.shibboleth.idp.authn.principal.ProxyAuthenticationPrincipal;
 import net.shibboleth.idp.authn.principal.UsernamePrincipal;
@@ -333,5 +336,47 @@ public class ValidateExternalAuthentication extends AbstractAuditingValidationAc
             filterContext.setAttributeIssuerID(extContext.getAuthenticatingAuthorities().iterator().next());
         }
     }
+    
+    /**
+     * A default cleanup hook that removes a {@link UsernameContext} from the tree.
+     * 
+     * @since 4.3.0
+     */
+    public static class UsernameCleanupHook implements Consumer<ProfileRequestContext> {
+
+        /** {@inheritDoc} */
+        public void accept(@Nullable final ProfileRequestContext input) {
+            if (input != null) {
+                final AuthenticationContext authnCtx = input.getSubcontext(AuthenticationContext.class);
+                if (authnCtx != null) {
+                    final UsernameContext uCtx = authnCtx.getSubcontext(UsernameContext.class);
+                    if (uCtx != null) {
+                        authnCtx.removeSubcontext(uCtx);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * A default cleanup hook that removes a {@link CertificateContext} from the tree.
+     * 
+     * @since 4.3.0
+     */
+    public static class CertificateCleanupHook implements Consumer<ProfileRequestContext> {
+
+        /** {@inheritDoc} */
+        public void accept(@Nullable final ProfileRequestContext input) {
+            if (input != null) {
+                final AuthenticationContext authnCtx = input.getSubcontext(AuthenticationContext.class);
+                if (authnCtx != null) {
+                    final CertificateContext cc = authnCtx.getSubcontext(CertificateContext.class);
+                    if (cc != null) {
+                        authnCtx.removeSubcontext(cc);
+                    }
+                }
+            }
+        }
+    }
 
 }
\ No newline at end of file
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateRemoteUser.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateRemoteUser.java
index 23cdda756..053fb4588 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateRemoteUser.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateRemoteUser.java
@@ -26,13 +26,11 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.security.auth.Subject;
 
-import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import net.shibboleth.idp.authn.AbstractValidationAction;
 import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.authn.context.UsernameContext;
@@ -54,7 +52,7 @@ import net.shibboleth.shared.primitive.StringSupport;
  * @post If AuthenticationContext.getSubcontext(UsernameContext.class, false).getUsername() != null, then
  * an {@link net.shibboleth.idp.authn.AuthenticationResult} is saved to the {@link AuthenticationContext}.
  */
-public class ValidateRemoteUser extends AbstractValidationAction {
+public class ValidateRemoteUser extends AbstractAuditingValidationAction {
 
     /** Default prefix for metrics. */
     @Nonnull @NotEmpty private static final String DEFAULT_METRIC_NAME = "net.shibboleth.idp.authn.remoteuser";
@@ -127,13 +125,15 @@ public class ValidateRemoteUser extends AbstractValidationAction {
         usernameContext = authenticationContext.getSubcontext(UsernameContext.class);
         if (usernameContext == null) {
             log.debug("{} No UsernameContext available within authentication context", getLogPrefix());
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
+            handleError(profileRequestContext, authenticationContext, AuthnEventIds.NO_CREDENTIALS,
+                    AuthnEventIds.NO_CREDENTIALS);
             return false;
         }
 
         if (usernameContext.getUsername() == null) {
             log.debug("{} No username available within UsernameContext", getLogPrefix());
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
+            handleError(profileRequestContext, authenticationContext, AuthnEventIds.NO_CREDENTIALS,
+                    AuthnEventIds.NO_CREDENTIALS);
             return false;
         }
         
@@ -147,7 +147,8 @@ public class ValidateRemoteUser extends AbstractValidationAction {
                 
         if (!isAuthenticated(usernameContext.getUsername())) {
             log.info("{} User '{}' was not valid", getLogPrefix(), usernameContext.getUsername());
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_CREDENTIALS);
+            handleError(profileRequestContext, authenticationContext, AuthnEventIds.INVALID_CREDENTIALS,
+                    AuthnEventIds.INVALID_CREDENTIALS);
             recordFailure(profileRequestContext);
             return;
         }
@@ -184,4 +185,5 @@ public class ValidateRemoteUser extends AbstractValidationAction {
         subject.getPrincipals().add(new UsernamePrincipal(usernameContext.getUsername()));
         return subject;
     }
-}
\ No newline at end of file
+    
+}
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateUserAgentAddress.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateUserAgentAddress.java
index 1afd33417..ced689870 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateUserAgentAddress.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateUserAgentAddress.java
@@ -28,7 +28,6 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.security.auth.Subject;
 
-import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
@@ -111,13 +110,15 @@ public class ValidateUserAgentAddress extends AbstractAuditingValidationAction {
         uaContext = authenticationContext.getSubcontext(UserAgentContext.class, false);
         if (uaContext == null) {
             log.debug("{} No UserAgentContext available within authentication context", getLogPrefix());
-            handleError(profileRequestContext, authenticationContext, "NoCredentials", AuthnEventIds.NO_CREDENTIALS);
+            handleError(profileRequestContext, authenticationContext, AuthnEventIds.NO_CREDENTIALS,
+                    AuthnEventIds.NO_CREDENTIALS);
             return false;
         }
 
         if (uaContext.getAddress() == null) {
             log.debug("{} No address available within UserAgentContext", getLogPrefix());
-            handleError(profileRequestContext, authenticationContext, "NoCredentials", AuthnEventIds.NO_CREDENTIALS);
+            handleError(profileRequestContext, authenticationContext, AuthnEventIds.NO_CREDENTIALS,
+                    AuthnEventIds.NO_CREDENTIALS);
             return false;
         }
         
@@ -142,7 +143,8 @@ public class ValidateUserAgentAddress extends AbstractAuditingValidationAction {
 
         log.debug("{} User agent with address {} was not authenticated", getLogPrefix(),
                 uaContext.getAddress().getHostAddress());
-        ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_CREDENTIALS);
+        handleError(profileRequestContext, authenticationContext, AuthnEventIds.INVALID_CREDENTIALS,
+                AuthnEventIds.INVALID_CREDENTIALS);
         recordFailure(profileRequestContext);
     }
 
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/X509AuthServlet.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/X509AuthServlet.java
index 38fd9e47f..ca1edb36c 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/X509AuthServlet.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/X509AuthServlet.java
@@ -157,6 +157,7 @@ public class X509AuthServlet extends HttpServlet {
             log.debug("End-entity X.509 certificate found with subject '{}', issued by '{}'",
                     cert.getSubjectX500Principal().getName(), cert.getIssuerX500Principal().getName());
             
+            // Populate the cert chain into a CertificateContext for auditing.
             final ProfileRequestContext prc = ExternalAuthentication.getProfileRequestContext(key, httpRequest);
             final AuthenticationContext authnCtx = prc.getSubcontext(AuthenticationContext.class);
             if (authnCtx != null) {
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-authn-beans.xml
index a0843c419..c438bddb7 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-authn-beans.xml
@@ -22,18 +22,67 @@
     <bean id="shibboleth.authn.RemoteUser.externalAuthnPathStrategy" parent="shibboleth.Functions.Constant"
         c:target="#{getObject('shibboleth.authn.RemoteUser.externalAuthnPath') ?: '%{idp.authn.RemoteUser.externalAuthnPath:contextRelative:/Authn/RemoteUser}'.trim()}" />
     
+    <!-- Default message map. -->
+    <util:map id="shibboleth.authn.RemoteUser.ClassifiedMessageMap">
+        <entry key="RequestUnsupported">
+            <list>
+                <value>RequestUnsupported</value>
+            </list>
+        </entry>
+        <entry key="NoCredentials">
+            <list>
+                <value>NoCredentials</value>
+            </list>
+        </entry>
+        <entry key="InvalidCredentials">
+            <list>
+                <value>InvalidCredentials</value>
+            </list>
+        </entry>
+    </util:map>
+    
     <import resource="conditional:%{idp.home}/conf/authn/remoteuser-authn-config.xml" />
 
+    <bean id="DefaultCleanupHook" class="net.shibboleth.idp.authn.impl.ValidateExternalAuthentication.UsernameCleanupHook" />
+
     <bean id="ValidateExternalAuthentication"
         class="net.shibboleth.idp.authn.impl.ValidateExternalAuthentication" scope="prototype"
         p:metricName="net.shibboleth.idp.authn.remoteuser"
         p:matchExpression="#{getObject('shibboleth.authn.RemoteUser.matchExpression') ?: '%{idp.authn.RemoteUser.matchExpression:}'}"
         p:addDefaultPrincipals="#{getObject('shibboleth.authn.RemoteUser.addDefaultPrincipals') ?: %{idp.authn.RemoteUser.addDefaultPrincipals:true}}"
         p:classifiedMessages="#{getObject('shibboleth.authn.RemoteUser.ClassifiedMessageMap')}"
-        p:resultCachingPredicate="#{getObject('shibboleth.authn.RemoteUser.resultCachingPredicate')}" />
+        p:resultCachingPredicate="#{getObject('shibboleth.authn.RemoteUser.resultCachingPredicate')}"
+        p:cleanupHook-ref="DefaultCleanupHook"
+        p:populateAuditContextAction="#{%{idp.authn.RemoteUser.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.RemoteUser.PopulateAuditContext') : null}"
+        p:writeAuditLogAction="#{%{idp.authn.RemoteUser.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuditLog') : null}" />
 
     <bean id="PopulateSubjectCanonicalizationContext"
         class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
         p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
 
+    <!-- Audit logging beans. -->
+
+    <util:map id="shibboleth.authn.AuditFormattingMap">
+        <entry key="#{'%{idp.authn.RemoteUser.audit.category:Shibboleth-Audit.RemoteUser}'.trim()}"
+            value="#{'%{idp.authn.RemoteUser.audit.format:%a|%T|%SP|%s|%AF|%CV|%u|%AR|%UA}'.trim()}" />
+    </util:map>
+
+    <bean id="shibboleth.authn.RemoteUser.DefaultAuditExtractors" parent="shibboleth.authn.DefaultAuditExtractors" lazy-init="true"
+            class="org.springframework.beans.factory.config.MapFactoryBean">
+        <property name="sourceMap">
+             <map merge="true">
+                <entry>
+                    <key>
+                        <util:constant static-field="net.shibboleth.idp.profile.IdPAuditFields.USERNAME"/>
+                    </key>
+                    <bean class="net.shibboleth.idp.authn.audit.impl.AttemptedUsernameAuditExtractor" />
+                </entry>
+             </map>
+        </property>
+    </bean>
+    
+    <bean id="shibboleth.authn.RemoteUser.PopulateAuditContext" parent="shibboleth.authn.AbstractPopulateAuditContext" lazy-init="true"
+        p:fieldExtractors="#{getObject('shibboleth.authn.RemoteUser.AuditExtractors') ?: getObject('shibboleth.authn.RemoteUser.DefaultAuditExtractors')}"
+        p:clearAuditContext="true" />
+
 </beans>
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-internal-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-internal-authn-beans.xml
index 184e3c612..3c4238535 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-internal-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-internal-authn-beans.xml
@@ -24,6 +24,25 @@
     <bean id="shibboleth.authn.RemoteUser.checkAttributes" parent="shibboleth.CommaDelimStringArray"
         c:_0="#{'%{idp.authn.RemoteUserInternal.checkAttributes:}'.trim()}" />
 
+    <!-- Default message map. -->
+    <util:map id="shibboleth.authn.RemoteUser.ClassifiedMessageMap">
+        <entry key="RequestUnsupported">
+            <list>
+                <value>RequestUnsupported</value>
+            </list>
+        </entry>
+        <entry key="NoCredentials">
+            <list>
+                <value>NoCredentials</value>
+            </list>
+        </entry>
+        <entry key="InvalidCredentials">
+            <list>
+                <value>InvalidCredentials</value>
+            </list>
+        </entry>
+    </util:map>
+
     <import resource="conditional:%{idp.home}/conf/authn/remoteuser-internal-authn-config.xml" />
 
     <bean class="net.shibboleth.shared.spring.config.DeprecatedBeanDetector" c:_1="remoteuser-internal-authn-config.xml">
@@ -60,10 +79,38 @@
         p:allowedUsernames="#{getObject('shibboleth.authn.RemoteUser.allowedUsernames') ?: (getObject('shibboleth.authn.RemoteUser.whitelistedUsernames') ?: getObject('PropertyDrivenAllowList'))}"
         p:deniedUsernames="#{getObject('shibboleth.authn.RemoteUser.deniedUsernames') ?: (getObject('shibboleth.authn.RemoteUser.blacklistedUsernames') ?: getObject('PropertyDrivenDenyList'))}"
         p:addDefaultPrincipals="#{getObject('shibboleth.authn.RemoteUser.addDefaultPrincipals') ?: %{idp.authn.RemoteUserInternal.addDefaultPrincipals:true}}"
-        p:resultCachingPredicate="#{getObject('shibboleth.authn.RemoteUser.resultCachingPredicate')}" />
+        p:classifiedMessages="#{getObject('shibboleth.authn.RemoteUser.ClassifiedMessageMap')}"
+        p:resultCachingPredicate="#{getObject('shibboleth.authn.RemoteUser.resultCachingPredicate')}"
+        p:populateAuditContextAction="#{%{idp.authn.RemoteUserInternal.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.RemoteUserInternal.PopulateAuditContext') : null}"
+        p:writeAuditLogAction="#{%{idp.authn.RemoteUserInternal.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuditLog') : null}" />
 
     <bean id="PopulateSubjectCanonicalizationContext"
         class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
         p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
 
+    <!-- Audit logging beans. -->
+
+    <util:map id="shibboleth.authn.AuditFormattingMap">
+        <entry key="#{'%{idp.authn.RemoteUserInternal.audit.category:Shibboleth-Audit.RemoteUserInternal}'.trim()}"
+            value="#{'%{idp.authn.RemoteUserInternal.audit.format:%a|%T|%SP|%s|%AF|%CV|%u|%AR|%UA}'.trim()}" />
+    </util:map>
+
+    <bean id="shibboleth.authn.RemoteUserInternal.DefaultAuditExtractors" parent="shibboleth.authn.DefaultAuditExtractors" lazy-init="true"
+            class="org.springframework.beans.factory.config.MapFactoryBean">
+        <property name="sourceMap">
+             <map merge="true">
+                <entry>
+                    <key>
+                        <util:constant static-field="net.shibboleth.idp.profile.IdPAuditFields.USERNAME"/>
+                    </key>
+                    <bean class="net.shibboleth.idp.authn.audit.impl.AttemptedUsernameAuditExtractor" />
+                </entry>
+             </map>
+        </property>
+    </bean>
+    
+    <bean id="shibboleth.authn.RemoteUserInternal.PopulateAuditContext" parent="shibboleth.authn.AbstractPopulateAuditContext" lazy-init="true"
+        p:fieldExtractors="#{getObject('shibboleth.authn.RemoteUserInternal.AuditExtractors') ?: getObject('shibboleth.authn.RemoteUserInternal.DefaultAuditExtractors')}"
+        p:clearAuditContext="true" />
+
 </beans>
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-authn-beans.xml
index b30312997..d0db1f98f 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-authn-beans.xml
@@ -24,12 +24,15 @@
 
     <import resource="conditional:%{idp.home}/conf/authn/x509-authn-config.xml" />
 
+    <bean id="DefaultCleanupHook" class="net.shibboleth.idp.authn.impl.ValidateExternalAuthentication.CertificateCleanupHook" />
+
     <bean id="ValidateExternalAuthentication"
         class="net.shibboleth.idp.authn.impl.ValidateExternalAuthentication" scope="prototype"
         p:metricName="net.shibboleth.idp.authn.x509"
         p:addDefaultPrincipals="#{getObject('shibboleth.authn.X509.addDefaultPrincipals') ?: %{idp.authn.X509.addDefaultPrincipals:true}}"
         p:classifiedMessages="#{getObject('shibboleth.authn.X509.ClassifiedMessageMap')}"
         p:resultCachingPredicate="#{getObject('shibboleth.authn.X509.resultCachingPredicate')}"
+        p:cleanupHook-ref="DefaultCleanupHook"
         p:populateAuditContextAction="#{%{idp.authn.X509.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.X509.PopulateAuditContext') : null}"
         p:writeAuditLogAction="#{%{idp.authn.X509.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuditLog') : null}" />
 
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/remoteuser-authn-config.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/remoteuser-authn-config.xml
index 67d292105..3c718bcb4 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/remoteuser-authn-config.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/remoteuser-authn-config.xml
@@ -41,9 +41,9 @@
                 <value>UnknownUsername</value>
             </list>
         </entry>
-        <entry key="InvalidPassword">
+        <entry key="InvalidCredentials">
             <list>
-                <value>InvalidPassword</value>
+                <value>InvalidCredentials</value>
             </list>
         </entry>
         <entry key="ExpiredPassword">
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/remoteuser-authn-config.xml b/idp-conf/src/test/resources/conf/authn/remoteuser-authn-config.xml
similarity index 96%
copy from idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/remoteuser-authn-config.xml
copy to idp-conf/src/test/resources/conf/authn/remoteuser-authn-config.xml
index 67d292105..3c718bcb4 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/remoteuser-authn-config.xml
+++ b/idp-conf/src/test/resources/conf/authn/remoteuser-authn-config.xml
@@ -41,9 +41,9 @@
                 <value>UnknownUsername</value>
             </list>
         </entry>
-        <entry key="InvalidPassword">
+        <entry key="InvalidCredentials">
             <list>
-                <value>InvalidPassword</value>
+                <value>InvalidCredentials</value>
             </list>
         </entry>
         <entry key="ExpiredPassword">

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list