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

Scott Cantor cantor.2 at osu.edu
Tue Jan 3 22:01:48 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=0b217e1df9b6999143a7905ec03e3c64ab21ef3b

commit 0b217e1df9b6999143a7905ec03e3c64ab21ef3b
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Dec 7 12:07:40 2022 -0500

    IDP-2039 - Add audit logging to login flows
    
    https://shibboleth.atlassian.net/browse/IDP-2039
    
    Finish adding to Function and SPNEGO flows.
    Adjust Function flow with better behavior.
    Remove extraneous message mappings.
---
 .../idp/authn/impl/RemoteUserAuthServlet.java      | 12 +---
 .../authn/impl/ValidateExternalAuthentication.java | 67 +++++++++++++---------
 .../idp/authn/impl/ValidateFunctionResult.java     | 60 ++++++++++++++++---
 .../shibboleth/idp/flows/authn/duo-authn-beans.xml | 11 ----
 .../idp/flows/authn/external-authn-beans.xml       | 22 ++++++-
 .../idp/flows/authn/function-authn-beans.xml       | 23 +++++++-
 .../idp/flows/authn/ipaddress-authn-beans.xml      | 19 ------
 .../idp/flows/authn/password-authn-beans.xml       |  9 ---
 .../idp/flows/authn/remoteuser-authn-beans.xml     | 31 +---------
 .../authn/remoteuser-internal-authn-beans.xml      | 19 ------
 .../idp/flows/authn/spnego-authn-beans.xml         | 36 +++++++++---
 .../idp/flows/authn/x509-internal-authn-beans.xml  | 14 -----
 .../module/conf/authn/external-authn-config.xml    | 21 +------
 .../module/conf/authn/function-authn-config.xml    |  3 +
 .../idp/module/conf/authn/spnego-authn-config.xml  | 20 -------
 15 files changed, 172 insertions(+), 195 deletions(-)

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 4ee08888e..2a3485e33 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,7 +39,6 @@ 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;
@@ -189,7 +188,8 @@ public class RemoteUserAuthServlet extends HttpServlet {
             }
         }
 
