[java-idp-plugin-totp] branch main updated: JTOTP-6 - Port to IdP V5

Scott Cantor cantor.2 at osu.edu
Tue Jul 18 18:34:41 UTC 2023


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

scantor pushed a commit to branch main
in repository java-idp-plugin-totp.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-totp.git;a=commit;h=10b7121cc0e33dc2a8229aa289c8a966f345c4f7

The following commit(s) were added to refs/heads/main by this push:
     new 10b7121  JTOTP-6 - Port to IdP V5
10b7121 is described below

commit 10b7121cc0e33dc2a8229aa289c8a966f345c4f7
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Jul 18 14:34:38 2023 -0400

    JTOTP-6 - Port to IdP V5
    
    https://shibboleth.atlassian.net/browse/JTOTP-6
    
    Initial port, tests passing.
---
 pom.xml                                            |  35 +++++--
 totp-impl/pom.xml                                  | 107 ++++++++++++---------
 .../idp/plugin/authn/totp/TOTPModule.java          |   2 +-
 .../idp/plugin/authn/totp/TOTPPlugin.java          |   4 +-
 .../idp/plugin/authn/totp/context/TOTPContext.java |   9 +-
 .../plugin/authn/totp/context/package-info.java    |   4 +-
 .../plugin/authn/totp/impl/AbstractSeedSource.java |  13 ++-
 .../totp/impl/AbstractTOTPExtractionAction.java    |  16 +--
 .../totp/impl/AttributeResolverSeedSource.java     |  31 +++---
 .../totp/impl/ExtractTOTPFromFormRequest.java      |  17 ++--
 .../authn/totp/impl/ExtractTOTPFromHeader.java     |  17 ++--
 .../authn/totp/impl/GoogleTOTPAuthenticator.java   |  31 +++---
 .../plugin/authn/totp/impl/StaticSeedSource.java   |  24 +++--
 .../plugin/authn/totp/impl/TOTPAuthenticator.java  |  11 +--
 .../totp/impl/TOTPAuthenticatorArguments.java      |  13 +--
 .../authn/totp/impl/TOTPAuthenticatorCLI.java      |   6 +-
 .../authn/totp/impl/TOTPCredentialValidator.java   |  22 ++---
 .../idp/plugin/authn/totp/impl/package-info.java   |   4 +-
 .../idp/plugin/authn/totp/module.properties        |   2 +
 .../idp/plugin/authn/totp/plugin.properties        |   2 +-
 .../totp/impl/AttributeResolverSeedSourceTest.java |  19 ++--
 .../totp/impl/BaseAuthenticationContextTest.java   |  79 +++++++++++++++
 .../totp/impl/ExtractTOTPFromFormRequestTest.java  |  10 +-
 .../authn/totp/impl/ExtractTOTPFromHeaderTest.java |  10 +-
 .../totp/impl/GoogleTOTPAuthenticatorTest.java     |  22 ++---
 25 files changed, 307 insertions(+), 203 deletions(-)

diff --git a/pom.xml b/pom.xml
index 34808fb..f2c98be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,24 +7,25 @@
     <parent>
         <groupId>net.shibboleth</groupId>
         <artifactId>parent</artifactId>
-        <version>11.3.4</version>
+        <version>17.0.0-SNAPSHOT</version>
     </parent>
 
     <name>Shibboleth IdP :: Plugins :: TOTP Login Flow</name>
     <description>An IdP plugin providing TOTP login support.</description>
     <groupId>net.shibboleth.idp.plugin.authn</groupId>
     <artifactId>idp-plugin-totp</artifactId>
-    <version>1.0.3-SNAPSHOT</version>
+    <version>2.0.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <properties>
         <idp.groupId>net.shibboleth.idp</idp.groupId>
-        <idp.version>4.2.0</idp.version>
+        <idp.version>5.0.0-SNAPSHOT</idp.version>
         <opensaml.groupId>org.opensaml</opensaml.groupId>
-        <opensaml.version>4.2.0</opensaml.version>
-        <java-support.version>8.3.1</java-support.version>
-        <spring-extensions.version>6.2.0</spring-extensions.version>
-        <checkstyle.configLocation>${project.basedir}/checkstyle.xml</checkstyle.configLocation>
+        <opensaml.version>5.0.0-SNAPSHOT</opensaml.version>
+        <shib-profile.version>5.0.0-SNAPSHOT</shib-profile.version>
+        <shib-attribute.version>5.0.0-SNAPSHOT</shib-attribute.version>
+        <shib-shared.groupId>net.shibboleth</shib-shared.groupId>
+        <shib-shared.version>9.0.0-SNAPSHOT</shib-shared.version>
     </properties>
     
     <distributionManagement>
@@ -50,9 +51,16 @@
                 <scope>import</scope>
             </dependency>
             <dependency>
