Forced authentication does not reset the AuthnInstant
authorcantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 22 Dec 2010 19:29:29 +0000 (19:29 +0000)
committercantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 22 Dec 2010 19:29:29 +0000 (19:29 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/branches/REL_2@2973 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

doc/RELEASE-NOTES.txt
src/main/java/edu/internet2/middleware/shibboleth/idp/authn/AuthenticationEngine.java
src/main/java/edu/internet2/middleware/shibboleth/idp/authn/LoginHandler.java

index b11656b..cbf4b8d 100644 (file)
@@ -3,6 +3,7 @@ Changes in Release 2.2.1
 [SIDP-417] - Shib deployed to root web context, SSOProfileHandler forwards to "/null/AuthnEngine"
 [SIDP-421] - Error logging SOAP queries
 [SIDP-422] - aacli.sh Exception in thread "main" 
 [SIDP-417] - Shib deployed to root web context, SSOProfileHandler forwards to "/null/AuthnEngine"
 [SIDP-421] - Error logging SOAP queries
 [SIDP-422] - aacli.sh Exception in thread "main" 
+[SIDP-426] - Forced authentication does not reset the AuthnInstant 
 [SIDP-427] - Incorrect handling of returned authn error in SSO profile handlers
 [SIDP-428] - Address lifecycle issues around use of MetadataCredentialResolverFactory
 [SIDP-431] - Typo in default attribute-resolver.xml
 [SIDP-427] - Incorrect handling of returned authn error in SSO profile handlers
 [SIDP-428] - Address lifecycle issues around use of MetadataCredentialResolverFactory
 [SIDP-431] - Typo in default attribute-resolver.xml
index 7f65fb8..4bed051 100644 (file)
@@ -134,8 +134,7 @@ public class AuthenticationEngine extends HttpServlet {
         storageService = (StorageService<String, LoginContextEntry>) HttpServletHelper.getStorageService(context);
     }
 
         storageService = (StorageService<String, LoginContextEntry>) HttpServletHelper.getStorageService(context);
     }
 