-        param = config.getInitParameter(CHECK_HEADERS_PARAM);
+        //param = config.getInitParameter(CHECK_HEADERS_PARAM);
+        param = "ShibbolethUser";
         if (param != null) {
             final String[] headers = param.split(" ");
             if (headers != null) {
@@ -284,14 +284,6 @@ 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 55c121c2d..dfc328021 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
@@ -18,6 +18,7 @@
 package net.shibboleth.idp.authn.impl;
 
 import java.util.Collections;
+import java.util.Map;
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.regex.Pattern;
@@ -45,10 +46,10 @@ 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;
+import net.shibboleth.idp.profile.IdPAuditFields;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.service.ReloadableService;
 import net.shibboleth.shared.service.ServiceException;
@@ -260,23 +261,54 @@ public class ValidateExternalAuthentication extends AbstractAuditingValidationAc
     private boolean checkUsername(@Nonnull final Subject subject) {
         
         if (matchExpression != null) {
-            final Set<UsernamePrincipal> princs = subject.getPrincipals(UsernamePrincipal.class);
-            if (princs != null && !princs.isEmpty()) {
-                if (matchExpression.matcher(princs.iterator().next().getName()).matches()) {
+            final String name = getUsername(subject);
+            if (name != null) {
+                if (matchExpression.matcher(name).matches()) {
                     return true;
                 }
                 
-                log.info("{} Username did not match expression", getLogPrefix());
+                log.info("{} Username {} did not match expression", getLogPrefix(), name);
                 return false;
             }
             
-            log.info("{} Match expression set, but not UsernamePrincipal found");
+            log.info("{} Match expression set, but no UsernamePrincipal found");
             return false;
         }
         
         return true;
     }
     
+    /**
+     * Get the username from a {@link UsernamePrincipal} inside the subject.
+     * 
+     * @param subject input subject
+     * 
+     * @return username, or null
+     */
+    @Nullable private String getUsername(@Nonnull final Subject subject) {
+        
+        final Set<UsernamePrincipal> princs = subject.getPrincipals(UsernamePrincipal.class);
+        if (princs != null && !princs.isEmpty()) {
+            return princs.iterator().next().getName();
+        }
+        
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable protected Map<String,String> getAuditFields(@Nonnull final ProfileRequestContext profileRequestContext) {
+        
+        if (extContext != null && extContext.getSubject() != null) {
+            final String name = getUsername(extContext.getSubject());
+            if (name != null) {
+                return Collections.singletonMap(IdPAuditFields.USERNAME, name);
+            }
+        }
+        
+        return super.getAuditFields(profileRequestContext);
+    }
+    
     /**
      * Check for inbound attributes and apply filtering.
      */
@@ -336,27 +368,6 @@ 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.
@@ -379,4 +390,4 @@ public class ValidateExternalAuthentication extends AbstractAuditingValidationAc
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateFunctionResult.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateFunctionResult.java
index b1b94d6f6..416b39cfb 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateFunctionResult.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateFunctionResult.java
@@ -18,22 +18,24 @@
 package net.shibboleth.idp.authn.impl;
 
 import java.security.Principal;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
 import java.util.function.Function;
 
 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.principal.UsernamePrincipal;
+import net.shibboleth.idp.profile.IdPAuditFields;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.component.ComponentInitializationException;
@@ -53,7 +55,7 @@ import net.shibboleth.shared.logic.ConstraintViolationException;
  * 
  * @since 3.4.0
  */
-public class ValidateFunctionResult extends AbstractValidationAction {
+public class ValidateFunctionResult extends AbstractAuditingValidationAction {
 
     /** Default prefix for metrics. */
     @Nonnull @NotEmpty private static final String DEFAULT_METRIC_NAME = "net.shibboleth.idp.authn.function";
@@ -99,11 +101,19 @@ public class ValidateFunctionResult extends AbstractValidationAction {
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final AuthenticationContext authenticationContext) {
 
-        result = resultLookupStrategy.apply(profileRequestContext);
+        try {
+            result = resultLookupStrategy.apply(profileRequestContext);
+        } catch (final Exception e) {
+            log.info("{} Authentication by function failed with exception", getLogPrefix(), e);
+            handleError(profileRequestContext, authenticationContext, e, AuthnEventIds.AUTHN_EXCEPTION);
+            recordFailure(profileRequestContext);
+            return;
+        }
 
         if (result == null) {
             log.info("{} Authentication by function failed", getLogPrefix());
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
+            handleError(profileRequestContext, authenticationContext, AuthnEventIds.NO_CREDENTIALS,
+                    AuthnEventIds.NO_CREDENTIALS);
             recordFailure(profileRequestContext);
         } else if (result instanceof String) {
             log.info("{} Validated user via name '{}'", getLogPrefix(), result);
@@ -119,7 +129,8 @@ public class ValidateFunctionResult extends AbstractValidationAction {
             buildAuthenticationResult(profileRequestContext, authenticationContext);
         } else {
             log.info("{} Authentication by function failed, result type was invalid", getLogPrefix());
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_CREDENTIALS);
+            handleError(profileRequestContext, authenticationContext, AuthnEventIds.NO_CREDENTIALS,
+                    AuthnEventIds.NO_CREDENTIALS);
             recordFailure(profileRequestContext);
         }
     }
@@ -143,5 +154,40 @@ public class ValidateFunctionResult extends AbstractValidationAction {
         // Save my walrus!
         throw new ConstraintViolationException("Result type was unexpected");
     }
-    
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable protected Map<String,String> getAuditFields(@Nonnull final ProfileRequestContext profileRequestContext) {
+        
+        if (result instanceof String) {
+            return Collections.singletonMap(IdPAuditFields.USERNAME, (String) result);
+        } else if (result instanceof UsernamePrincipal) {
+            return Collections.singletonMap(IdPAuditFields.USERNAME, ((UsernamePrincipal) result).getName());
+        } else if (result instanceof Subject) {
+            final String name = getUsername((Subject) result);
+            if (name != null) {
+                return Collections.singletonMap(IdPAuditFields.USERNAME, name);
+            }
+        }
+        
+        return super.getAuditFields(profileRequestContext);
+    }
+
+    /**
+     * Get the username from a {@link UsernamePrincipal} inside the subject.
+     * 
+     * @param subject input subject
+     * 
+     * @return username, or null
+     */
+    @Nullable private String getUsername(@Nonnull final Subject subject) {
+        
+        final Set<UsernamePrincipal> princs = subject.getPrincipals(UsernamePrincipal.class);
+        if (princs != null && !princs.isEmpty()) {
+            return princs.iterator().next().getName();
+        }
+        
+        return null;
+    }
+
 }
\ No newline at end of file
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/duo-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/duo-authn-beans.xml
index b103877e8..5a315a064 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/duo-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/duo-authn-beans.xml
@@ -44,22 +44,11 @@
                 <value>Your two-factor account is disabled.</value>
             </list>
         </entry>
-        <entry key="RequestUnsupported">
-            <list>
-                <value>RequestUnsupported</value>
-            </list>
-        </entry>
         <entry key="NoCredentials">
             <list>
-                <value>NoCredentials</value>
                 <value>Invalid request parameters (no capable device)</value>
             </list>
         </entry>
-        <entry key="InvalidCredentials">
-            <list>
-                <value>InvalidCredentials</value>
-            </list>
-        </entry>
     </util:map>
 
     <!-- Can override one or more of the beans above. -->
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/external-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/external-authn-beans.xml
index 7dbb024f8..0428827e2 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/external-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/external-authn-beans.xml
@@ -31,10 +31,30 @@
         p:classifiedMessages="#{getObject('shibboleth.authn.External.ClassifiedMessageMap')}"
         p:resultCachingPredicate="#{getObject('shibboleth.authn.External.resultCachingPredicate')}"
         c:filterService-ref="shibboleth.AttributeFilterService"
-        p:metadataResolver-ref="shibboleth.MetadataResolver" />
+        p:metadataResolver-ref="shibboleth.MetadataResolver"
+        p:populateAuditContextAction="#{%{idp.authn.External.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.External.PopulateAuditContext') : null}"
+        p:writeAuditLogAction="#{%{idp.authn.External.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.External.audit.category:Shibboleth-Audit.External}'.trim()}"
+            value="#{'%{idp.authn.External.audit.format:%a|%T|%SP|%s|%AF|%u|%AR|%UA}'.trim()}" />
+    </util:map>
+
+    <bean id="shibboleth.authn.External.DefaultAuditExtractors" parent="shibboleth.authn.DefaultAuditExtractors" lazy-init="true"
+            class="org.springframework.beans.factory.config.MapFactoryBean">
+        <property name="sourceMap">
+             <map merge="true" />
+        </property>
+    </bean>
+    
+    <bean id="shibboleth.authn.External.PopulateAuditContext" parent="shibboleth.authn.AbstractPopulateAuditContext" lazy-init="true"
+        p:fieldExtractors="#{getObject('shibboleth.authn.External.AuditExtractors') ?: getObject('shibboleth.authn.External.DefaultAuditExtractors')}"
+        p:clearAuditContext="true" />
+
 </beans>
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/function-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/function-authn-beans.xml
index 203dc127e..72d53726c 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/function-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/function-authn-beans.xml
@@ -29,10 +29,31 @@
     <bean id="ValidateFunctionResult" class="net.shibboleth.idp.authn.impl.ValidateFunctionResult" scope="prototype"
         p:addDefaultPrincipals="#{getObject('shibboleth.authn.Function.addDefaultPrincipals') ?: %{idp.authn.Function.addDefaultPrincipals:true}}"
         p:resultCachingPredicate="#{getObject('shibboleth.authn.Function.resultCachingPredicate')}"
-        p:resultLookupStrategy="#{getObject('shibboleth.authn.Function.ResultLookupStrategy') ?: getObject('DefaultResultLookupStrategy')}" />
+        p:classifiedMessages="#{getObject('shibboleth.authn.Function.ClassifiedMessageMap')}"
+        p:resultLookupStrategy="#{getObject('shibboleth.authn.Function.ResultLookupStrategy') ?: getObject('DefaultResultLookupStrategy')}"
+        p:populateAuditContextAction="#{%{idp.authn.Function.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.Function.PopulateAuditContext') : null}"
+        p:writeAuditLogAction="#{%{idp.authn.Function.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.Function.audit.category:Shibboleth-Audit.Function}'.trim()}"
+            value="#{'%{idp.authn.Function.audit.format:%a|%T|%SP|%s|%AF|%u|%AR|%UA}'.trim()}" />
+    </util:map>
+
+    <bean id="shibboleth.authn.Function.DefaultAuditExtractors" parent="shibboleth.authn.DefaultAuditExtractors" lazy-init="true"
+            class="org.springframework.beans.factory.config.MapFactoryBean">
+        <property name="sourceMap">
+             <map merge="true" />
+        </property>
+    </bean>
+    
+    <bean id="shibboleth.authn.Function.PopulateAuditContext" parent="shibboleth.authn.AbstractPopulateAuditContext" lazy-init="true"
+        p:fieldExtractors="#{getObject('shibboleth.authn.Function.AuditExtractors') ?: getObject('shibboleth.authn.Function.DefaultAuditExtractors')}"
+        p:clearAuditContext="true" />
+
 </beans>
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/ipaddress-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/ipaddress-authn-beans.xml
index 5df2d675d..b9dbcdeaf 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/ipaddress-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/ipaddress-authn-beans.xml
@@ -18,25 +18,6 @@
     <bean class="net.shibboleth.shared.spring.config.IdentifiableBeanPostProcessor" />
     <bean class="net.shibboleth.idp.profile.impl.ProfileActionBeanPostProcessor" />
 
-    <!-- Default message map. -->
-    <util:map id="shibboleth.authn.IPAddress.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/ipaddress-authn-config.xml" />
     
     <bean id="ExtractUserAgentAddress" class="net.shibboleth.idp.authn.impl.ExtractUserAgentAddress" scope="prototype"
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/password-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/password-authn-beans.xml
index 13f6288ac..aeb78921d 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/password-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/password-authn-beans.xml
@@ -43,15 +43,6 @@
     <bean id="shibboleth.authn.JAAS.LoginConfigNames" parent="shibboleth.CommaDelimStringArray"
         c:_0="#{'%{idp.authn.JAAS.loginConfigNames:ShibUserPassAuth}'.trim()}" />
 
-    <!-- Default message map. -->
-    <util:map id="shibboleth.authn.Password.ClassifiedMessageMap">
-        <entry key="RequestUnsupported">
-            <list>
-                <value>RequestUnsupported</value>
-            </list>
-        </entry>
-    </util:map>
-
     <import resource="conditional:%{idp.home}/conf/authn/password-authn-config.xml" />
 
     <bean id="ExtractUsernamePasswordFromBasicAuth"
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 c438bddb7..a33344a51 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,29 +22,8 @@
     <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"
@@ -52,7 +31,6 @@
         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: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}" />
 
@@ -70,14 +48,7 @@
     <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>
+             <map merge="true"/>
         </property>
     </bean>
     
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 3c4238535..295b0f558 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,25 +24,6 @@
     <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">
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/spnego-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/spnego-authn-beans.xml
index 8203c3472..2e9883b66 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/spnego-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/spnego-authn-beans.xml
@@ -47,19 +47,39 @@
     <!-- Action beans. -->
 
     <bean id="ValidateExternalAuthentication"
-            class="net.shibboleth.idp.authn.impl.ValidateExternalAuthentication" scope="prototype"
-            p:metricName="net.shibboleth.idp.authn.spnego"
-            p:matchExpression="#{getObject('shibboleth.authn.SPNEGO.matchExpression') ?: '%{idp.authn.SPNEGO.matchExpression:}'}"
-            p:addDefaultPrincipals="#{getObject('shibboleth.authn.SPNEGO.addDefaultPrincipals') ?: %{idp.authn.SPNEGO.addDefaultPrincipals:true}}"
-            p:classifiedMessages="#{getObject('shibboleth.authn.SPNEGO.ClassifiedMessageMap')}" />
+        class="net.shibboleth.idp.authn.impl.ValidateExternalAuthentication" scope="prototype"
+        p:metricName="net.shibboleth.idp.authn.spnego"
+        p:matchExpression="#{getObject('shibboleth.authn.SPNEGO.matchExpression') ?: '%{idp.authn.SPNEGO.matchExpression:}'}"
+        p:addDefaultPrincipals="#{getObject('shibboleth.authn.SPNEGO.addDefaultPrincipals') ?: %{idp.authn.SPNEGO.addDefaultPrincipals:true}}"
+        p:classifiedMessages="#{getObject('shibboleth.authn.SPNEGO.ClassifiedMessageMap')}"
+        p:populateAuditContextAction="#{%{idp.authn.SPNEGO.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.SPNEGO.PopulateAuditContext') : null}"
+        p:writeAuditLogAction="#{%{idp.authn.SPNEGO.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuditLog') : null}" />
             
     <bean id="SPNEGOAutoLoginManager"
-          class="net.shibboleth.idp.authn.spnego.impl.SPNEGOAutoLoginManager"
-          p:cookieManager-ref="shibboleth.UserPrefsCookieManager"
-          p:cookieName="%{idp.authn.SPNEGO.cookieName:_idp_spnego_autologin}" />
+        class="net.shibboleth.idp.authn.spnego.impl.SPNEGOAutoLoginManager"
+        p:cookieManager-ref="shibboleth.UserPrefsCookieManager"
+        p:cookieName="%{idp.authn.SPNEGO.cookieName:_idp_spnego_autologin}" />
 
     <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.SPNEGO.audit.category:Shibboleth-Audit.SPNEGO}'.trim()}"
+            value="#{'%{idp.authn.SPNEGO.audit.format:%a|%T|%SP|%s|%AF|%u|%AR|%UA}'.trim()}" />
+    </util:map>
+
+    <bean id="shibboleth.authn.SPNEGO.DefaultAuditExtractors" parent="shibboleth.authn.DefaultAuditExtractors" lazy-init="true"
+            class="org.springframework.beans.factory.config.MapFactoryBean">
+        <property name="sourceMap">
+             <map merge="true" />
+        </property>
+    </bean>
+    
+    <bean id="shibboleth.authn.SPNEGO.PopulateAuditContext" parent="shibboleth.authn.AbstractPopulateAuditContext" lazy-init="true"
+        p:fieldExtractors="#{getObject('shibboleth.authn.SPNEGO.AuditExtractors') ?: getObject('shibboleth.authn.SPNEGO.DefaultAuditExtractors')}"
+        p:clearAuditContext="true" />
+
 </beans>
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-internal-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-internal-authn-beans.xml
index a5691e5cf..ce454b6e2 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-internal-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-internal-authn-beans.xml
@@ -18,20 +18,6 @@
     <bean class="net.shibboleth.shared.spring.config.IdentifiableBeanPostProcessor" />
     <bean class="net.shibboleth.idp.profile.impl.ProfileActionBeanPostProcessor" />
 
-    <!-- Default message map. -->
-    <util:map id="shibboleth.authn.X509Internal.ClassifiedMessageMap">
-        <entry key="RequestUnsupported">
-            <list>
-                <value>RequestUnsupported</value>
-            </list>
-        </entry>
-        <entry key="InvalidCredentials">
-            <list>
-                <value>InvalidCredentials</value>
-            </list>
-        </entry>
-    </util:map>
-
     <import resource="conditional:%{idp.home}/conf/authn/x509-internal-authn-config.xml" />
     
     <bean id="ExtractX509CertificateFromRequest"
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/external-authn-config.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/external-authn-config.xml
index 0d19b78d9..ceb92663d 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/external-authn-config.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/external-authn-config.xml
@@ -25,32 +25,17 @@
     kinds of errors for use in your templates and as events in flows.
 
     Keys are events to signal, values are error codes.
-
-    The examples here just allow external signaling of the exact type of condition to record.
     
     If you want to "fall-through" to other login flows, include a mapping to "ReselectFlow".
     -->
+    <!--
     <util:map id="shibboleth.authn.External.ClassifiedMessageMap">
-        <entry key="UnknownUsername">
+        <entry key="ReselectFlow">
             <list>
                 <value>UnknownUsername</value>
             </list>
         </entry>
-        <entry key="InvalidPassword">
-            <list>
-                <value>InvalidPassword</value>
-            </list>
-        </entry>
-        <entry key="ExpiredPassword">
-            <list>
-                <value>ExpiredPassword</value>
-            </list>
-        </entry>
-        <entry key="ExpiringPassword">
-            <list>
-                <value>ExpiringPassword</value>
-            </list>
-        </entry>
     </util:map>
+    -->
     
 </beans>
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/function-authn-config.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/function-authn-config.xml
index 180555631..636fec5f0 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/function-authn-config.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/function-authn-config.xml
@@ -15,6 +15,9 @@
     <!--
     The entire flow depends on the execution of a function bean you supply. A pathological script example
     is below. The function may return a String, Principal, Subject, or a null to signal failure.
+    
+    You may also raise an exception and install a bean named shibboleth.authn.Function.ClassifiedMessageMap
+    to map exception messages to events.
     -->
     
     <bean id="shibboleth.authn.Function.ResultLookupStrategy"
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/spnego-authn-config.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/spnego-authn-config.xml
index 5be020400..b26c020c7 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/spnego-authn-config.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/spnego-authn-config.xml
@@ -31,24 +31,4 @@
 
     </util:list>
 
-    <!--
-    Define entries here to map events or error messages returned by the SPNEGO module
-    and classify them as particular kinds of errors for use in your templates and as
-    events in flows.
-
-    Keys are events to signal, values are error codes.
-    -->
-    <util:map id="shibboleth.authn.SPNEGO.ClassifiedMessageMap">
-        <entry key="SPNEGONotAvailable">
-            <list>
-                <value>SPNEGONotAvailable</value>
-            </list>
-        </entry>
-        <entry key="NTLMUnsupported">
-            <list>
-                <value>NTLMUnsupported</value>
-            </list>
-        </entry>
-    </util:map>
- 
 </beans>

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


More information about the commits mailing list