-                <groupId>${idp.groupId}</groupId>
-                <artifactId>idp-tests-bom</artifactId>
-                <version>${idp.version}</version>
+                <groupId>${shib-shared.groupId}</groupId>
+                <artifactId>shib-profile-bom</artifactId>
+                <version>${shib-profile.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>${shib-shared.groupId}</groupId>
+                <artifactId>shib-attribute-bom</artifactId>
+                <version>${shib-attribute.version}</version>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
@@ -63,6 +71,13 @@
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
+            <dependency>
+                <groupId>${shib-shared.groupId}</groupId>
+                <artifactId>shib-shared-bom</artifactId>
+                <version>${shib-shared.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/totp-impl/pom.xml b/totp-impl/pom.xml
index 79dff79..2acc0a8 100644
--- a/totp-impl/pom.xml
+++ b/totp-impl/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>net.shibboleth.idp.plugin.authn</groupId>
         <artifactId>idp-plugin-totp</artifactId>
-        <version>1.0.3-SNAPSHOT</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
     
     <name>Shibboleth IdP :: Plugins :: TOTP Login Flow Impl</name>
@@ -30,55 +30,46 @@
                 
         <!-- provided dependencies -->
         <dependency>
-            <groupId>${slf4j.groupId}</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>javax.servlet-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>net.shibboleth.utilities</groupId>
-            <artifactId>java-support</artifactId>
+            <groupId>${idp.groupId}</groupId>
+            <artifactId>idp-admin-api</artifactId>
             <scope>provided</scope>
         </dependency>
+        <!-- Needed to allow module/plugin derivation. -->
         <dependency>
-            <groupId>${spring-webflow.groupId}</groupId>
-            <artifactId>spring-webflow</artifactId>
+            <groupId>${idp.groupId}</groupId>
+            <artifactId>idp-admin-impl</artifactId>
             <scope>provided</scope>
         </dependency>
+
         <dependency>
             <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-admin-api</artifactId>
+            <artifactId>idp-authn-api</artifactId>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-attribute-api</artifactId>
+            <artifactId>idp-cli</artifactId>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-attribute-resolver-api</artifactId>
+            <artifactId>idp-session-api</artifactId>
             <scope>provided</scope>
         </dependency>
+
         <dependency>
-            <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-authn-api</artifactId>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-profile-api</artifactId>
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-session-api</artifactId>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-attribute-api</artifactId>
             <scope>provided</scope>
         </dependency>
-
-        <!-- Needed to allow module/plugin derivation. -->
         <dependency>
-            <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-admin-impl</artifactId>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-attribute-resolver-api</artifactId>
             <scope>provided</scope>
         </dependency>
 
@@ -93,6 +84,33 @@
             <scope>provided</scope>
         </dependency>
         
+        <dependency>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-cli</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-support</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>${slf4j.groupId}</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>${spring-webflow.groupId}</groupId>
+            <artifactId>spring-webflow</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
         <dependency>
             <groupId>${spring.groupId}</groupId>
             <artifactId>spring-core</artifactId>
@@ -119,50 +137,43 @@
         <!-- test dependencies -->
         <dependency>
             <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-attribute-resolver-api</artifactId>
+            <artifactId>idp-authn-impl</artifactId>
             <scope>test</scope>
-            <type>test-jar</type>
         </dependency>
         <dependency>
             <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-attribute-resolver-impl</artifactId>
+            <artifactId>idp-testing</artifactId>
             <scope>test</scope>
         </dependency>
+
         <dependency>
-            <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-authn-impl</artifactId>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-attribute-resolver-impl</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-authn-impl</artifactId>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-attribute-testing</artifactId>
             <scope>test</scope>
-            <type>test-jar</type>
-        </dependency>
-        <dependency>
-            <groupId>${idp.groupId}</groupId>
-            <artifactId>idp-profile-api</artifactId>
-            <scope>test</scope>
-            <type>test-jar</type>
         </dependency>
+        
         <dependency>
             <groupId>${opensaml.groupId}</groupId>
-            <artifactId>opensaml-core</artifactId>
+            <artifactId>opensaml-core-impl</artifactId>
             <scope>test</scope>
-            <type>test-jar</type>
         </dependency>
         <dependency>
-            <groupId>net.shibboleth.utilities</groupId>
-            <artifactId>java-support</artifactId>
+            <groupId>${opensaml.groupId}</groupId>
+            <artifactId>opensaml-testing</artifactId>
             <scope>test</scope>
-            <type>test-jar</type>
         </dependency>
+        
         <dependency>
-            <groupId>net.shibboleth.ext</groupId>
-            <artifactId>spring-extensions</artifactId>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-testing</artifactId>
             <scope>test</scope>
-            <type>test-jar</type>
         </dependency>
+        
         <dependency>
             <groupId>${spring.groupId}</groupId>
             <artifactId>spring-test</artifactId>
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/TOTPModule.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/TOTPModule.java
index 43619c3..3e1fbad 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/TOTPModule.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/TOTPModule.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.plugin.authn.totp;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.PluginIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/TOTPPlugin.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/TOTPPlugin.java
index 9a8fd95..a1e0ad5 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/TOTPPlugin.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/TOTPPlugin.java
@@ -21,9 +21,9 @@ import java.io.IOException;
 import java.util.Collections;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
-import net.shibboleth.idp.plugin.PluginException;
 import net.shibboleth.idp.plugin.impl.FirstPartyIdPPlugin;
+import net.shibboleth.profile.module.ModuleException;
+import net.shibboleth.profile.plugin.PluginException;
 
 /**
  * Details about the TOTP login plugin.
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/context/TOTPContext.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/context/TOTPContext.java
index a783d30..e426bc1 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/context/TOTPContext.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/context/TOTPContext.java
@@ -27,9 +27,8 @@ import org.opensaml.messaging.context.BaseContext;
 
 import com.google.common.base.Strings;
 
-import net.shibboleth.utilities.java.support.annotation.constraint.Live;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.Live;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 
 /**
  * Context class for state of a TOTP validation.
@@ -43,7 +42,7 @@ public class TOTPContext extends BaseContext {
     @Nullable private Integer tokenCode;
 
     /** The raw token seeds associated with the subject. */
-    @Nonnull @NonnullElements private Collection<byte[]> tokenSeeds;
+    @Nonnull private Collection<byte[]> tokenSeeds;
 
     /** Constructor. */
     public TOTPContext() {
@@ -103,7 +102,7 @@ public class TOTPContext extends BaseContext {
      *
      * @return the token seeds
      */
-     @Nonnull @NonnullElements @Live public Collection<byte[]> getTokenSeeds() {
+     @Nonnull @Live public Collection<byte[]> getTokenSeeds() {
          return tokenSeeds;
      }
 
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/context/package-info.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/context/package-info.java
index e61a9cc..fe1642e 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/context/package-info.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/context/package-info.java
@@ -16,5 +16,7 @@
  */
 
 /** TOTP login flow context classes. */
-
+ at NonnullElements
 package net.shibboleth.idp.plugin.authn.totp.context;
+
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AbstractSeedSource.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AbstractSeedSource.java
index ba273c8..9f14983 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AbstractSeedSource.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AbstractSeedSource.java
@@ -27,11 +27,10 @@ import org.opensaml.profile.context.ProfileRequestContext;
 
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.plugin.authn.totp.context.TOTPContext;
-import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.logic.FunctionSupport;
+import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.component.AbstractInitializableComponent;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.FunctionSupport;
 
 /**
  * Base class for token seed source implementations.
@@ -82,7 +81,7 @@ public abstract class AbstractSeedSource extends AbstractInitializableComponent
      * @param enc encoding
      */
     public void setEncoding(@Nonnull final Encoding enc) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         encoding = Constraint.isNotNull(enc, "Encoding cannot be null");
     }
@@ -102,7 +101,7 @@ public abstract class AbstractSeedSource extends AbstractInitializableComponent
      * @param strategy lookup strategy
      */
     public void setTOTPContextLookupStrategy(@Nonnull final Function<ProfileRequestContext,TOTPContext> strategy) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         totpContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
     }
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AbstractTOTPExtractionAction.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AbstractTOTPExtractionAction.java
index ab1c4dd..ce7ba7b 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AbstractTOTPExtractionAction.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AbstractTOTPExtractionAction.java
@@ -21,7 +21,6 @@ import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
 
 import net.shibboleth.idp.authn.AbstractAuthenticationAction;
 import net.shibboleth.idp.authn.AuthnEventIds;
@@ -29,14 +28,15 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.authn.context.AuthenticationErrorContext;
 import net.shibboleth.idp.plugin.authn.totp.context.TOTPContext;
 import net.shibboleth.idp.session.context.navigate.CanonicalUsernameLookupStrategy;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpServletRequest;
 
 /**
 /**
@@ -76,7 +76,7 @@ public abstract class AbstractTOTPExtractionAction extends AbstractAuthenticatio
      * @param strategy lookup strategy
      */
     public void setUsernameLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         usernameLookupStrategy = Constraint.isNotNull(strategy, "Username lookup strategy cannot be null");
     }
@@ -87,7 +87,7 @@ public abstract class AbstractTOTPExtractionAction extends AbstractAuthenticatio
      * @param strategy lookup/creation strategy
      */
     public void setTOTPContextCreationStrategy(@Nonnull final Function<AuthenticationContext,TOTPContext> strategy) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         totpContextCreationStrategy = Constraint.isNotNull(strategy, "TOTPContext creation strategy cannot be null");
     }
@@ -131,8 +131,8 @@ public abstract class AbstractTOTPExtractionAction extends AbstractAuthenticatio
             totpContext.setTokenCode(Integer.valueOf(code));
         } catch (final NumberFormatException e) {
             log.warn("{} Exception converting code string to an integer", getLogPrefix(), e);
-            authenticationContext.getSubcontext(AuthenticationErrorContext.class,
-                    true).getClassifiedErrors().add(AuthnEventIds.INVALID_CREDENTIALS);
+            authenticationContext.ensureSubcontext(AuthenticationErrorContext.class).getClassifiedErrors().add(
+                    AuthnEventIds.INVALID_CREDENTIALS);
             ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_CREDENTIALS);
         }
     }
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AttributeResolverSeedSource.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AttributeResolverSeedSource.java
index 8a43d2d..f0f92ff 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AttributeResolverSeedSource.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/AttributeResolverSeedSource.java
@@ -25,24 +25,23 @@ import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.resolver.AttributeResolver;
 import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
 import net.shibboleth.idp.plugin.authn.totp.context.TOTPContext;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.utilities.java.support.codec.Base32Support;