-    /**
-     * Returns control back to the authentication engine.
+    /* Returns control back to the authentication engine.
      * 
      * @param httpRequest current HTTP request
      * @param httpResponse current HTTP response
      * 
      * @param httpRequest current HTTP request
      * @param httpResponse current HTTP response
@@ -527,19 +526,27 @@ public class AuthenticationEngine extends HttpServlet {
             } else {
                 actualAuthnMethod = loginContext.getAttemptedAuthnMethod();
             }
             } else {
                 actualAuthnMethod = loginContext.getAttemptedAuthnMethod();
             }
-
+            
             // Check to make sure the login handler did the right thing
             validateSuccessfulAuthentication(loginContext, httpRequest, actualAuthnMethod);
 
             // Check to make sure the login handler did the right thing
             validateSuccessfulAuthentication(loginContext, httpRequest, actualAuthnMethod);
 
+            // Check for an overridden authn instant.
+            DateTime actualAuthnInstant = (DateTime) httpRequest.getAttribute(LoginHandler.AUTHENTICATION_INSTANT_KEY);
+
             // Get the Subject from the request. If force authentication was required then make sure the
             // Subject identifies the same user that authenticated before
             Subject subject = getLoginHandlerSubject(httpRequest);
             if (loginContext.isForceAuthRequired()) {
                 validateForcedReauthentication(idpSession, actualAuthnMethod, subject);
             // Get the Subject from the request. If force authentication was required then make sure the
             // Subject identifies the same user that authenticated before
             Subject subject = getLoginHandlerSubject(httpRequest);
             if (loginContext.isForceAuthRequired()) {
                 validateForcedReauthentication(idpSession, actualAuthnMethod, subject);
+                
+                // Reset the authn instant.
+                if (actualAuthnInstant == null) {
+                    actualAuthnInstant = new DateTime();
+                }
             }
 
             loginContext.setPrincipalAuthenticated(true);
             }
 
             loginContext.setPrincipalAuthenticated(true);
-            updateUserSession(loginContext, subject, actualAuthnMethod, httpRequest, httpResponse);
+            updateUserSession(loginContext, subject, actualAuthnMethod, actualAuthnInstant, httpRequest, httpResponse);
             LOG.debug("User {} authenticated with method {}", loginContext.getPrincipalName(),
                     loginContext.getAuthenticationMethod());
         } catch (AuthenticationException e) {
             LOG.debug("User {} authenticated with method {}", loginContext.getPrincipalName(),
                     loginContext.getAuthenticationMethod());
         } catch (AuthenticationException e) {
@@ -662,11 +669,13 @@ public class AuthenticationEngine extends HttpServlet {
      * @param loginContext current login context
      * @param authenticationSubject subject created from the authentication method
      * @param authenticationMethod the method used to authenticate the subject
      * @param loginContext current login context
      * @param authenticationSubject subject created from the authentication method
      * @param authenticationMethod the method used to authenticate the subject
+     * @param authenticationInstant the time of authentication
      * @param httpRequest current HTTP request
      * @param httpResponse current HTTP response
      */
     protected void updateUserSession(LoginContext loginContext, Subject authenticationSubject,
      * @param httpRequest current HTTP request
      * @param httpResponse current HTTP response
      */
     protected void updateUserSession(LoginContext loginContext, Subject authenticationSubject,
-            String authenticationMethod, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+            String authenticationMethod, DateTime authenticationInstant,
+            HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
         Principal authenticationPrincipal = authenticationSubject.getPrincipals().iterator().next();
         LOG.debug("Updating session information for principal {}", authenticationPrincipal.getName());
 
         Principal authenticationPrincipal = authenticationSubject.getPrincipals().iterator().next();
         LOG.debug("Updating session information for principal {}", authenticationPrincipal.getName());
 
@@ -682,15 +691,21 @@ public class AuthenticationEngine extends HttpServlet {
         // login handler subject
         idpSession.setSubject(mergeSubjects(idpSession.getSubject(), authenticationSubject));
 
         // login handler subject
         idpSession.setSubject(mergeSubjects(idpSession.getSubject(), authenticationSubject));
 
-        // Check if an existing authentication method was used (i.e. SSO occurred), if not record the new information
+        // Check if an existing authentication method with no updated timestamp was used (i.e. SSO occurred);
+        // if not record the new information
         AuthenticationMethodInformation authnMethodInfo = idpSession.getAuthenticationMethods().get(
                 authenticationMethod);
         AuthenticationMethodInformation authnMethodInfo = idpSession.getAuthenticationMethods().get(
                 authenticationMethod);
-        if (authnMethodInfo == null) {
+        if (authnMethodInfo == null || authenticationInstant != null) {
             LOG.debug("Recording authentication and service information in Shibboleth session for principal: {}",
                     authenticationPrincipal.getName());
             LoginHandler loginHandler = handlerManager.getLoginHandlers().get(loginContext.getAttemptedAuthnMethod());
             LOG.debug("Recording authentication and service information in Shibboleth session for principal: {}",
                     authenticationPrincipal.getName());
             LoginHandler loginHandler = handlerManager.getLoginHandlers().get(loginContext.getAttemptedAuthnMethod());
-            authnMethodInfo = new AuthenticationMethodInformationImpl(idpSession.getSubject(), authenticationPrincipal,
-                    authenticationMethod, new DateTime(), loginHandler.getAuthenticationDuration());
+            authnMethodInfo = new AuthenticationMethodInformationImpl(
+                    idpSession.getSubject(),
+                    authenticationPrincipal,
+                    authenticationMethod,
+                    (authenticationInstant != null ? authenticationInstant : new DateTime()),
+                    loginHandler.getAuthenticationDuration()
+                    );
         }
 
         loginContext.setAuthenticationMethodInformation(authnMethodInfo);
         }
 
         loginContext.setAuthenticationMethodInformation(authnMethodInfo);
index ae1a37f..98943af 100644 (file)
@@ -79,6 +79,9 @@ public interface LoginHandler {
     /** Request attribute to which an authentication method URI may be bound. */
     public static final String AUTHENTICATION_METHOD_KEY = "authnMethod";
 
     /** Request attribute to which an authentication method URI may be bound. */
     public static final String AUTHENTICATION_METHOD_KEY = "authnMethod";
 
+    /** Request attribute to which an authentication timestamp may be bound. */
+    public static final String AUTHENTICATION_INSTANT_KEY = "authnInstant";
+    
     /** Request attribute to which an error message may be bound. */
     public static final String AUTHENTICATION_ERROR_KEY = "authnError";
 
     /** Request attribute to which an error message may be bound. */
     public static final String AUTHENTICATION_ERROR_KEY = "authnError";