-import net.shibboleth.utilities.java.support.codec.Base64Support;
-import net.shibboleth.utilities.java.support.codec.DecodingException;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-import net.shibboleth.utilities.java.support.service.ReloadableService;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.codec.Base32Support;
+import net.shibboleth.shared.codec.Base64Support;
+import net.shibboleth.shared.codec.DecodingException;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.shared.service.ReloadableService;
 
 /**
  * Token seed source implementation that leverages the {@link AttributeResolver}.
@@ -68,7 +67,7 @@ public class AttributeResolverSeedSource extends AbstractSeedSource {
      * @param service the resolver
      */
     public void setAttributeResolver(@Nonnull final ReloadableService<AttributeResolver> service) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         attributeResolver = Constraint.isNotNull(service, "AttributeResolver cannot be null");
     }
@@ -79,7 +78,7 @@ public class AttributeResolverSeedSource extends AbstractSeedSource {
      * @param id attribute ID
      */
     public void setSourceAttribute(@Nonnull @NotEmpty final String id) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         attributeId = Constraint.isNotNull(StringSupport.trimOrNull(id), "Source attribute ID cannot be null or empty");
     }
@@ -98,11 +97,11 @@ public class AttributeResolverSeedSource extends AbstractSeedSource {
 
     /** {@inheritDoc} */
     public void accept(@Nullable final ProfileRequestContext input) {
-        ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+        checkComponentActive();
         
         final TOTPContext totp = getTOTPContextLookupStrategy().apply(input);
         if (totp != null && totp.getUsername() != null) {
-            final AttributeResolutionContext resCtx = totp.getSubcontext(AttributeResolutionContext.class, true);
+            final AttributeResolutionContext resCtx = totp.ensureSubcontext(AttributeResolutionContext.class);
 
             resCtx.setResolutionLabel("TOTP");
             resCtx.setPrincipal(totp.getUsername());
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromFormRequest.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromFormRequest.java
index 70a166e..8200d3d 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromFormRequest.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromFormRequest.java
@@ -19,16 +19,15 @@ package net.shibboleth.idp.plugin.authn.totp.impl;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
-
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpServletRequest;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
 
 /**
  * An action that derives the TOTP code from a form parameter.
@@ -55,7 +54,7 @@ public class ExtractTOTPFromFormRequest extends AbstractTOTPExtractionAction {
      * @param field field name
      */
     public void setFieldName(@Nonnull @NotEmpty final String field) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         fieldName = Constraint.isNotNull(StringSupport.trimOrNull(field), "Field name cannot be null or empty");
     }
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromHeader.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromHeader.java
index f1fb03e..c5819bb 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromHeader.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromHeader.java
@@ -19,16 +19,15 @@ package net.shibboleth.idp.plugin.authn.totp.impl;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
-
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpServletRequest;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
 
 /**
  * An action that derives the TOTP code from an HTTP header.
@@ -55,7 +54,7 @@ public class ExtractTOTPFromHeader extends AbstractTOTPExtractionAction {
      * @param header header name
      */
     public void setHeaderName(@Nonnull @NotEmpty final String header) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         headerName = Constraint.isNotNull(StringSupport.trimOrNull(header), "Header name cannot be null or empty");
     }
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/GoogleTOTPAuthenticator.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/GoogleTOTPAuthenticator.java
index af321a3..889c61f 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/GoogleTOTPAuthenticator.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/GoogleTOTPAuthenticator.java
@@ -23,27 +23,26 @@ import java.util.Collection;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.utilities.java.support.codec.Base32Support;
-import net.shibboleth.utilities.java.support.codec.Base64Support;
-import net.shibboleth.utilities.java.support.codec.DecodingException;
-import net.shibboleth.utilities.java.support.codec.EncodingException;
-import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.net.UrlEscapers;
 import com.warrenstrange.googleauth.GoogleAuthenticator;
 import com.warrenstrange.googleauth.GoogleAuthenticatorConfig;
 import com.warrenstrange.googleauth.GoogleAuthenticatorKey;
 
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.codec.Base32Support;
+import net.shibboleth.shared.codec.Base64Support;
+import net.shibboleth.shared.codec.DecodingException;
+import net.shibboleth.shared.codec.EncodingException;
+import net.shibboleth.shared.component.AbstractInitializableComponent;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
+
 /**
  * A TOTP implementation based on Google Authenticator code.
  */
@@ -65,7 +64,7 @@ public class GoogleTOTPAuthenticator extends AbstractInitializableComponent impl
      * @param config configuration to use
      */
     public void setGoogleAuthenticatorConfig(@Nonnull final GoogleAuthenticatorConfig config) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         authconfig = Constraint.isNotNull(config, "GoogleAuthenticator cannot be null");
     }
@@ -82,7 +81,7 @@ public class GoogleTOTPAuthenticator extends AbstractInitializableComponent impl
     }
 
     /** {@inheritDoc} */
-    public TOTPCredential createCredential(@Nullable @NotEmpty final String issuer,
+    @Nonnull public TOTPCredential createCredential(@Nullable @NotEmpty final String issuer,
             @Nullable @NotEmpty final String accountName) throws GeneralSecurityException {
         
         final byte[] secret;
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/StaticSeedSource.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/StaticSeedSource.java
index 6fb1f6a..4c1089b 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/StaticSeedSource.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/StaticSeedSource.java
@@ -25,20 +25,18 @@ import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.LinkedListMultimap;
 import com.google.common.collect.Multimap;
 
 import net.shibboleth.idp.plugin.authn.totp.context.TOTPContext;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.utilities.java.support.codec.Base32Support;
-import net.shibboleth.utilities.java.support.codec.Base64Support;
-import net.shibboleth.utilities.java.support.codec.DecodingException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.codec.Base32Support;
+import net.shibboleth.shared.codec.Base64Support;
+import net.shibboleth.shared.codec.DecodingException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
 
 /**
  * Token seed source implementation that returns statically defined values.
@@ -50,7 +48,7 @@ public class StaticSeedSource extends AbstractSeedSource {
     @Nonnull private final Logger log = LoggerFactory.getLogger(StaticSeedSource.class);
     
     /** Token seeds. */
-    @Nonnull @NonnullElements private Multimap<String,byte[]> tokenSeeds;
+    @Nonnull private Multimap<String,byte[]> tokenSeeds;
     
     /** Constructor. */
     public StaticSeedSource() {
@@ -62,8 +60,8 @@ public class StaticSeedSource extends AbstractSeedSource {
      * 
      * @param seeds the seeds
      */
-    public void setSeeds(@Nonnull @NonnullElements final Map<String,Collection<String>> seeds) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+    public void setSeeds(@Nonnull final Map<String,Collection<String>> seeds) {
+        checkSetterPreconditions();
         Constraint.isNotNull(seeds, "Seed map cannot be null");
         
         seeds.forEach((k,v) -> {
@@ -93,7 +91,7 @@ public class StaticSeedSource extends AbstractSeedSource {
     
     /** {@inheritDoc} */
     public void accept(@Nullable final ProfileRequestContext input) {
-        ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+        checkComponentActive();
         
         final TOTPContext totp = getTOTPContextLookupStrategy().apply(input);
         if (totp != null) {
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticator.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticator.java
index 5db56b4..40c02d3 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticator.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticator.java
@@ -23,10 +23,9 @@ import java.util.Collection;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
-import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
 
 /**
  * Interface to a TOTP implementation's primitives.
@@ -57,7 +56,7 @@ public interface TOTPAuthenticator {
     boolean validate(@Nonnull @NotEmpty final byte[] secret, final int code);
     
     /** Interface to a TOTP credential. */
-    public interface TOTPCredential {
+    interface TOTPCredential {
         
         /**
          * Get the secret key.
@@ -78,7 +77,7 @@ public interface TOTPAuthenticator {
          *
          * @return the list of scratch codes
          */
-        @Nonnull @NonnullElements @Unmodifiable @NotLive Collection<Integer> getScratchCodes();
+        @Nonnull @Unmodifiable @NotLive Collection<Integer> getScratchCodes();
     }
 
 }
\ No newline at end of file
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticatorArguments.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticatorArguments.java
index db359c9..3dfed09 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticatorArguments.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticatorArguments.java
@@ -19,18 +19,19 @@ package net.shibboleth.idp.plugin.authn.totp.impl;
 
 import java.io.PrintStream;
 
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.beust.jcommander.Parameter;
 
 import net.shibboleth.idp.cli.AbstractIdPHomeAwareCommandLineArguments;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.codec.Base32Support;
-import net.shibboleth.utilities.java.support.codec.DecodingException;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.codec.Base32Support;
+import net.shibboleth.shared.codec.DecodingException;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
 
 /**
  * Arguments for {@link TOTPAuthenticatorCLI}.
@@ -61,7 +62,7 @@ public class TOTPAuthenticatorArguments extends AbstractIdPHomeAwareCommandLineA
     @Nullable private Logger log;
 
     /** {@inheritDoc} */
-    public Logger getLog() {
+    @Nonnull public Logger getLog() {
         if (log == null) {
             log = LoggerFactory.getLogger(TOTPAuthenticatorArguments.class);
         }
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticatorCLI.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticatorCLI.java
index 3e926e7..0b06f71 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticatorCLI.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPAuthenticatorCLI.java
@@ -21,15 +21,15 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.net.UrlEscapers;
 
 import net.shibboleth.idp.Version;
 import net.shibboleth.idp.cli.AbstractIdPHomeAwareCommandLine;
 import net.shibboleth.idp.plugin.authn.totp.impl.TOTPAuthenticator.TOTPCredential;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.codec.Base32Support;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.codec.Base32Support;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Command line utility for {@link TOTPAuthenticator}.
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPCredentialValidator.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPCredentialValidator.java
index 78200d0..86b68ca 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPCredentialValidator.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/TOTPCredentialValidator.java
@@ -29,7 +29,6 @@ import javax.security.auth.login.LoginException;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import net.shibboleth.idp.authn.AbstractCredentialValidator;
 import net.shibboleth.idp.authn.AuthnEventIds;
@@ -38,11 +37,11 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
 import net.shibboleth.idp.authn.principal.TOTPPrincipal;
 import net.shibboleth.idp.plugin.authn.totp.context.TOTPContext;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * A {@link CredentialValidator} that checks for a {@link TOTPContext}.
@@ -79,7 +78,7 @@ public class TOTPCredentialValidator extends AbstractCredentialValidator {
      */
     public void setTOTPContextLookupStrategy(
             @Nonnull final Function<AuthenticationContext,TOTPContext> strategy) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         totpContextLookupStrategy = Constraint.isNotNull(strategy, "TOTPContext lookup strategy cannot be null");
     }
@@ -90,7 +89,7 @@ public class TOTPCredentialValidator extends AbstractCredentialValidator {
      * @param impl TOTP implementation
      */
     public void setAuthenticator(@Nonnull final TOTPAuthenticator impl) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         authenticator = Constraint.isNotNull(impl, "TOTPAuthenticator cannot be null");
     }
@@ -101,7 +100,7 @@ public class TOTPCredentialValidator extends AbstractCredentialValidator {
      * @param source seed source
      */
     public void setSeedSource(@Nonnull final Consumer<ProfileRequestContext> source) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         seedSource = Constraint.isNotNull(source, "Token seed source cannot be null");
     }
@@ -112,7 +111,7 @@ public class TOTPCredentialValidator extends AbstractCredentialValidator {
      * @param expression a matching expression
      */
     public void setMatchExpression(@Nullable final Pattern expression) {
-        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        checkSetterPreconditions();
         
         matchExpression = expression;
     }
@@ -134,7 +133,6 @@ public class TOTPCredentialValidator extends AbstractCredentialValidator {
             @Nonnull final AuthenticationContext authenticationContext,
             @Nullable final WarningHandler warningHandler,
             @Nullable final ErrorHandler errorHandler) throws Exception {
-        ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
         
         final TOTPContext totpContext = totpContextLookupStrategy.apply(authenticationContext);
         if (totpContext == null) {
@@ -216,7 +214,7 @@ public class TOTPCredentialValidator extends AbstractCredentialValidator {
         subject.getPrincipals().add(new TOTPPrincipal(totpContext.getUsername()));
         
         // Bypass c14n. We already operate on a canonical name, so just re-confirm it.
-        profileRequestContext.getSubcontext(SubjectCanonicalizationContext.class, true).setPrincipalName(
+        profileRequestContext.ensureSubcontext(SubjectCanonicalizationContext.class).setPrincipalName(
                 totpContext.getUsername());
         
         return super.populateSubject(subject);
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/package-info.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/package-info.java
index 32df027..9003402 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/package-info.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/authn/totp/impl/package-info.java
@@ -16,5 +16,7 @@
  */
 
 /** TOTP login flow implementation classes. */
+ at NonnullElements
+package net.shibboleth.idp.plugin.authn.totp.impl;
 
-package net.shibboleth.idp.plugin.authn.totp.impl;
\ No newline at end of file
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
diff --git a/totp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/totp/module.properties b/totp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/totp/module.properties
index 4b131ee..1669548 100644
--- a/totp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/totp/module.properties
+++ b/totp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/totp/module.properties
@@ -12,10 +12,12 @@ idp.authn.TOTP.url = /TOTP
 idp.authn.TOTP.1.src = /net/shibboleth/idp/plugin/authn/totp/bin/totpauth.bat
 idp.authn.TOTP.1.dest = bin/totpauth.bat
 idp.authn.TOTP.1.replace = true
+idp.authn.TOTP.1.nonwindows = false
 idp.authn.TOTP.2.src = /net/shibboleth/idp/plugin/authn/totp/bin/totpauth.sh
 idp.authn.TOTP.2.dest = bin/totpauth.sh
 idp.authn.TOTP.2.replace = true
 idp.authn.TOTP.2.exec = true
+idp.authn.TOTP.2.windows = false
 idp.authn.TOTP.3.src = /net/shibboleth/idp/plugin/authn/totp/views/totp.vm
 idp.authn.TOTP.3.dest = views/totp.vm
 idp.authn.TOTP.3.optional = true
diff --git a/totp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/totp/plugin.properties b/totp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/totp/plugin.properties
index 65f96c1..cc3e5a9 100644
--- a/totp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/totp/plugin.properties
+++ b/totp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/totp/plugin.properties
@@ -2,7 +2,7 @@
 
 plugin.id = net.shibboleth.idp.plugin.authn.totp
 # Only used when package manifest is not available
-plugin.version = 1.0.2
+plugin.version = 2.0.0
 plugin.license =/net/shibboleth/idp/plugin/authn/totp/doc/GoogleAuth-LICENSE.txt
 
 # No prereqs
diff --git a/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/AttributeResolverSeedSourceTest.java b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/AttributeResolverSeedSourceTest.java
index d01c78a..b8674bc 100644
--- a/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/AttributeResolverSeedSourceTest.java
+++ b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/AttributeResolverSeedSourceTest.java
@@ -30,7 +30,6 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
-import net.shibboleth.ext.spring.testing.MockApplicationContext;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.resolver.AttributeDefinition;
@@ -40,12 +39,13 @@ import net.shibboleth.idp.attribute.resolver.testing.MockAttributeDefinition;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.plugin.authn.totp.context.TOTPContext;
 import net.shibboleth.idp.profile.testing.RequestContextBuilder;
-import net.shibboleth.utilities.java.support.codec.Base32Support;
-import net.shibboleth.utilities.java.support.codec.EncodingException;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.test.service.MockReloadableService;
+import net.shibboleth.shared.codec.Base32Support;
+import net.shibboleth.shared.codec.EncodingException;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.testing.MockReloadableService;
 
 /** Test case for {@link AttributeResolverSeedSource}. */
+ at SuppressWarnings("javadoc")
 public class AttributeResolverSeedSourceTest {
 
     private AttributeResolverSeedSource source;
@@ -91,7 +91,7 @@ public class AttributeResolverSeedSourceTest {
         // also does nothing
         source.accept(prc);
         
-        final TOTPContext totp = prc.getSubcontext(AuthenticationContext.class, true).getSubcontext(TOTPContext.class, true);
+        final TOTPContext totp = prc.ensureSubcontext(AuthenticationContext.class).ensureSubcontext(TOTPContext.class);
         source.accept(prc);
         assertTrue(totp.getTokenSeeds().isEmpty());
     }
@@ -102,7 +102,7 @@ public class AttributeResolverSeedSourceTest {
         source.initialize();
         
         final ProfileRequestContext prc = new RequestContextBuilder().buildProfileRequestContext();
-        final TOTPContext totp = prc.getSubcontext(AuthenticationContext.class, true).getSubcontext(TOTPContext.class, true);
+        final TOTPContext totp = prc.ensureSubcontext(AuthenticationContext.class).ensureSubcontext(TOTPContext.class);
         totp.setUsername("jdoe");
         source.accept(prc);
         
@@ -115,7 +115,7 @@ public class AttributeResolverSeedSourceTest {
         source.initialize();
         
         final ProfileRequestContext prc = new RequestContextBuilder().buildProfileRequestContext();
-        final TOTPContext totp = prc.getSubcontext(AuthenticationContext.class, true).getSubcontext(TOTPContext.class, true);
+        final TOTPContext totp = prc.ensureSubcontext(AuthenticationContext.class).ensureSubcontext(TOTPContext.class);
         totp.setUsername("jdoe");
         source.accept(prc);
         
@@ -129,7 +129,7 @@ public class AttributeResolverSeedSourceTest {
         source.initialize();
         
         final ProfileRequestContext prc = new RequestContextBuilder().buildProfileRequestContext();
-        final TOTPContext totp = prc.getSubcontext(AuthenticationContext.class, true).getSubcontext(TOTPContext.class, true);
+        final TOTPContext totp = prc.ensureSubcontext(AuthenticationContext.class).ensureSubcontext(TOTPContext.class);
         totp.setUsername("jdoe");
         source.accept(prc);
         
@@ -147,7 +147,6 @@ public class AttributeResolverSeedSourceTest {
         
         result.setAttributeDefinitions(definitions == null ? Collections.emptyList() : definitions);
         result.setDataConnectors(connectors == null ? Collections.emptyList() : connectors);
-        result.setApplicationContext(new MockApplicationContext());
         result.initialize();
         
         return result;
diff --git a/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/BaseAuthenticationContextTest.java b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/BaseAuthenticationContextTest.java
new file mode 100644
index 0000000..adf3801
--- /dev/null
+++ b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/BaseAuthenticationContextTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.totp.impl;
+
+import net.shibboleth.idp.authn.AbstractAuthenticationAction;
+import net.shibboleth.idp.authn.AuthenticationFlowDescriptor;
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.impl.PopulateAuthenticationContext;
+import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
+import net.shibboleth.idp.profile.testing.RequestContextBuilder;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.FunctionSupport;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.core.testing.OpenSAMLInitBaseTestCase;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.webflow.execution.RequestContext;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/** Base class for further action tests. */
+public class BaseAuthenticationContextTest extends OpenSAMLInitBaseTestCase {
+
+    protected RequestContext src;
+    protected ProfileRequestContext prc;
+    protected List<AuthenticationFlowDescriptor> authenticationFlows;
+
+    protected void initializeMembers() throws ComponentInitializationException {        
+        src = new RequestContextBuilder().buildRequestContext();
+        prc = new WebflowRequestContextProfileRequestContextLookup().apply(src);
+        prc.addSubcontext(new AuthenticationContext(), true);
+
+        authenticationFlows = List.of(new AuthenticationFlowDescriptor(),
+                new AuthenticationFlowDescriptor(), new AuthenticationFlowDescriptor());
+        authenticationFlows.get(0).setId("test1");
+        authenticationFlows.get(1).setId("test2");
+        authenticationFlows.get(1).setPassiveAuthenticationSupported(true);
+        authenticationFlows.get(2).setId("test3");
+    }
+
+    protected void setUp() throws ComponentInitializationException {        
+        initializeMembers();
+        
+        final PopulateAuthenticationContext action = new PopulateAuthenticationContext();
+        assert authenticationFlows!= null;
+        action.setAvailableFlows(authenticationFlows);
+        action.setPotentialFlowsLookupStrategy(FunctionSupport.constant(authenticationFlows));
+        action.initialize();
+
+        action.execute(src);
+    }
+
+    @Nonnull protected final MockHttpServletRequest getMockHttpServletRequest(final AbstractAuthenticationAction action) {
+        assert action != null;
+        final HttpServletRequest req = action.getHttpServletRequest();
+        assert req != null;
+        return (MockHttpServletRequest)req;
+    }
+
+}
\ No newline at end of file
diff --git a/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromFormRequestTest.java b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromFormRequestTest.java
index 65b5fd1..1e35257 100644
--- a/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromFormRequestTest.java
+++ b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromFormRequestTest.java
@@ -26,13 +26,14 @@ import org.testng.annotations.Test;
 
 import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.idp.authn.impl.testing.BaseAuthenticationContextTest;
 import net.shibboleth.idp.plugin.authn.totp.context.TOTPContext;
 import net.shibboleth.idp.profile.testing.ActionTestingSupport;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.logic.FunctionSupport;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.shared.testing.ConstantSupplier;
 
 /** {@link ExtractTOTPFromFormRequest} unit test. */
+ at SuppressWarnings("javadoc")
 public class ExtractTOTPFromFormRequestTest extends BaseAuthenticationContextTest {
     
     private ExtractTOTPFromFormRequest action; 
@@ -42,7 +43,8 @@ public class ExtractTOTPFromFormRequestTest extends BaseAuthenticationContextTes
         
         action = new ExtractTOTPFromFormRequest();
         action.setFieldName("Foo");
-        action.setHttpServletRequest(new MockHttpServletRequest());
+        final MockHttpServletRequest request = new MockHttpServletRequest();
+        action.setHttpServletRequestSupplier(new ConstantSupplier<>(request));
         action.setUsernameLookupStrategy(FunctionSupport.constant("jdoe"));
         action.initialize();
     }
diff --git a/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromHeaderTest.java b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromHeaderTest.java
index 2f7c9a9..c134d40 100644
--- a/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromHeaderTest.java
+++ b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/ExtractTOTPFromHeaderTest.java
@@ -26,13 +26,14 @@ import org.testng.annotations.Test;
 
 import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.idp.authn.impl.testing.BaseAuthenticationContextTest;
 import net.shibboleth.idp.plugin.authn.totp.context.TOTPContext;
 import net.shibboleth.idp.profile.testing.ActionTestingSupport;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.logic.FunctionSupport;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.shared.testing.ConstantSupplier;
 
 /** {@link ExtractTOTPFromHeader} unit test. */
+ at SuppressWarnings("javadoc")
 public class ExtractTOTPFromHeaderTest extends BaseAuthenticationContextTest {
     
     private ExtractTOTPFromHeader action; 
@@ -42,7 +43,8 @@ public class ExtractTOTPFromHeaderTest extends BaseAuthenticationContextTest {
         
         action = new ExtractTOTPFromHeader();
         action.setHeaderName("X-Foo");
-        action.setHttpServletRequest(new MockHttpServletRequest());
+        final MockHttpServletRequest request = new MockHttpServletRequest();
+        action.setHttpServletRequestSupplier(new ConstantSupplier<>(request));
         action.setUsernameLookupStrategy(FunctionSupport.constant("jdoe"));
         action.initialize();
     }
diff --git a/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/GoogleTOTPAuthenticatorTest.java b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/GoogleTOTPAuthenticatorTest.java
index d2b6f4e..a920917 100644
--- a/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/GoogleTOTPAuthenticatorTest.java
+++ b/totp-impl/src/test/java/net/shibboleth/idp/plugin/authn/totp/impl/GoogleTOTPAuthenticatorTest.java
@@ -29,13 +29,12 @@ import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.authn.context.AuthenticationErrorContext;
 import net.shibboleth.idp.authn.impl.ValidateCredentials;
-import net.shibboleth.idp.authn.impl.testing.BaseAuthenticationContextTest;
 import net.shibboleth.idp.authn.principal.TOTPPrincipal;
 import net.shibboleth.idp.plugin.authn.totp.context.TOTPContext;
 import net.shibboleth.idp.profile.testing.ActionTestingSupport;
-import net.shibboleth.utilities.java.support.codec.Base32Support;
-import net.shibboleth.utilities.java.support.codec.DecodingException;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.shared.codec.Base32Support;
+import net.shibboleth.shared.codec.DecodingException;
+import net.shibboleth.shared.component.ComponentInitializationException;
 
 import org.springframework.webflow.execution.Event;
 import org.testng.Assert;
@@ -46,6 +45,7 @@ import com.warrenstrange.googleauth.GoogleAuthenticator;
 import com.warrenstrange.googleauth.GoogleAuthenticatorKey;
 
 /** Unit test for {@link GoogleTOTPAuthenticator}. */
+ at SuppressWarnings("javadoc")
 public class GoogleTOTPAuthenticatorTest extends BaseAuthenticationContextTest {
     
     private GoogleTOTPAuthenticator authenticator;
@@ -91,7 +91,7 @@ public class GoogleTOTPAuthenticatorTest extends BaseAuthenticationContextTest {
     @Test public void testMissingUser() throws ComponentInitializationException {
         final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
         ac.setAttemptedFlow(authenticationFlows.get(0));
-        ac.getSubcontext(TOTPContext.class, true);
+        ac.ensureSubcontext(TOTPContext.class);
         
         validator.initialize();
         action.initialize();
@@ -104,7 +104,7 @@ public class GoogleTOTPAuthenticatorTest extends BaseAuthenticationContextTest {
     @Test public void testMissingCode() throws ComponentInitializationException {
         final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
         ac.setAttemptedFlow(authenticationFlows.get(0));
-        ac.getSubcontext(TOTPContext.class, true).setUsername("foo").getTokenSeeds().add("foo".getBytes());
+        ac.ensureSubcontext(TOTPContext.class).setUsername("foo").getTokenSeeds().add("foo".getBytes());
         
         validator.initialize();
         action.initialize();
@@ -116,7 +116,7 @@ public class GoogleTOTPAuthenticatorTest extends BaseAuthenticationContextTest {
     @Test public void testMissingSeeds() throws ComponentInitializationException {
         final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
         ac.setAttemptedFlow(authenticationFlows.get(0));
-        ac.getSubcontext(TOTPContext.class, true).setUsername("foo").setTokenCode(123456);
+        ac.ensureSubcontext(TOTPContext.class).setUsername("foo").setTokenCode(123456);
         
         validator.initialize();
         action.initialize();
@@ -128,7 +128,7 @@ public class GoogleTOTPAuthenticatorTest extends BaseAuthenticationContextTest {
     @Test public void testUnmatchedUser() throws Exception {
         final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
         ac.setAttemptedFlow(authenticationFlows.get(0));
-        ac.getSubcontext(TOTPContext.class, true).setUsername("bar").setTokenCode(123456).getTokenSeeds().add("foo".getBytes());
+        ac.ensureSubcontext(TOTPContext.class).setUsername("bar").setTokenCode(123456).getTokenSeeds().add("foo".getBytes());
         
         
         validator.setMatchExpression(Pattern.compile("foo.+"));
@@ -143,7 +143,7 @@ public class GoogleTOTPAuthenticatorTest extends BaseAuthenticationContextTest {
     @Test public void testInvalidSeed() throws ComponentInitializationException {
         final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
         ac.setAttemptedFlow(authenticationFlows.get(0));
-        ac.getSubcontext(TOTPContext.class, true).setUsername("foo").setTokenCode(123456).getTokenSeeds().add("foo".getBytes());
+        ac.ensureSubcontext(TOTPContext.class).setUsername("foo").setTokenCode(123456).getTokenSeeds().add("foo".getBytes());
         
         validator.initialize();
         action.initialize();
@@ -157,7 +157,7 @@ public class GoogleTOTPAuthenticatorTest extends BaseAuthenticationContextTest {
     @Test public void testInvalidCode() throws ComponentInitializationException, DecodingException {
         final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
         ac.setAttemptedFlow(authenticationFlows.get(0));
-        ac.getSubcontext(TOTPContext.class, true).setUsername("foo").setTokenCode(123456).getTokenSeeds().add(
+        ac.ensureSubcontext(TOTPContext.class).setUsername("foo").setTokenCode(123456).getTokenSeeds().add(
                 Base32Support.decode("G24YUKCHHXRDWCPR"));
         
         validator.initialize();
@@ -176,7 +176,7 @@ public class GoogleTOTPAuthenticatorTest extends BaseAuthenticationContextTest {
         final GoogleAuthenticator auth = new GoogleAuthenticator();
         final GoogleAuthenticatorKey creds = auth.createCredentials();
 
-        ac.getSubcontext(TOTPContext.class, true)
+        ac.ensureSubcontext(TOTPContext.class)
             .setUsername("foo")
             .setTokenCode(auth.getTotpPassword(creds.getKey()))
             .getTokenSeeds().add(Base32Support.decode(creds.getKey()));

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


More information about the commits mailing list