[java-identity-provider] 01/02: IDP-2069 Null handling

Rod Widdowson rdw at steadingsoftware.com
Thu Mar 2 11:04:09 UTC 2023


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

rdw 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=e9692a8f288e52a75adfa995f63c8f801909a027

commit e9692a8f288e52a75adfa995f63c8f801909a027
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Wed Mar 1 08:52:01 2023 +0000

    IDP-2069 Null handling
    
    https://shibboleth.atlassian.net/browse/IDP-2069
    
    Cleanup idp-saml-impl.
    
    Tests TBD.
---
 .../impl/EncryptionAlgorithmAuditExtractor.java    |  18 ++-
 .../audit/impl/MetadataProtocolAuditExtractor.java |   1 +
 .../idp/saml/audit/impl/NameIDAuditExtractor.java  |   2 +
 .../audit/impl/NameIDFormatAuditExtractor.java     |   2 +
 .../audit/impl/ProxyAudienceAuditExtractor.java    |   5 +-
 .../idp/saml/audit/impl/WriteFTICKSLog.java        |   9 +-
 .../MapDrivenAuthnContextTranslationStrategy.java  |  19 ++-
 .../InitializeRelyingPartyContextFromSAMLPeer.java |   7 +-
 .../idp/saml/nameid/impl/BaseTransientDecoder.java |   1 +
 .../impl/CryptoTransientIdGenerationStrategy.java  |  13 +-
 .../nameid/impl/CryptoTransientNameIDDecoder.java  |   5 +-
 .../impl/CryptoTransientNameIdentifierDecoder.java |   6 +-
 .../saml/nameid/impl/LegacyCanonicalization.java   |   3 +-
 .../saml/nameid/impl/NameIDCanonicalization.java   |   9 +-
 .../impl/NameIdentifierCanonicalization.java       |  11 +-
 .../impl/NameIdentifierGenerationServiceImpl.java  |   8 +-
 .../nameid/impl/StoredPersistentIdDecoder.java     |   7 +-
 .../nameid/impl/TransformingNameIDDecoder.java     |   4 +-
 .../impl/TransformingNameIdentifierDecoder.java    |   4 +-
 .../saml/nameid/impl/TransientIdParameters.java    |   5 +-
 .../saml/nameid/impl/TransientNameIDDecoder.java   |   9 +-
 .../impl/TransientNameIdentifierDecoder.java       |   9 +-
 .../TransientSAML1NameIdentifierGenerator.java     |   5 +-
 .../nameid/impl/TransientSAML2NameIDGenerator.java |   5 +-
 .../impl/BaseAddAttributeStatementToAssertion.java |  10 +-
 .../BaseAddAuthenticationStatementToAssertion.java |  16 +--
 .../BaseIdPInitiatedSSORequestMessageDecoder.java  |   2 +
 .../profile/impl/ExtractSubjectFromRequest.java    |  19 +--
 .../saml/profile/impl/IdPInitiatedSSORequest.java  |  12 +-
 .../impl/InitializeAuthenticationContext.java      |  18 +--
 .../impl/InitializeOutboundMessageContext.java     |  16 +--
 .../InitializeOutboundMessageContextForError.java  |  18 +--
 .../InitializeRelyingPartyContextFromSAMLPeer.java |   9 +-
 .../impl/PopulateBindingAndEndpointContexts.java   |  27 ++--
 .../PopulateInboundMessageContextWithSAMLSelf.java |   6 +-
 .../idp/saml/profile/impl/ReloadMetadata.java      |  16 ++-
 .../impl/SpringAwareMessageDecoderFactory.java     |   1 +
 .../impl/SpringAwareMessageEncoderFactory.java     |  20 +--
 .../profile/impl/UpdateSAMLSelfEntityContext.java  |  17 +--
 .../impl/AddAttributeStatementToAssertion.java     |  11 +-
 .../AddAuthenticationStatementToAssertion.java     |  17 +--
 .../impl/FilterByQueriedAttributeDesignators.java  |  34 +++--
 .../impl/IdPInitiatedSSORequestMessageDecoder.java |  13 +-
 ...ractSAML2ArtifactAwareProfileConfiguration.java |   4 +-
 .../impl/AbstractSAML2ProfileConfiguration.java    |   2 +-
 .../impl/AddAttributeStatementToAssertion.java     |   8 +-
 .../saml/saml2/profile/impl/AddAuthnRequest.java   |  23 ++--
 .../profile/impl/AddAuthnStatementToAssertion.java |  13 +-
 .../profile/impl/ContinueSAMLAuthentication.java   |  29 +++--
 .../profile/impl/EnforceDisallowedSSOFeatures.java |  15 ++-
 .../profile/impl/FilterByQueriedAttributes.java    |  17 +--
 .../impl/IdPInitiatedSSORequestMessageDecoder.java |  14 ++-
 ...estedAttributesInAttributeConsumingService.java |   8 +-
 .../profile/impl/PopulateEncryptionParameters.java |  31 +++--
 .../profile/impl/PreProcessLogoutMessage.java      |  16 ++-
 .../impl/ProcessAssertionsForAuthentication.java   |  17 ++-
 .../saml2/profile/impl/ProcessLogoutRequest.java   |  43 ++++---
 .../profile/impl/ProcessRequestedAuthnContext.java |  21 ++--
 .../saml2/profile/impl/SAMLAuthnController.java    |  28 +++--
 .../saml/saml2/profile/impl/SOAPLogoutRequest.java |  42 +++++--
 .../profile/impl/ValidateSAMLAuthentication.java   | 139 ++++++++++++++-------
 .../idp/saml/session/impl/AddLogoutRequest.java    |  15 ++-
 .../impl/BestMatchLocationLookupStrategy.java      |   6 +-
 .../session/impl/PrepareInboundMessageContext.java |   9 +-
 .../impl/SAML2SPSessionCreationStrategy.java       |  25 ++--
 .../session/impl/SAML2SPSessionSerializer.java     |   2 +-
 66 files changed, 621 insertions(+), 355 deletions(-)

diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/EncryptionAlgorithmAuditExtractor.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/EncryptionAlgorithmAuditExtractor.java
index 590784d15..b952abfd6 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/EncryptionAlgorithmAuditExtractor.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/EncryptionAlgorithmAuditExtractor.java
@@ -25,6 +25,7 @@ import javax.annotation.Nullable;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.saml.saml2.profile.context.EncryptionContext;
+import org.opensaml.xmlsec.EncryptionParameters;
 
 import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.shared.logic.Constraint;
@@ -58,12 +59,17 @@ public class EncryptionAlgorithmAuditExtractor implements Function<ProfileReques
         
         final EncryptionContext encryptionCtx = encryptionContextLookupStrategy.apply(input);
         if (encryptionCtx != null) {
-            if (encryptionCtx.getAssertionEncryptionParameters() != null) {
-                return encryptionCtx.getAssertionEncryptionParameters().getDataEncryptionAlgorithm();
-            } else if (encryptionCtx.getAttributeEncryptionParameters() != null) {
-                return encryptionCtx.getAttributeEncryptionParameters().getDataEncryptionAlgorithm();
-            } else if (encryptionCtx.getIdentifierEncryptionParameters() != null) {
-                return encryptionCtx.getIdentifierEncryptionParameters().getDataEncryptionAlgorithm();
+            final EncryptionParameters assertionParams = encryptionCtx.getAssertionEncryptionParameters();
+            if (assertionParams != null) {
+                return assertionParams.getDataEncryptionAlgorithm();
+            }
+            final EncryptionParameters attributeParams = encryptionCtx.getAttributeEncryptionParameters();
+            if (attributeParams != null) {
+                return attributeParams.getDataEncryptionAlgorithm();
+            }
+            final EncryptionParameters idParams =encryptionCtx.getIdentifierEncryptionParameters();
+            if (idParams != null) {
+                return idParams.getDataEncryptionAlgorithm();
             }
         }
         return null;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/MetadataProtocolAuditExtractor.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/MetadataProtocolAuditExtractor.java
index db9e7582d..c3e1091eb 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/MetadataProtocolAuditExtractor.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/MetadataProtocolAuditExtractor.java
@@ -32,6 +32,7 @@ public class MetadataProtocolAuditExtractor implements Function<ProfileRequestCo
 
     /** {@inheritDoc} */
     @Nullable public Object apply(@Nullable final ProfileRequestContext input) {
+        assert input != null;
         final SpringRequestContext springCtx = input.getSubcontext(SpringRequestContext.class);
         if (springCtx == null) {
             return null;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/NameIDAuditExtractor.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/NameIDAuditExtractor.java
index 377996f60..1a8d0ca07 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/NameIDAuditExtractor.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/NameIDAuditExtractor.java
@@ -64,6 +64,7 @@ public class NameIDAuditExtractor implements Function<ProfileRequestContext,Stri
                 
                 for (final org.opensaml.saml.saml2.core.Assertion assertion
                         : ((org.opensaml.saml.saml2.core.Response) msg).getAssertions()) {
+                    assert assertion != null;
                     final String id = apply(assertion);
                     if (id != null) {
                         return id;
@@ -86,6 +87,7 @@ public class NameIDAuditExtractor implements Function<ProfileRequestContext,Stri
 
                 for (final org.opensaml.saml.saml1.core.Assertion assertion
                         : ((org.opensaml.saml.saml1.core.Response) msg).getAssertions()) {
+                    assert assertion != null;
                     final String id = apply(assertion);
                     if (id != null) {
                         return id;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/NameIDFormatAuditExtractor.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/NameIDFormatAuditExtractor.java
index 7d8350c51..d8ef5aef5 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/NameIDFormatAuditExtractor.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/NameIDFormatAuditExtractor.java
@@ -64,6 +64,7 @@ public class NameIDFormatAuditExtractor implements Function<ProfileRequestContex
                 
                 for (final org.opensaml.saml.saml2.core.Assertion assertion
                         : ((org.opensaml.saml.saml2.core.Response) msg).getAssertions()) {
+                    assert assertion != null;
                     final String format = apply(assertion);
                     if (format != null) {
                         return format;
@@ -87,6 +88,7 @@ public class NameIDFormatAuditExtractor implements Function<ProfileRequestContex
 
                 for (final org.opensaml.saml.saml1.core.Assertion assertion
                         : ((org.opensaml.saml.saml1.core.Response) msg).getAssertions()) {
+                    assert assertion != null;
                     final String format = apply(assertion);
                     if (format != null) {
                         return format;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/ProxyAudienceAuditExtractor.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/ProxyAudienceAuditExtractor.java
index fa0618703..9f6be4de2 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/ProxyAudienceAuditExtractor.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/ProxyAudienceAuditExtractor.java
@@ -18,6 +18,7 @@
 package net.shibboleth.idp.saml.audit.impl;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -50,7 +51,9 @@ public class ProxyAudienceAuditExtractor extends AbstractProxyRestrictionAuditEx
     @Override
     @Nullable protected Collection<String> doApply(@Nullable final ProxyRestriction condition) {
         if (condition != null) {
-            return condition.getAudiences().stream()
+            final List<Audience> audiences = condition.getAudiences();
+            assert audiences != null;
+            return audiences.stream()
                     .map(Audience::getURI)
                     .collect(Collectors.toUnmodifiableList());
         }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/WriteFTICKSLog.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/WriteFTICKSLog.java
index 201be22e3..06b754000 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/WriteFTICKSLog.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/audit/impl/WriteFTICKSLog.java
@@ -54,13 +54,13 @@ public class WriteFTICKSLog extends AbstractProfileAction {
     @Nonnull @NotEmpty public static final String FTICKS_LOG_CATEGORY = "Shibboleth-FTICKS";
     
     /** Strategy used to locate the {@link AuditContext} associated with a given {@link ProfileRequestContext}. */
-    @Nonnull private Function<ProfileRequestContext,AuditContext> auditContextLookupStrategy;
+    private Function<ProfileRequestContext,AuditContext> auditContextLookupStrategy;
 
     /** Federation ID for log. */
     @NonnullAfterInit @NotEmpty private String federationId;
     
     /** Digest algorithm for username hashing. */
-    @Nonnull @NotEmpty private String digestAlgorithm;
+    @NonnullAfterInit @NotEmpty private String digestAlgorithm;
 
     /** Salt for username hashing. */
     @Nullable private String salt;
@@ -186,8 +186,13 @@ public class WriteFTICKSLog extends AbstractProfileAction {
         if (federationId == null) {
             throw new ComponentInitializationException("Federation ID cannot be null or empty.");
         }
+        
+        if (digestAlgorithm == null) {
+            throw new ComponentInitializationException("Digest Algorithm cannot be null or empty.");
+        }
 
         try {
+            assert digestAlgorithm != null;
             digester = new StringDigester(digestAlgorithm, StringDigester.OutputFormat.HEX_LOWER);
             digester.setSalt(salt);
             digester.setRequireSalt(true);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/MapDrivenAuthnContextTranslationStrategy.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/MapDrivenAuthnContextTranslationStrategy.java
index bbd223622..e7f9f04d3 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/MapDrivenAuthnContextTranslationStrategy.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/MapDrivenAuthnContextTranslationStrategy.java
@@ -30,11 +30,14 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.opensaml.saml.saml2.core.AuthnContext;
+import org.opensaml.saml.saml2.core.AuthnContextClassRef;
+import org.opensaml.saml.saml2.core.AuthnContextDeclRef;
 import org.slf4j.Logger;
 
 import net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal;
 import net.shibboleth.idp.saml.authn.principal.AuthnContextDeclRefPrincipal;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
@@ -53,7 +56,7 @@ public class MapDrivenAuthnContextTranslationStrategy implements Function<AuthnC
     
     /** Constructor. */
     public MapDrivenAuthnContextTranslationStrategy() {
-        principalMappings = Collections.emptyMap();
+        principalMappings = CollectionSupport.emptyMap();
     }
     
     /**
@@ -65,7 +68,7 @@ public class MapDrivenAuthnContextTranslationStrategy implements Function<AuthnC
      */
     public void setMappings(@Nullable @NonnullElements final Map<Principal,Collection<Principal>> mappings) {
         if (mappings == null || mappings.isEmpty()) {
-            principalMappings = Collections.emptyMap();
+            principalMappings = CollectionSupport.emptyMap();
             return;
         }
         
@@ -78,11 +81,15 @@ public class MapDrivenAuthnContextTranslationStrategy implements Function<AuthnC
         
         if (input != null) {
             final Principal principal;
+            final AuthnContextClassRef classRef = input.getAuthnContextClassRef();
+            final String classRefURI = classRef == null ? null : classRef.getURI();
+            final AuthnContextDeclRef declRef = input.getAuthnContextDeclRef();
+            final String declRefURI = declRef == null ? null : declRef.getURI();
             
-            if (input.getAuthnContextClassRef() != null && input.getAuthnContextClassRef().getURI() != null) {
-                principal = new AuthnContextClassRefPrincipal(input.getAuthnContextClassRef().getURI());
-            } else if (input.getAuthnContextDeclRef() != null && input.getAuthnContextDeclRef().getURI() != null) {
-                principal = new AuthnContextDeclRefPrincipal(input.getAuthnContextDeclRef().getURI());
+            if (classRefURI != null) {
+                principal = new AuthnContextClassRefPrincipal(classRefURI);
+            } else if (declRefURI != null) {
+                principal = new AuthnContextDeclRefPrincipal(declRefURI);
             } else {
                 log.trace("Input AuthnContext did not contain a class or decl reference, returning nothing");
                 return null;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/messaging/impl/InitializeRelyingPartyContextFromSAMLPeer.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/messaging/impl/InitializeRelyingPartyContextFromSAMLPeer.java
index d0dc22180..00f7c78f9 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/messaging/impl/InitializeRelyingPartyContextFromSAMLPeer.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/messaging/impl/InitializeRelyingPartyContextFromSAMLPeer.java
@@ -122,10 +122,11 @@ public class InitializeRelyingPartyContextFromSAMLPeer extends AbstractMessageHa
             log.debug("{} Unable to locate or create RelyingPartyContext", getLogPrefix());
             throw new MessageHandlerException("Unable to locate or create RelyingPartyContext");
         }
-        
+        final SAMLPeerEntityContext pec = peerEntityCtx; 
+        assert pec != null;
         log.debug("{} Attaching RelyingPartyContext based on SAML peer {}", getLogPrefix(),
-                peerEntityCtx.getEntityId());
-        rpContext.setRelyingPartyIdContextTree(peerEntityCtx);
+                pec.getEntityId());
+        rpContext.setRelyingPartyIdContextTree(pec);
         rpContext.setRelyingPartyIdLookupStrategy(RPID_LOOKUP);
         rpContext.setVerificationLookupStrategy(VERIFY_LOOKUP);
     }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/BaseTransientDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/BaseTransientDecoder.java
index 67f36729f..484473e53 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/BaseTransientDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/BaseTransientDecoder.java
@@ -130,6 +130,7 @@ public abstract class BaseTransientDecoder extends AbstractIdentifiableInitializ
         if (null == prefix) {
             final StringBuilder builder = new StringBuilder("Transient Decoder '").append(getId()).append("':");
             prefix = builder.toString();
+            assert prefix !=null;
             if (null == logPrefix) {
                 logPrefix = prefix;
             }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientIdGenerationStrategy.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientIdGenerationStrategy.java
index b08f41989..dadc4cfcf 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientIdGenerationStrategy.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientIdGenerationStrategy.java
@@ -23,14 +23,12 @@ import java.time.Instant;
 import javax.annotation.Nonnull;
 
 import org.opensaml.saml.common.SAMLException;
-import org.slf4j.Logger;
 
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.security.DataSealer;
 import net.shibboleth.shared.security.DataSealerException;
 
@@ -41,9 +39,6 @@ import net.shibboleth.shared.security.DataSealerException;
 public class CryptoTransientIdGenerationStrategy extends AbstractIdentifiableInitializableComponent
         implements TransientIdGenerationStrategy {
 
-    /** Class logger. */
-    @Nonnull private final Logger log = LoggerFactory.getLogger(CryptoTransientIdGenerationStrategy.class);
-
     /** Object used to protect and encrypt the data. */
     @NonnullAfterInit private DataSealer dataSealer;
 
@@ -52,7 +47,9 @@ public class CryptoTransientIdGenerationStrategy extends AbstractIdentifiableIni
 
     /** Constructor. */
     public CryptoTransientIdGenerationStrategy() {
-        idLifetime = Duration.ofHours(4);
+        final Duration fourHours = Duration.ofHours(4);
+        assert fourHours!=null;
+        idLifetime = fourHours;
     }
 
     /**
@@ -105,7 +102,9 @@ public class CryptoTransientIdGenerationStrategy extends AbstractIdentifiableIni
         principalTokenIdBuilder.append(relyingPartyId).append("!").append(principalName);
 
         try {
-            return dataSealer.wrap(principalTokenIdBuilder.toString(), Instant.now().plus(idLifetime));
+            final String result = principalTokenIdBuilder.toString();
+            assert result!=null;
+            return dataSealer.wrap(result, Instant.now().plus(idLifetime));
         } catch (final DataSealerException e) {
             throw new SAMLException("Exception wrapping principal identifier", e);
         }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientNameIDDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientNameIDDecoder.java
index 552484386..db1229a84 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientNameIDDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientNameIDDecoder.java
@@ -40,7 +40,10 @@ public class CryptoTransientNameIDDecoder extends BaseCryptoTransientDecoder imp
     @Nullable @NotEmpty public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
             @Nonnull final NameID nameID) throws NameDecoderException {
 
-        return super.decode(nameID.getValue(), c14nContext.getRequesterId());
+        final String value = nameID.getValue();
+        final String requesterId = c14nContext.getRequesterId();
+        assert value != null && requesterId!= null;
+        return super.decode(value, requesterId);
     }
 
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientNameIdentifierDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientNameIdentifierDecoder.java
index 849f30efb..4e7b13774 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientNameIdentifierDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/CryptoTransientNameIdentifierDecoder.java
@@ -39,7 +39,11 @@ public class CryptoTransientNameIdentifierDecoder extends BaseCryptoTransientDec
     @Nullable @NotEmpty public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
             @Nonnull final NameIdentifier nameIdentifier) throws NameDecoderException {
 
-        return super.decode(nameIdentifier.getValue(), c14nContext.getRequesterId());
+        final String val = nameIdentifier.getValue();
+        final String id = c14nContext.getRequesterId();
+        assert val != null &&id != null;
+        
+        return super.decode(val, id);
     }
 
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/LegacyCanonicalization.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/LegacyCanonicalization.java
index 757b88aaf..35e04b16c 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/LegacyCanonicalization.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/LegacyCanonicalization.java
@@ -29,6 +29,7 @@ import net.shibboleth.idp.authn.AbstractSubjectCanonicalizationAction;
 import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
 import net.shibboleth.idp.saml.nameid.NameIDCanonicalizationFlowDescriptor;
+import net.shibboleth.shared.logic.PredicateSupport;
 import net.shibboleth.shared.primitive.DeprecationSupport;
 import net.shibboleth.shared.primitive.DeprecationSupport.ObjectType;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -62,7 +63,7 @@ public class LegacyCanonicalization extends AbstractSubjectCanonicalizationActio
         // V4 deprecation, remove this class in V5.
         DeprecationSupport.warn(ObjectType.BEAN, "c14n/LegacyPrincipalConnector", "c14n/subject-c14n.xml", "<remove>");
         final NameIDCanonicalizationFlowDescriptor result = new NameIDCanonicalizationFlowDescriptor();
-        result.setActivationCondition(Predicates.alwaysFalse());
+        result.setActivationCondition(PredicateSupport.alwaysFalse());
         return result;
     }
     
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIDCanonicalization.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIDCanonicalization.java
index 945534e41..7f3fa2117 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIDCanonicalization.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIDCanonicalization.java
@@ -22,6 +22,7 @@ import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.security.auth.Subject;
 
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -115,7 +116,9 @@ public class NameIDCanonicalization extends AbstractSubjectCanonicalizationActio
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final SubjectCanonicalizationContext c14nContext) {
 
-        final Set<NameIDPrincipal> nameIDs = c14nContext.getSubject().getPrincipals(NameIDPrincipal.class);
+        final Subject subject = c14nContext.getSubject();
+        assert subject != null;
+        final Set<NameIDPrincipal> nameIDs = subject.getPrincipals(NameIDPrincipal.class);
         final NameID nameID = nameIDs.iterator().next().getNameID();
 
         try {
@@ -207,7 +210,9 @@ public class NameIDCanonicalization extends AbstractSubjectCanonicalizationActio
 
             Set<NameIDPrincipal> nameIDs = null;
             if (c14nContext.getSubject() != null) {
-                nameIDs = c14nContext.getSubject().getPrincipals(NameIDPrincipal.class);
+                final Subject subject = c14nContext.getSubject();
+                assert subject != null;
+                nameIDs = subject.getPrincipals(NameIDPrincipal.class);
             }
 
             if (nameIDs == null || nameIDs.isEmpty()) {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIdentifierCanonicalization.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIdentifierCanonicalization.java
index 27eb6553f..545fb29d4 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIdentifierCanonicalization.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIdentifierCanonicalization.java
@@ -22,6 +22,7 @@ import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.security.auth.Subject;
 
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -114,8 +115,10 @@ public class NameIdentifierCanonicalization extends AbstractSubjectCanonicalizat
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final SubjectCanonicalizationContext c14nContext) {
 
+        final Subject subject = c14nContext.getSubject();
+        assert subject != null;
         final Set<NameIdentifierPrincipal> nameIdentifiers =
-                c14nContext.getSubject().getPrincipals(NameIdentifierPrincipal.class);
+                subject.getPrincipals(NameIdentifierPrincipal.class);
         final NameIdentifier nameIdentifier = nameIdentifiers.iterator().next().getNameIdentifier();
 
         try {
@@ -206,8 +209,10 @@ public class NameIdentifierCanonicalization extends AbstractSubjectCanonicalizat
                 @Nonnull final SubjectCanonicalizationContext c14nContext, final boolean duringAction) {
 
             Set<NameIdentifierPrincipal> nameIdentifiers = null;
-            if (c14nContext.getSubject() != null) {
-                nameIdentifiers = c14nContext.getSubject().getPrincipals(NameIdentifierPrincipal.class);
+            final Subject subject = c14nContext.getSubject();
+
+            if (subject != null) {
+                nameIdentifiers = subject.getPrincipals(NameIdentifierPrincipal.class);
             }
 
             if (nameIdentifiers == null || nameIdentifiers.isEmpty()) {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIdentifierGenerationServiceImpl.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIdentifierGenerationServiceImpl.java
index 292c9c738..0d6ae659e 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIdentifierGenerationServiceImpl.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/NameIdentifierGenerationServiceImpl.java
@@ -68,13 +68,17 @@ public class NameIdentifierGenerationServiceImpl extends AbstractIdentifiableIni
 
     /** {@inheritDoc} */
     @Override
-    public SAML1NameIdentifierGenerator getSAML1NameIdentifierGenerator() {
+    public @Nonnull SAML1NameIdentifierGenerator getSAML1NameIdentifierGenerator() {
+        checkComponentActive();
+        assert saml1Generator!=null;
         return saml1Generator;
     }
 
     /** {@inheritDoc} */
     @Override
-    public SAML2NameIDGenerator getSAML2NameIDGenerator() {
+    public @Nonnull SAML2NameIDGenerator getSAML2NameIDGenerator() {
+        checkComponentActive();
+        assert saml2Generator!=null;
         return saml2Generator;
     }
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/StoredPersistentIdDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/StoredPersistentIdDecoder.java
index f2f76898e..06803d061 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/StoredPersistentIdDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/StoredPersistentIdDecoder.java
@@ -79,12 +79,13 @@ public class StoredPersistentIdDecoder extends AbstractIdentifiableInitializable
         super.doInitialize();
     
         if (null == pidStore) {
-            if (dataSource != null) {
+            final DataSource ds = dataSource;
+            if (ds != null) {
                 log.debug("Creating JDBCPairwiseIdStore instance around supplied DataSource");
                 final JDBCPairwiseIdStore newStore = new JDBCPairwiseIdStore();
                 // Don't validate the database because this side is just reading data.
                 newStore.setVerifyDatabase(false);
-                newStore.setDataSource(dataSource);
+                newStore.setDataSource(ds);
                 newStore.initialize();
                 pidStore = newStore;
             }
@@ -96,7 +97,7 @@ public class StoredPersistentIdDecoder extends AbstractIdentifiableInitializable
     }
 
     /** {@inheritDoc} */
-    @Nonnull @NotEmpty public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
+    @Nullable @NotEmpty public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
             @Nonnull final NameID nameID) throws NameDecoderException {
         checkComponentActive();
 
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransformingNameIDDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransformingNameIDDecoder.java
index 214aac95d..9710270fe 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransformingNameIDDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransformingNameIDDecoder.java
@@ -34,7 +34,9 @@ public class TransformingNameIDDecoder extends BaseTransformingDecoder implement
     @Nullable public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
             @Nonnull final NameID nameIdentifier) throws NameDecoderException {
         
-        return decode(nameIdentifier.getValue());
+        final String value = nameIdentifier.getValue();
+        assert value != null;
+        return decode(value);
     }
 
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransformingNameIdentifierDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransformingNameIdentifierDecoder.java
index 95a50dd49..014ceaddb 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransformingNameIdentifierDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransformingNameIdentifierDecoder.java
@@ -34,7 +34,9 @@ public class TransformingNameIdentifierDecoder extends BaseTransformingDecoder i
     @Nullable public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
             @Nonnull final NameIdentifier nameIdentifier) throws NameDecoderException {
         
-        return decode(nameIdentifier.getValue());
+        final String value = nameIdentifier.getValue();
+        assert value != null;
+        return decode(value);
     }
     
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientIdParameters.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientIdParameters.java
index d165e6878..b84f5d960 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientIdParameters.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientIdParameters.java
@@ -123,8 +123,9 @@ public class TransientIdParameters {
             gen.writeStartObject().write(ATTRIBUTE_RECIPIENT_FIELD, getAttributeRecipient())
                     .write(PRINCIPAL_FIELD, getPrincipal());
             gen.writeEnd().close();
-
-            return sink.toString();
+            final String result = sink.toString();
+            assert result != null;
+            return result;
         } catch (final JsonException e) {
             log.error("Exception while serializing TransientID: {}", e.getMessage());
             throw new IOException("Exception while serializing TransientID", e);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientNameIDDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientNameIDDecoder.java
index c6fcae3c5..b2da459ba 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientNameIDDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientNameIDDecoder.java
@@ -18,6 +18,7 @@
 package net.shibboleth.idp.saml.nameid.impl;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
 import net.shibboleth.idp.saml.nameid.NameDecoderException;
@@ -34,10 +35,14 @@ public class TransientNameIDDecoder extends BaseTransientDecoder implements Name
 
     /** {@inheritDoc} */
     @Override
-    @Nonnull @NotEmpty public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
+    @Nullable @NotEmpty public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
             @Nonnull final NameID nameID) throws NameDecoderException {
 
-        return super.decode(nameID.getValue(), c14nContext.getRequesterId());
+        final String value = nameID.getValue();
+        final String id = c14nContext.getRequesterId();
+        assert value != null && id != null;
+
+        return super.decode(value, id);
     }
 
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientNameIdentifierDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientNameIdentifierDecoder.java
index 6cdb55672..7ba7f83fa 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientNameIdentifierDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientNameIdentifierDecoder.java
@@ -18,6 +18,7 @@
 package net.shibboleth.idp.saml.nameid.impl;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
 import net.shibboleth.idp.saml.nameid.NameDecoderException;
@@ -33,10 +34,14 @@ public class TransientNameIdentifierDecoder extends BaseTransientDecoder impleme
 
     /** {@inheritDoc} */
     @Override
-    @Nonnull public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
+    @Nullable public String decode(@Nonnull final SubjectCanonicalizationContext c14nContext,
             @Nonnull final NameIdentifier nameIdentifier) throws NameDecoderException {
 
-        return super.decode(nameIdentifier.getValue(), c14nContext.getRequesterId());
+        final String value = nameIdentifier.getValue();
+        final String id = c14nContext.getRequesterId();
+        assert value != null && id != null;
+
+        return super.decode(value, id);
     }
 
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientSAML1NameIdentifierGenerator.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientSAML1NameIdentifierGenerator.java
index d3d83a0af..7f139c7d6 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientSAML1NameIdentifierGenerator.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientSAML1NameIdentifierGenerator.java
@@ -103,13 +103,14 @@ public class TransientSAML1NameIdentifierGenerator extends AbstractSAML1NameIden
         }
 
         final SubjectContext subjectCtx = subjectContextLookupStrategy.apply(profileRequestContext);
-        if (subjectCtx == null || subjectCtx.getPrincipalName() == null) {
+        final String principalName = subjectCtx == null ? null : subjectCtx.getPrincipalName();
+        if (principalName  == null) {
             log.debug("No principal name available, can't generate transient ID");
             return null;
         }
 
         try {
-            return transientIdGenerator.generate(relyingPartyId, subjectCtx.getPrincipalName());
+            return transientIdGenerator.generate(relyingPartyId, principalName);
         } catch (final SAMLException e) {
             log.debug("Exception generating transient ID", e);
             return null;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientSAML2NameIDGenerator.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientSAML2NameIDGenerator.java
index 2186e89f3..5edaf7429 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientSAML2NameIDGenerator.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/nameid/impl/TransientSAML2NameIDGenerator.java
@@ -108,13 +108,14 @@ public class TransientSAML2NameIDGenerator extends AbstractSAML2NameIDGenerator
         }
 
         final SubjectContext subjectCtx = subjectContextLookupStrategy.apply(profileRequestContext);
-        if (subjectCtx == null || subjectCtx.getPrincipalName() == null) {
+        final String principalName = subjectCtx == null ? null : subjectCtx.getPrincipalName();
+        if (principalName == null) {
             log.debug("No principal name available, can't generate transient ID");
             return null;
         }
 
         try {
-            return transientIdGenerator.generate(relyingPartyId, subjectCtx.getPrincipalName());
+            return transientIdGenerator.generate(relyingPartyId, principalName);
         } catch (final SAMLException e) {
             log.debug("Exception generating transient ID", e);
             return null;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
index 22cd5d083..620587025 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
@@ -222,8 +222,7 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
      * @return the context to encode
      */
     @Nonnull public AttributeContext getAttributeContext() {
-        Constraint.isNotNull(attributeCtx, "AttributeContext has not been initialized yet");
-        return attributeCtx;
+        return Constraint.isNotNull(attributeCtx, "AttributeContext has not been initialized yet");
     }
 
     /**
@@ -232,8 +231,7 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
      * @return the ID generation strategy
      */
     @Nonnull public IdentifierGenerationStrategy getIdGenerator() {
-        Constraint.isNotNull(idGenerator, "IdentifierGenerationStrategy has not been initialized yet");
-        return idGenerator;
+        return Constraint.isNotNull(idGenerator, "IdentifierGenerationStrategy has not been initialized yet");
     }
 
     /**
@@ -242,8 +240,7 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
      * @return the issuer name
      */
     @Nonnull @NotEmpty public String getIssuerId() {
-        Constraint.isNotNull(issuerId, "Issuer name has not been initialized yet");
-        return issuerId;
+        return Constraint.isNotNull(issuerId, "Issuer name has not been initialized yet");
     }
 
     /** {@inheritDoc} */
@@ -318,6 +315,7 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
         
         for (final TranscodingRule rules : transcodingRules) {
             try {
+                assert rules != null;
                 final AttributeTranscoder<T> transcoder = TranscoderSupport.<T>getTranscoder(rules);
                 final T encodedAttribute = transcoder.encode(profileRequestContext, attribute, to, rules);
                 if (encodedAttribute != null) {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAuthenticationStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAuthenticationStatementToAssertion.java
index 3e254bd00..dddeef73b 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAuthenticationStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAuthenticationStatementToAssertion.java
@@ -26,6 +26,8 @@ import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
+
+import jakarta.servlet.http.HttpServletRequest;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
 import net.shibboleth.idp.authn.AbstractAuthenticationAction;
@@ -157,8 +159,7 @@ public abstract class BaseAddAuthenticationStatementToAssertion extends Abstract
      * @return the result to encode
      */
     @Nonnull public AuthenticationResult getAuthenticationResult() {
-        Constraint.isNotNull(authenticationResult, "AuthenticationResult has not been initialized yet");
-        return authenticationResult;
+        return Constraint.isNotNull(authenticationResult, "AuthenticationResult has not been initialized yet");
     }
 
     /**
@@ -167,8 +168,7 @@ public abstract class BaseAddAuthenticationStatementToAssertion extends Abstract
      * @return the ID generation strategy
      */
     @Nonnull public IdentifierGenerationStrategy getIdGenerator() {
-        Constraint.isNotNull(idGenerator, "IdentifierGenerationStrategy has not been initialized yet");
-        return idGenerator;
+        return Constraint.isNotNull(idGenerator, "IdentifierGenerationStrategy has not been initialized yet");
     }
 
     /**
@@ -177,8 +177,7 @@ public abstract class BaseAddAuthenticationStatementToAssertion extends Abstract
      * @return the issuer name
      */
     @Nonnull public String getIssuerId() {
-        Constraint.isNotNull(issuerId, "Issuer name has not been initialized yet");
-        return issuerId;
+        return Constraint.isNotNull(issuerId, "Issuer name has not been initialized yet");
     }
     
     /** {@inheritDoc} */
@@ -235,8 +234,9 @@ public abstract class BaseAddAuthenticationStatementToAssertion extends Abstract
 
         /** {@inheritDoc} */
         @Nullable public String apply(@Nullable final ProfileRequestContext t) {
-            if (getHttpServletRequest() != null) {
-                return HttpServletSupport.getRemoteAddr(getHttpServletRequest());
+            final HttpServletRequest req = getHttpServletRequest();
+            if (req != null) {
+                return HttpServletSupport.getRemoteAddr(req);
             }
             
             return null;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseIdPInitiatedSSORequestMessageDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseIdPInitiatedSSORequestMessageDecoder.java
index d5b21c144..1d8ff3ae5 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseIdPInitiatedSSORequestMessageDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseIdPInitiatedSSORequestMessageDecoder.java
@@ -104,6 +104,7 @@ public abstract class BaseIdPInitiatedSSORequestMessageDecoder extends AbstractH
      */
     @Nonnull protected IdPInitiatedSSORequest buildIdPInitiatedSSORequest() throws MessageDecodingException {
         final HttpServletRequest request = getHttpServletRequest();
+        assert request!=null;
         
         return new IdPInitiatedSSORequest(getEntityId(request), getAcsUrl(request), getTarget(request),
                 getTime(request));
@@ -199,6 +200,7 @@ public abstract class BaseIdPInitiatedSSORequestMessageDecoder extends AbstractH
      */
     @Nonnull protected String getMessageID() {
         final HttpServletRequest request = getHttpServletRequest();
+        assert request != null;
         final String timeString = StringSupport.trimOrNull(request.getParameter(TIME_PARAM));
         
         // If both a timestamp and session ID are available, construct a pseudo message ID 
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/ExtractSubjectFromRequest.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/ExtractSubjectFromRequest.java
index 9e9ca9bec..8f1cb7222 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/ExtractSubjectFromRequest.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/ExtractSubjectFromRequest.java
@@ -134,7 +134,7 @@ public class ExtractSubjectFromRequest extends AbstractProfileAction {
             return false;
         }
 
-        nameIdentifier = msgCtx.getSubcontext(SAMLSubjectNameIdentifierContext.class, true).getSubjectNameIdentifier();
+        nameIdentifier = msgCtx.getOrCreateSubcontext(SAMLSubjectNameIdentifierContext.class).getSubjectNameIdentifier();
         if (nameIdentifier == null) {
             log.debug("{} No Subject NameID/NameIdentifier in message needs inbound processing", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, NO_SUBJECT);
@@ -155,17 +155,18 @@ public class ExtractSubjectFromRequest extends AbstractProfileAction {
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
         final Subject subject;
-        if (nameIdentifier instanceof NameIdentifier) {
+        final SAMLObject identifier = nameIdentifier;
+        if (identifier instanceof NameIdentifier) {
             log.debug("{} Creating Subject for canonicalization around NameIdentifier {}", getLogPrefix(),
-                    ((NameIdentifier) nameIdentifier).getValue());
+                    ((NameIdentifier) identifier).getValue());
             subject = new Subject(false,
-                    Collections.singleton(new NameIdentifierPrincipal((NameIdentifier) nameIdentifier)),
+                    Collections.singleton(new NameIdentifierPrincipal((NameIdentifier) identifier)),
                     Collections.emptySet(), Collections.emptySet());
-        } else if (nameIdentifier instanceof NameID) {
+        } else if (identifier instanceof NameID) {
             log.debug("{} Creating Subject for canonicalization around NameID {}", getLogPrefix(),
-                    ((NameID) nameIdentifier).getValue());
+                    ((NameID) identifier).getValue());
             subject = new Subject(false,
-                    Collections.singleton(new NameIDPrincipal((NameID) nameIdentifier)),
+                    Collections.singleton(new NameIDPrincipal((NameID) identifier)),
                     Collections.emptySet(), Collections.emptySet());
         } else {
             subject = null;
@@ -206,8 +207,8 @@ public class ExtractSubjectFromRequest extends AbstractProfileAction {
             if (profileRequestContext != null) {
                 final MessageContext msgCtx = profileRequestContext.getInboundMessageContext();
                 if (msgCtx != null) {
-                    return msgCtx.getSubcontext(
-                            SAMLSubjectNameIdentifierContext.class, true).getSubjectNameIdentifier();
+                    return msgCtx.getOrCreateSubcontext(SAMLSubjectNameIdentifierContext.class)
+                            .getSubjectNameIdentifier();
                 }
             }
             
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/IdPInitiatedSSORequest.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/IdPInitiatedSSORequest.java
index 29abc75a0..becff7415 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/IdPInitiatedSSORequest.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/IdPInitiatedSSORequest.java
@@ -137,15 +137,15 @@ public class IdPInitiatedSSORequest {
         int result = 1;
 
         result = prime * result + entityId.hashCode();
-
-        if (acsURL != null) {
-            result = prime * result + acsURL.hashCode();
+        final String url = acsURL;  
+        if (url != null) {
+            result = prime * result + url.hashCode();
         } else {
             result = prime * result + 0;
         }
-
-        if (relayState != null) {
-            result = prime * result + relayState.hashCode();
+        final String state = relayState;
+        if (state != null) {
+            result = prime * result + state.hashCode();
         } else {
             result = prime * result + 0;
         }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContext.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContext.java
index 2d33c5d2f..df53f8709 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContext.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContext.java
@@ -43,6 +43,7 @@ import net.shibboleth.idp.authn.context.SubjectContext;
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration;
 import net.shibboleth.idp.saml.saml2.profile.config.logic.IgnoreScopingProfileConfigPredicate;
+import net.shibboleth.profile.config.ProfileConfiguration;
 import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.saml.saml2.profile.config.navigate.ProxyCountLookupFunction;
 import net.shibboleth.shared.logic.Constraint;
@@ -74,7 +75,7 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
     @Nonnull private Predicate<ProfileRequestContext> ignoreScopingPredicate;
 
     /** Strategy used to determine proxy count from configuration. */
-    @Nullable private Function<ProfileRequestContext,Integer> proxyCountLookupStrategy;
+    @Nonnull private Function<ProfileRequestContext,Integer> proxyCountLookupStrategy;
     
     /** Strategy used to locate the {@link AuthnRequest} to operate on, if any. */
     @Nonnull private Function<ProfileRequestContext,AuthnRequest> requestLookupStrategy;
@@ -170,16 +171,17 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
 
         final AuthenticationContext authnCtx = new AuthenticationContext();
 
-        if (authnRequest != null) {
+        final AuthnRequest ar = authnRequest;
+        if (ar != null) {
             if (!processScoping(profileRequestContext, authnCtx)) {
                 return;
             }
-            authnCtx.setForceAuthn(authnRequest.isForceAuthn());
-            authnCtx.setIsPassive(authnRequest.isPassive());
+            authnCtx.setForceAuthn(ar.isForceAuthn());
+            authnCtx.setIsPassive(ar.isPassive());
             
             // On an inbound Subject, migrate the populated SubjectContext into the required name
             // field in the new AuthenticationContext.
-            if (authnRequest.getSubject() != null && authnRequest.getSubject().getNameID() != null) {
+            if (ar.getSubject() != null && ar.getSubject().getNameID() != null) {
                 final SubjectContext subjectCtx = profileRequestContext.getSubcontext(SubjectContext.class);
                 if (subjectCtx != null && subjectCtx.getPrincipalName() != null) {
                     authnCtx.setRequiredName(subjectCtx.getPrincipalName());
@@ -227,6 +229,7 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
     private boolean processScoping(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final AuthenticationContext authenticationContext) {
         
+        assert authnRequest!=null;
         final Scoping scoping = authnRequest.getScoping();
         if (scoping == null) {
             log.debug("{} AuthnRequest did not contain Scoping, nothing to do", getLogPrefix());
@@ -240,8 +243,9 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
         
         // Check if permitted.
         final RelyingPartyContext rpContext = relyingPartyContextLookupStrategy.apply(profileRequestContext);
-        if (rpContext != null && rpContext.getProfileConfig() != null) {
-            if (rpContext.getProfileConfig().isFeatureDisallowed(
+        final ProfileConfiguration profileConfig = rpContext==null ? null : rpContext.getProfileConfig();
+        if (profileConfig != null) {
+            if (profileConfig.isFeatureDisallowed(
                     profileRequestContext, BrowserSSOProfileConfiguration.FEATURE_SCOPING)) {
                 log.warn("{} Incoming Scoping disallowed by profile configuration", getLogPrefix());
                 ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeOutboundMessageContext.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeOutboundMessageContext.java
index 3de9f4e56..2bda59e29 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeOutboundMessageContext.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeOutboundMessageContext.java
@@ -63,7 +63,7 @@ public class InitializeOutboundMessageContext extends AbstractProfileAction {
     @Nonnull private Function<ProfileRequestContext, RelyingPartyContext> relyingPartyContextLookupStrategy;
 
     /** Strategy used to obtain the self identity value. */
-    @Nullable private Function<ProfileRequestContext, String> selfIdentityLookupStrategy;
+    @Nonnull private Function<ProfileRequestContext, String> selfIdentityLookupStrategy;
 
     /** The {@link SAMLPeerEntityContext} to base the outbound context on. */
     @Nullable private SAMLPeerEntityContext peerEntityCtx;
@@ -128,21 +128,23 @@ public class InitializeOutboundMessageContext extends AbstractProfileAction {
         final MessageContext msgCtx = new MessageContext();
         profileRequestContext.setOutboundMessageContext(msgCtx);
 
-        final SAMLSelfEntityContext selfContext = msgCtx.getSubcontext(SAMLSelfEntityContext.class, true);
+        final SAMLSelfEntityContext selfContext = msgCtx.getOrCreateSubcontext(SAMLSelfEntityContext.class);
         selfContext.setEntityId(selfIdentityLookupStrategy.apply(profileRequestContext));
 
-        final SAMLPeerEntityContext peerContext = msgCtx.getSubcontext(SAMLPeerEntityContext.class, true);
-        peerContext.setEntityId(peerEntityCtx.getEntityId());
+        final SAMLPeerEntityContext peerContext = msgCtx.getOrCreateSubcontext(SAMLPeerEntityContext.class);
+        SAMLPeerEntityContext pec = peerEntityCtx;
+        assert pec!=null;
+        peerContext.setEntityId(pec.getEntityId());
 
-        final SAMLMetadataContext inboundMetadataCtx = peerEntityCtx.getSubcontext(SAMLMetadataContext.class);
+        final SAMLMetadataContext inboundMetadataCtx = pec.getSubcontext(SAMLMetadataContext.class);
         if (inboundMetadataCtx != null) {
-            final SAMLMetadataContext outboundMetadataCtx = peerContext.getSubcontext(SAMLMetadataContext.class, true);
+            final SAMLMetadataContext outboundMetadataCtx = peerContext.getOrCreateSubcontext(SAMLMetadataContext.class);
             outboundMetadataCtx.setEntityDescriptor(inboundMetadataCtx.getEntityDescriptor());
             outboundMetadataCtx.setRoleDescriptor(inboundMetadataCtx.getRoleDescriptor());
             final AttributeConsumingServiceContext acsCtx =
                     inboundMetadataCtx.getSubcontext(AttributeConsumingServiceContext.class);
             if (null != acsCtx) {
-                outboundMetadataCtx.getSubcontext(AttributeConsumingServiceContext.class, true)
+                outboundMetadataCtx.getOrCreateSubcontext(AttributeConsumingServiceContext.class)
                         .setAttributeConsumingService(acsCtx.getAttributeConsumingService());
             }
         }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeOutboundMessageContextForError.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeOutboundMessageContextForError.java
index 3d367e5c2..98da8820e 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeOutboundMessageContextForError.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeOutboundMessageContextForError.java
@@ -163,22 +163,24 @@ public class InitializeOutboundMessageContextForError extends AbstractProfileAct
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
             return;
         }
-        
-        if (profileRequestContext.getInboundMessageContext() != null) {
-            bindingCtx.setRelayState(SAMLBindingSupport.getRelayState(
-                    profileRequestContext.getInboundMessageContext()));
+
+        final MessageContext inboundMessageContext = profileRequestContext.getInboundMessageContext(); 
+        if (inboundMessageContext!= null) {
+            bindingCtx.setRelayState(SAMLBindingSupport.getRelayState(inboundMessageContext));
         }
         bindingCtx.setBindingDescriptor(outboundBinding);
                 
         // Copy SAML peer context and metadata if it exists.
         if (peerEntityCtx != null) {
-            final SAMLPeerEntityContext peerContext = msgCtx.getSubcontext(SAMLPeerEntityContext.class, true);
-            peerContext.setEntityId(peerEntityCtx.getEntityId());
+            final SAMLPeerEntityContext peerContext = msgCtx.getOrCreateSubcontext(SAMLPeerEntityContext.class);
+            SAMLPeerEntityContext pec = peerEntityCtx;
+            assert pec!=null;
+            peerContext.setEntityId(pec.getEntityId());
             
-            final SAMLMetadataContext inboundMetadataCtx = peerEntityCtx.getSubcontext(SAMLMetadataContext.class);
+            final SAMLMetadataContext inboundMetadataCtx = pec.getSubcontext(SAMLMetadataContext.class);
             if (inboundMetadataCtx != null) {
                 final SAMLMetadataContext outboundMetadataCtx =
-                        peerContext.getSubcontext(SAMLMetadataContext.class, true);
+                        peerContext.getOrCreateSubcontext(SAMLMetadataContext.class);
                 outboundMetadataCtx.setEntityDescriptor(inboundMetadataCtx.getEntityDescriptor());
                 outboundMetadataCtx.setRoleDescriptor(inboundMetadataCtx.getRoleDescriptor());
             }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeRelyingPartyContextFromSAMLPeer.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeRelyingPartyContextFromSAMLPeer.java
index 75f9235e5..a0e3356ef 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeRelyingPartyContextFromSAMLPeer.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeRelyingPartyContextFromSAMLPeer.java
@@ -122,10 +122,11 @@ public class InitializeRelyingPartyContextFromSAMLPeer extends AbstractProfileAc
             ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_RELYING_PARTY_CTX);
             return;
         }
-        
-        log.debug("{} Attaching RelyingPartyContext based on SAML peer {}", getLogPrefix(),
-                peerEntityCtx.getEntityId());
-        rpContext.setRelyingPartyIdContextTree(peerEntityCtx);
+        SAMLPeerEntityContext pec = peerEntityCtx;
+        assert pec!=null;
+
+        log.debug("{} Attaching RelyingPartyContext based on SAML peer {}", getLogPrefix(), pec.getEntityId());
+        rpContext.setRelyingPartyIdContextTree(pec);
         rpContext.setRelyingPartyIdLookupStrategy(RPID_LOOKUP);
         rpContext.setVerificationLookupStrategy(VERIFY_LOOKUP);
     }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/PopulateBindingAndEndpointContexts.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/PopulateBindingAndEndpointContexts.java
index d55ca5150..7ff124439 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/PopulateBindingAndEndpointContexts.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/PopulateBindingAndEndpointContexts.java
@@ -459,7 +459,9 @@ public class PopulateBindingAndEndpointContexts extends AbstractProfileAction {
         endpointContext.setEndpoint(resolvedEndpoint);
         
         final SAMLBindingContext bindingCtx = bindingContextLookupStrategy.apply(profileRequestContext);
-        bindingCtx.setRelayState(SAMLBindingSupport.getRelayState(profileRequestContext.getInboundMessageContext()));
+        final MessageContext imc = profileRequestContext.getInboundMessageContext();
+        assert imc != null;
+        bindingCtx.setRelayState(SAMLBindingSupport.getRelayState(imc));
         
         final Optional<BindingDescriptor> bindingDescriptor =
                 bds.stream().filter(b -> b.getId().equals(bindingURI)).findFirst();
@@ -503,9 +505,11 @@ public class PopulateBindingAndEndpointContexts extends AbstractProfileAction {
      */
     private boolean handleSynchronousRequest(@Nonnull final ProfileRequestContext profileRequestContext) {
         if (inboundMessage != null) {
-            final SAMLBindingContext bindingCtx =
-                    profileRequestContext.getInboundMessageContext().getSubcontext(SAMLBindingContext.class);
+            final MessageContext imc = profileRequestContext.getInboundMessageContext();
+            assert imc != null;
+            final SAMLBindingContext bindingCtx = imc.getSubcontext(SAMLBindingContext.class);
             if (bindingCtx != null && bindingCtx.getBindingUri() != null) {
+                assert bindingDescriptors!=null;
                 final Optional<BindingDescriptor> binding =
                         bindingDescriptors.stream().filter(
                                 b -> b.getId().equals(bindingCtx.getBindingUri())
@@ -515,8 +519,7 @@ public class PopulateBindingAndEndpointContexts extends AbstractProfileAction {
                             getLogPrefix(), binding.orElseThrow().getId());
                     
                     final SAMLBindingContext outboundCtx = bindingContextLookupStrategy.apply(profileRequestContext);
-                    outboundCtx.setRelayState(SAMLBindingSupport.getRelayState(
-                            profileRequestContext.getInboundMessageContext()));
+                    outboundCtx.setRelayState(SAMLBindingSupport.getRelayState(imc));
                     outboundCtx.setBindingDescriptor(binding.orElseThrow());
                     return true;
                 }
@@ -535,19 +538,21 @@ public class PopulateBindingAndEndpointContexts extends AbstractProfileAction {
      * @return criterion to give to resolver
      */
     @Nonnull private EndpointCriterion<?> buildEndpointCriterion(@Nonnull @NotEmpty final String unverifiedBinding) {
+        assert endpointType!=null;
         final Endpoint endpoint = (Endpoint) endpointBuilder.buildObject(endpointType);
         
-        if (inboundMessage instanceof IdPInitiatedSSORequest) {
+        final Object inbound = inboundMessage;
+        if (inbound instanceof IdPInitiatedSSORequest) {
             log.debug("{} Populating template endpoint for resolution from IdP-initiated SSO request", getLogPrefix());
-            endpoint.setLocation(((IdPInitiatedSSORequest) inboundMessage).getAssertionConsumerServiceURL());
-        } else if (inboundMessage instanceof AuthnRequest) {
+            endpoint.setLocation(((IdPInitiatedSSORequest) inbound).getAssertionConsumerServiceURL());
+        } else if (inbound instanceof AuthnRequest) {
             log.debug("{} Populating template endpoint for resolution from SAML AuthnRequest", getLogPrefix());
             
-            endpoint.setLocation(((AuthnRequest) inboundMessage).getAssertionConsumerServiceURL());
-            endpoint.setBinding(((AuthnRequest) inboundMessage).getProtocolBinding());
+            endpoint.setLocation(((AuthnRequest) inbound).getAssertionConsumerServiceURL());
+            endpoint.setBinding(((AuthnRequest) inbound).getProtocolBinding());
             if (endpoint instanceof IndexedEndpoint) {
                 ((IndexedEndpoint) endpoint).setIndex(
-                        ((AuthnRequest) inboundMessage).getAssertionConsumerServiceIndex());
+                        ((AuthnRequest) inbound).getAssertionConsumerServiceIndex());
             }
         }
 
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/PopulateInboundMessageContextWithSAMLSelf.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/PopulateInboundMessageContextWithSAMLSelf.java
index 50930b974..ca1d556b1 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/PopulateInboundMessageContextWithSAMLSelf.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/PopulateInboundMessageContextWithSAMLSelf.java
@@ -50,7 +50,7 @@ public class PopulateInboundMessageContextWithSAMLSelf extends AbstractProfileAc
     @Nonnull private final Logger log = LoggerFactory.getLogger(PopulateInboundMessageContextWithSAMLSelf.class);
 
     /** Strategy used to obtain the self identity value. */
-    @Nullable private Function<ProfileRequestContext, String> selfIdentityLookupStrategy;
+    @Nonnull private Function<ProfileRequestContext, String> selfIdentityLookupStrategy;
 
     /** Constructor. */
     public PopulateInboundMessageContextWithSAMLSelf() {
@@ -70,9 +70,9 @@ public class PopulateInboundMessageContextWithSAMLSelf extends AbstractProfileAc
     /** {@inheritDoc} */
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
-        final MessageContext msgCtx = profileRequestContext.getInboundMessageContext();
+        final MessageContext msgCtx = Constraint.isNotNull(profileRequestContext.getInboundMessageContext(), "No Inbound Message Context");
 
-        final SAMLSelfEntityContext selfContext = msgCtx.getSubcontext(SAMLSelfEntityContext.class, true);
+        final SAMLSelfEntityContext selfContext = msgCtx.getOrCreateSubcontext(SAMLSelfEntityContext.class);
         selfContext.setEntityId(selfIdentityLookupStrategy.apply(profileRequestContext));
 
         log.debug("{} Populated inbound message context with SAML self entityID: {}", getLogPrefix(),
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/ReloadMetadata.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/ReloadMetadata.java
index 98db325b1..11e770f2d 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/ReloadMetadata.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/ReloadMetadata.java
@@ -120,7 +120,9 @@ public class ReloadMetadata extends AbstractProfileAction {
         if (id == null) {
             log.warn("{} No '{}' flow variable found", getLogPrefix(), RESOLVER_ID);
             try {
-                getHttpServletResponse().sendError(HttpServletResponse.SC_NOT_FOUND, "Metadata source not found.");
+                final HttpServletResponse response = getHttpServletResponse();
+                assert response != null;
+                response.sendError(HttpServletResponse.SC_NOT_FOUND, "Metadata source not found.");
             } catch (final IOException e) {
                 ActionSupport.buildEvent(profileRequestContext, EventIds.IO_ERROR);
             }
@@ -155,6 +157,8 @@ public class ReloadMetadata extends AbstractProfileAction {
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
         log.debug("{} Reloading metadata from '{}'", getLogPrefix(), id);
 
+        final HttpServletResponse response = getHttpServletResponse();
+        assert response != null;
         try (final ServiceableComponent<MetadataResolver> component =
                 metadataResolverService.getServiceableComponent()) {
 
@@ -168,17 +172,17 @@ public class ReloadMetadata extends AbstractProfileAction {
                     ((ClearableMetadataResolver)toProcess).clear();
                     log.debug("{} Cleared metadata resolver: '{}'", getLogPrefix(), id);
                 }
-                getHttpServletResponse().setStatus(HttpServletResponse.SC_OK);
-                getHttpServletResponse().getWriter().println("Metadata reloaded for '" + id + "'");
+                response.setStatus(HttpServletResponse.SC_OK);
+                response.getWriter().println("Metadata reloaded for '" + id + "'");
             } else {
                 log.warn("{} Unable to locate refreshable or clearable metadata resolver: '{}'", getLogPrefix(), id);
-                getHttpServletResponse().sendError(HttpServletResponse.SC_NOT_FOUND, "Metadata source not found.");
+                response.sendError(HttpServletResponse.SC_NOT_FOUND, "Metadata source not found.");
             }
             
         } catch (final ResolverException e) {
             log.error("{} Error refreshing/clearing metadata resolver: '{}'", getLogPrefix(), id, e);
             try {
-                getHttpServletResponse().sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
             } catch (final IOException e2) {
                 log.error("{} I/O error responding to request", getLogPrefix(), e2);
                 ActionSupport.buildEvent(profileRequestContext, EventIds.IO_ERROR);
@@ -186,7 +190,7 @@ public class ReloadMetadata extends AbstractProfileAction {
         } catch (final ServiceException e) {
             log.error("{} Invalid metadata resolver configuration: '{}'", getLogPrefix(), id, e);
             try {
-                getHttpServletResponse().sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
             } catch (final IOException e2) {
                 log.error("{} I/O error responding to request", getLogPrefix(), e2);
                 ActionSupport.buildEvent(profileRequestContext, EventIds.IO_ERROR);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/SpringAwareMessageDecoderFactory.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/SpringAwareMessageDecoderFactory.java
index a34602be0..4c576366c 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/SpringAwareMessageDecoderFactory.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/SpringAwareMessageDecoderFactory.java
@@ -102,6 +102,7 @@ public class SpringAwareMessageDecoderFactory extends AbstractInitializableCompo
         log.debug("Looking up message decoder with bean ID: {}", beanID);
         
         try {
+            assert applicationContext!=null;
             return applicationContext.getBean(beanID, MessageDecoder.class);
         } catch (final BeansException e) {
             log.warn("Error instantiating message decoder from bean ID {}", beanID, e);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/SpringAwareMessageEncoderFactory.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/SpringAwareMessageEncoderFactory.java
index 6efb146ff..591dd7094 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/SpringAwareMessageEncoderFactory.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/SpringAwareMessageEncoderFactory.java
@@ -22,6 +22,7 @@ import java.util.function.Function;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.encoder.MessageEncoder;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.saml.common.messaging.context.SAMLBindingContext;
@@ -57,30 +58,33 @@ public class SpringAwareMessageEncoderFactory extends AbstractInitializableCompo
     /** {@inheritDoc} */
     @Nullable public MessageEncoder apply(@Nullable final ProfileRequestContext profileRequestContext) {
         checkComponentActive();
+        assert profileRequestContext!=null;
+        final MessageContext obmc = profileRequestContext.getOutboundMessageContext();
         
         if (applicationContext == null) {
             log.warn("No Spring ApplicationContext set");
             return null;
-        } else if (profileRequestContext.getOutboundMessageContext() == null) {
+        } else if (obmc == null) {
             log.warn("No outbound message context, unable to lookup message encoder");
             return null;
         }
         
-        final SAMLBindingContext bindingContext =
-                profileRequestContext.getOutboundMessageContext().getSubcontext(SAMLBindingContext.class);
-        if (bindingContext == null || bindingContext.getBindingDescriptor() == null
-                || !(bindingContext.getBindingDescriptor() instanceof BindingDescriptor)) {
+        final SAMLBindingContext bindingContext = obmc.getSubcontext(SAMLBindingContext.class);
+        Object desc = bindingContext == null ? null : bindingContext.getBindingDescriptor();
+        if (bindingContext == null || desc  == null || !(desc instanceof BindingDescriptor)) {
             log.warn("BindingDescriptor was not available, unable to lookup message encoder");
             return null;
         }
         
         log.debug("Looking up message encoder based on binding URI: {}", bindingContext.getBindingUri());
         
-        final BindingDescriptor descriptor = (BindingDescriptor) bindingContext.getBindingDescriptor();
-        if (descriptor.getEncoderBeanId() != null) {
+        final BindingDescriptor descriptor = (BindingDescriptor) desc;
+        final String beanId = descriptor.getEncoderBeanId(); 
+        if (beanId!= null) {
             
             try {
-                return applicationContext.getBean(descriptor.getEncoderBeanId(), MessageEncoder.class);
+                assert applicationContext!=null;
+                return applicationContext.getBean(beanId, MessageEncoder.class);
             } catch (final BeansException e) {
                 log.warn("Error instantiating message encoder from bean ID {}", descriptor.getEncoderBeanId(), e);
             }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/UpdateSAMLSelfEntityContext.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/UpdateSAMLSelfEntityContext.java
index 83b6b138a..4669e3f9c 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/UpdateSAMLSelfEntityContext.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/UpdateSAMLSelfEntityContext.java
@@ -23,14 +23,15 @@ import java.util.function.Function;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.saml.common.messaging.context.SAMLSelfEntityContext;
 import org.slf4j.Logger;
-import net.shibboleth.shared.primitive.LoggerFactory;
 
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.idp.profile.context.navigate.ResponderIdLookupFunction;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Action that updates inbound and/or outbound instances of {@link SAMLSelfEntityContext}
@@ -49,7 +50,7 @@ public class UpdateSAMLSelfEntityContext extends AbstractProfileAction {
     @Nonnull private final Logger log = LoggerFactory.getLogger(UpdateSAMLSelfEntityContext.class);
 
     /** Strategy used to obtain the self identity value. */
-    @Nullable private Function<ProfileRequestContext,String> selfIdentityLookupStrategy;
+    @Nonnull private Function<ProfileRequestContext,String> selfIdentityLookupStrategy;
 
     /** Result of strategy function. */
     @Nullable private String selfIdentity;
@@ -83,19 +84,19 @@ public class UpdateSAMLSelfEntityContext extends AbstractProfileAction {
     /** {@inheritDoc} */
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
-        if (profileRequestContext.getInboundMessageContext() != null) {
+        final MessageContext imc = profileRequestContext.getInboundMessageContext();
+        if (imc != null) {
             final SAMLSelfEntityContext context =
-                    profileRequestContext.getInboundMessageContext().getSubcontext(SAMLSelfEntityContext.class);
+                    imc.getSubcontext(SAMLSelfEntityContext.class);
             if (context != null && !Objects.equals(context.getEntityId(), selfIdentity)) {
                 log.debug("{} Updating inbound SAMLSelfEntityContext, '{}' to '{}'", getLogPrefix(),
                         context.getEntityId(), selfIdentity);
                 context.setEntityId(selfIdentity);
             }
         }
-
-        if (profileRequestContext.getOutboundMessageContext() != null) {
-            final SAMLSelfEntityContext context =
-                    profileRequestContext.getOutboundMessageContext().getSubcontext(SAMLSelfEntityContext.class);
+        final MessageContext omc = profileRequestContext.getOutboundMessageContext(); 
+        if (omc != null) {
+            final SAMLSelfEntityContext context = omc.getSubcontext(SAMLSelfEntityContext.class);
             if (context != null && !Objects.equals(context.getEntityId(), selfIdentity)) {
                 log.debug("{} Updating outbound SAMLSelfEntityContext, '{}' to '{}'", getLogPrefix(),
                         context.getEntityId(), selfIdentity);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java
index 504cdca14..b19f9c340 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java
@@ -28,6 +28,7 @@ import javax.annotation.Nullable;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -158,6 +159,7 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
         final AttributeStatement statement = statementBuilder.buildObject();
         
         for (final Attribute attribute : encodedAttributes) {
+            assert attribute != null;
             final Attribute existing = findExistingAttribute(statement, attribute);
             if (existing != null) {
                 final Iterator<XMLObject> newValues = attribute.getAttributeValues().iterator();
@@ -232,12 +234,15 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
 
         /** {@inheritDoc} */
         @Nullable public Assertion apply(@Nullable final ProfileRequestContext input) {
-            if (input != null && input.getOutboundMessageContext() != null) {
-                final Object outboundMessage = input.getOutboundMessageContext().getMessage();
+            final MessageContext omc = input == null ? null : input.getOutboundMessageContext(); 
+
+            if (input != null && omc != null) {
+                final Object outboundMessage = omc.getMessage();
                 if (outboundMessage == null) {
+
                     final Assertion ret = SAML1ActionSupport.buildAssertion(AddAttributeStatementToAssertion.this,
                             getIdGenerator(), getIssuerId());
-                    input.getOutboundMessageContext().setMessage(ret);
+                    omc.setMessage(ret);
                     return ret;
                 } else if (outboundMessage instanceof Assertion) {
                     return (Assertion) outboundMessage;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAuthenticationStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAuthenticationStatementToAssertion.java
index 15034aea1..db8d8c680 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAuthenticationStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAuthenticationStatementToAssertion.java
@@ -17,6 +17,7 @@
 
 package net.shibboleth.idp.saml.saml1.profile.impl;
 
+import java.security.Principal;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -24,6 +25,7 @@ import javax.annotation.Nullable;
 
 import org.opensaml.core.xml.XMLObjectBuilderFactory;
 import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -157,10 +159,10 @@ public class AddAuthenticationStatementToAssertion extends BaseAddAuthentication
 
         final AuthenticationStatement statement = statementBuilder.buildObject();
         statement.setAuthenticationInstant(getAuthenticationResult().getAuthenticationInstant());
-        
-        if (requestedPrincipalContext != null && requestedPrincipalContext.getMatchingPrincipal() != null
-                && requestedPrincipalContext.getMatchingPrincipal() instanceof AuthenticationMethodPrincipal) {
-            statement.setAuthenticationMethod(requestedPrincipalContext.getMatchingPrincipal().getName());
+
+        final Principal matchingPrincipal = requestedPrincipalContext != null ? requestedPrincipalContext.getMatchingPrincipal() : null;
+        if (matchingPrincipal != null && matchingPrincipal instanceof AuthenticationMethodPrincipal) {
+            statement.setAuthenticationMethod(matchingPrincipal.getName());
         } else {
             statement.setAuthenticationMethod(methodLookupStrategy.apply(profileRequestContext).getName());
         }
@@ -190,12 +192,13 @@ public class AddAuthenticationStatementToAssertion extends BaseAddAuthentication
         /** {@inheritDoc} */
         @Override
         @Nullable public Assertion apply(@Nullable final ProfileRequestContext input) {
-            if (input != null && input.getOutboundMessageContext() != null) {
-                final Object outboundMessage = input.getOutboundMessageContext().getMessage();
+            final MessageContext omc = input == null ? null : input.getOutboundMessageContext(); 
+            if (input != null && omc != null) {
+                final Object outboundMessage = omc.getMessage();
                 if (outboundMessage == null) {
                     final Assertion ret = SAML1ActionSupport.buildAssertion(AddAuthenticationStatementToAssertion.this,
                             getIdGenerator(), getIssuerId());
-                    input.getOutboundMessageContext().setMessage(ret);
+                    omc.setMessage(ret);
                     return ret;
                 } else if (outboundMessage instanceof Assertion) {
                     return (Assertion) outboundMessage;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java
index 5d9b65d17..c75615e2d 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.List;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -32,8 +33,8 @@ import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
-import org.opensaml.saml.saml1.core.AttributeDesignator;
 import org.opensaml.saml.saml1.core.AttributeQuery;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
 import org.opensaml.saml.saml1.core.Request;
 import org.slf4j.Logger;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -64,6 +65,9 @@ import net.shibboleth.shared.service.ServiceableComponent;
  */
 public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
 
+    /** Unused?. */
+    private static final String List = null;
+
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(FilterByQueriedAttributeDesignators.class);
 
@@ -84,10 +88,12 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
 
     /** Constructor. */
     public FilterByQueriedAttributeDesignators() {
-        attributeContextLookupStrategy = new ChildContextLookup<>(AttributeContext.class).compose(
+        final Function<ProfileRequestContext,AttributeContext> acls = new ChildContextLookup<>(AttributeContext.class).compose(
                 new ChildContextLookup<>(RelyingPartyContext.class));
-        
-        requestLookupStrategy = new MessageLookup<>(Request.class).compose(new InboundMessageContextLookup());
+        final Function<ProfileRequestContext,Request> rls = new MessageLookup<>(Request.class).compose(new InboundMessageContextLookup()); 
+        assert acls != null && rls != null;
+        attributeContextLookupStrategy = acls;
+        requestLookupStrategy = rls;
     }
 
     /**
@@ -145,8 +151,10 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
         if (request != null) {
             query = request.getAttributeQuery();
         }
+        final AttributeQuery ac = query;
         
-        if (query == null || query.getAttributeDesignators().isEmpty()) {
+        final List<AttributeDesignator> designators = ac == null ? null : ac.getAttributeDesignators();
+        if (ac == null || designators == null|| designators.isEmpty()) {
             log.debug("No AttributeDesignators found, nothing to do ");
             return false;
         }
@@ -156,7 +164,7 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
             log.debug("{} No attribute context, no attributes to filter", getLogPrefix());
             return false;
         }
-
+        assert attributeContext!=null;
         if (attributeContext.getIdPAttributes().isEmpty()) {
             log.debug("{} No attributes to filter", getLogPrefix());
             return false;
@@ -171,10 +179,13 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
 
         final Set<String> decodedAttributeIds = new HashSet<>();
 
+        final AttributeQuery ac = query;
+        final AttributeContext aCtx = attributeContext;
+        assert ac != null && aCtx != null;
         try (final ServiceableComponent<AttributeTranscoderRegistry> component =
                 transcoderRegistry.getServiceableComponent()) {
-
-            for (final AttributeDesignator designator : query.getAttributeDesignators()) {
+            for (final AttributeDesignator designator : ac.getAttributeDesignators()) {
+                assert designator!=null;
                 try {
                     decodeAttributeDesignator(component.getComponent(), profileRequestContext, designator,
                             decodedAttributeIds);
@@ -188,10 +199,10 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
             return;
         }
 
-        final Collection<IdPAttribute> keepers = new ArrayList<>(query.getAttributeDesignators().size());
+        final Collection<IdPAttribute> keepers = new ArrayList<>(ac.getAttributeDesignators().size());
         log.debug("Query content mapped to attribute IDs: {}", decodedAttributeIds);
         
-        for (final IdPAttribute attribute : attributeContext.getIdPAttributes().values()) {
+        for (final IdPAttribute attribute : aCtx.getIdPAttributes().values()) {
             if (decodedAttributeIds.contains(attribute.getId())) {
                 log.debug("Retaining attribute '{}' requested by query", attribute.getId());
                 keepers.add(attribute);
@@ -200,7 +211,7 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
             }
         }
         
-        attributeContext.setIdPAttributes(keepers);
+        aCtx.setIdPAttributes(keepers);
     }
 
     /**
@@ -225,6 +236,7 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
         }
         
         for (final TranscodingRule rules : transcodingRules) {
+            assert rules != null;
             final AttributeTranscoder<AttributeDesignator> transcoder = TranscoderSupport.getTranscoder(rules);
             final IdPAttribute decodedAttribute = transcoder.decode(profileRequestContext, input, rules);
             if (decodedAttribute != null) {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/IdPInitiatedSSORequestMessageDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/IdPInitiatedSSORequestMessageDecoder.java
index c1e46b944..abf0b2c91 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/IdPInitiatedSSORequestMessageDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/IdPInitiatedSSORequestMessageDecoder.java
@@ -23,6 +23,7 @@ import javax.annotation.Nullable;
 import net.shibboleth.idp.saml.profile.impl.BaseIdPInitiatedSSORequestMessageDecoder;
 import net.shibboleth.idp.saml.profile.impl.IdPInitiatedSSORequest;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
 
 import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.decoder.MessageDecodingException;
@@ -58,9 +59,9 @@ public class IdPInitiatedSSORequestMessageDecoder extends BaseIdPInitiatedSSOReq
         final MessageContext messageContext = new MessageContext();
         messageContext.setMessage(ssoRequest);
         
-        messageContext.getSubcontext(SAMLPeerEntityContext.class, true).setEntityId(ssoRequest.getEntityId());
+        messageContext.getOrCreateSubcontext(SAMLPeerEntityContext.class).setEntityId(ssoRequest.getEntityId());
         
-        final SAMLMessageInfoContext msgInfoContext = messageContext.getSubcontext(SAMLMessageInfoContext.class, true);
+        final SAMLMessageInfoContext msgInfoContext = messageContext.getOrCreateSubcontext(SAMLMessageInfoContext.class);
         msgInfoContext.setMessageIssueInstant(ssoRequest.getTime());
         msgInfoContext.setMessageId(getMessageID());
         
@@ -78,13 +79,14 @@ public class IdPInitiatedSSORequestMessageDecoder extends BaseIdPInitiatedSSOReq
      */
     protected void populateBindingContext(@Nonnull final MessageContext messageContext)
         throws MessageDecodingException {
-        final String relayState = ((IdPInitiatedSSORequest) messageContext.getMessage()).getRelayState();
+        final  IdPInitiatedSSORequest message = Constraint.isNotNull((IdPInitiatedSSORequest) messageContext.getMessage(), "No message");
+        final String relayState = message.getRelayState();
         if (relayState == null) {
             throw new MessageDecodingException("Legacy Shibboleth authentication requests require a target parameter");
         }
         log.debug("Decoded SAML relay state: {}", relayState);
         
-        final SAMLBindingContext bindingContext = messageContext.getSubcontext(SAMLBindingContext.class, true);
+        final SAMLBindingContext bindingContext = messageContext.getOrCreateSubcontext(SAMLBindingContext.class);
         bindingContext.setRelayState(relayState);
         bindingContext.setBindingUri(getBindingURI());
         bindingContext.setBindingDescriptor(getBindingDescriptor());
@@ -95,7 +97,8 @@ public class IdPInitiatedSSORequestMessageDecoder extends BaseIdPInitiatedSSOReq
     /** {@inheritDoc} */
     @Override
     @Nullable protected String getMessageToLog() {
-        return "SAML 1 IdP-initiated request was: " + getMessageContext().getMessage().toString();
+        final  Object message = Constraint.isNotNull((IdPInitiatedSSORequest) getMessageContext().getMessage(), "No message");
+        return "SAML 1 IdP-initiated request was: " + message.toString();
     }
     
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AbstractSAML2ArtifactAwareProfileConfiguration.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AbstractSAML2ArtifactAwareProfileConfiguration.java
index e16faa699..f25feb42c 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AbstractSAML2ArtifactAwareProfileConfiguration.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AbstractSAML2ArtifactAwareProfileConfiguration.java
@@ -61,7 +61,9 @@ public abstract class AbstractSAML2ArtifactAwareProfileConfiguration extends Abs
         super(profileId);
         artifactConfigurationLookupStrategy = FunctionSupport.constant(null);
         signArtifactRequestsPredicate = new NoIntegrityMessageChannelPredicate();
-        clientTLSArtifactRequestsPredicate = new NoIntegrityMessageChannelPredicate().negate();
+        final Predicate<MessageContext> pred = new NoIntegrityMessageChannelPredicate().negate();
+        assert pred != null;
+        clientTLSArtifactRequestsPredicate = pred;
     }
     
     /** {@inheritDoc} */
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AbstractSAML2ProfileConfiguration.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AbstractSAML2ProfileConfiguration.java
index b2153d9dc..035c779ee 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AbstractSAML2ProfileConfiguration.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AbstractSAML2ProfileConfiguration.java
@@ -57,7 +57,7 @@ public abstract class AbstractSAML2ProfileConfiguration extends AbstractSAMLProf
     }
     
     /** {@inheritDoc} */
-    public boolean isIgnoreRequestSignatures(@Nonnull final ProfileRequestContext profileRequestContext) {
+    public boolean isIgnoreRequestSignatures(final @Nullable ProfileRequestContext profileRequestContext) {
         return ignoreRequestSignaturesPredicate.test(profileRequestContext);
     }
     
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java
index 817f9f90b..4e9e09b86 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java
@@ -28,6 +28,7 @@ import javax.annotation.Nullable;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -236,12 +237,13 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
         /** {@inheritDoc} */
         @Override
         @Nullable public Assertion apply(@Nullable final ProfileRequestContext input) {
-            if (input != null && input.getOutboundMessageContext() != null) {
-                final Object outboundMessage = input.getOutboundMessageContext().getMessage();
+            final MessageContext omc = input != null ? input.getOutboundMessageContext() : null;  
+            if (omc != null) {
+                final Object outboundMessage = omc.getMessage();
                 if (outboundMessage == null) {
                     final Assertion ret = SAML2ActionSupport.buildAssertion(AddAttributeStatementToAssertion.this,
                             getIdGenerator(), getIssuerId());
-                    input.getOutboundMessageContext().setMessage(ret);
+                    omc.setMessage(ret);
                     return ret;
                 } else if (outboundMessage instanceof Assertion) {
                     return (Assertion) outboundMessage;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnRequest.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnRequest.java
index ebbab37f5..b29da89ab 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnRequest.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnRequest.java
@@ -262,12 +262,13 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
                         NameIDPolicy.DEFAULT_ELEMENT_NAME);
 
         final AuthnRequest object = requestBuilder.buildObject();
-        
+        assert idGenerator!=null;
         object.setID(idGenerator.generateIdentifier());
         object.setIssueInstant(Instant.now());
         object.setVersion(SAMLVersion.VERSION_20);
-        
-        final Integer index = profileConfiguration.getAttributeIndex(profileRequestContext);
+        final BrowserSSOProfileConfiguration profileConfig = profileConfiguration;
+        assert profileConfig!=null;
+        final Integer index = profileConfig.getAttributeIndex(profileRequestContext);
         if (index != null) {
             log.debug("{} Setting AttributeConsumingServiceIndex to '{}' for SAML AuthnRequest", getLogPrefix(),
                     index);
@@ -287,7 +288,7 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
         
         // ForceAuthn comes from configuration, which by default will take into account the
         // AuthenticationContext parent's state (but may be overridden by deployer).
-        if (profileConfiguration.isForceAuthn(profileRequestContext)) {
+        if (profileConfig.isForceAuthn(profileRequestContext)) {
             log.debug("{} Setting ForceAuthn for SAML AuthnRequest", getLogPrefix());
             object.setForceAuthn(true);
         }
@@ -300,7 +301,7 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
         
         final NameIDPolicy nip = nipBuilder.buildObject();
         nip.setAllowCreate(true);
-        final String qualifier = profileConfiguration.getSPNameQualifier(profileRequestContext);
+        final String qualifier = profileConfig.getSPNameQualifier(profileRequestContext);
         if (qualifier != null) {
             log.debug("{} Setting NameIDPolicy SPNameQualifier to '{}' for SAML AuthnRequest", getLogPrefix(),
                     qualifier);
@@ -308,7 +309,7 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
         }
         
         // TODO: use metadata for NameID Formats too?
-        final List<String> formats = profileConfiguration.getNameIDFormatPrecedence(profileRequestContext);
+        final List<String> formats = profileConfig.getNameIDFormatPrecedence(profileRequestContext);
         if (!formats.isEmpty()) {
             log.debug("{} Setting NameIDPolicy Format to '{}' for SAML AuthnRequest", getLogPrefix(), formats.get(0));
             nip.setFormat(formats.get(0));
@@ -319,7 +320,7 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
         final RequestedAuthnContext rac = getRequestedAuthnContext(profileRequestContext);
         if (rac != null) {
             final AuthnContextComparisonTypeEnumeration operator =
-                    profileConfiguration.getAuthnContextComparison(profileRequestContext);
+                    profileConfig.getAuthnContextComparison(profileRequestContext);
             if (operator != null) {
                 log.debug("{} Setting RequestedAuthnContext comparison to {}", getLogPrefix(), operator);
                 rac.setComparison(operator);
@@ -331,8 +332,9 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
                 authenticationContext.getProxiableAuthorities()));
 
         object.setExtensions(buildExtensions(profileRequestContext));
-        
-        profileRequestContext.getOutboundMessageContext().setMessage(object);
+        final MessageContext omc = profileRequestContext.getOutboundMessageContext();
+        assert omc != null;
+        omc.setMessage(object);
     }
 // Checkstyle: MethodLength ON
     
@@ -347,6 +349,7 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
             @Nullable final ProfileRequestContext profileRequestContext) {
         
         // RequestedAuthnContext also based on profile configuration.
+        assert profileConfiguration!=null;
         final List<Principal> principals = profileConfiguration.getDefaultAuthenticationMethods(profileRequestContext);
         if (principals.isEmpty()) {
             return null;
@@ -420,6 +423,7 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
 
         boolean include = false;
         
+        assert profileConfiguration!=null;
         if (profileConfiguration.isIgnoreScoping(profileRequestContext)) {
             log.warn("{} Skipping generation of Scoping element in violation of standard", getLogPrefix());
             return null;
@@ -487,6 +491,7 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
     @Nullable private Extensions buildExtensions(
             @Nonnull final ProfileRequestContext profileRequestContext) {
         
+        assert profileConfiguration!=null;
         final Collection<RequestedAttribute> attrs = profileConfiguration.getRequestedAttributes(profileRequestContext);
         if (!attrs.isEmpty()) {
             final XMLObjectBuilderFactory bf = XMLObjectProviderRegistrySupport.getBuilderFactory();
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java
index a0171081c..442328bb5 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java
@@ -29,6 +29,7 @@ import javax.annotation.Nullable;
 
 import org.opensaml.core.xml.XMLObjectBuilderFactory;
 import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -244,6 +245,10 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
         return statement;
     }
     
+    /** Add Authenticating Authorities.
+     * @param profileRequestContext the prc
+     * @param authnContext the authnContext
+     */
     private void addAuthenticatingAuthorities(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final AuthnContext authnContext) {
         
@@ -287,12 +292,14 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
         /** {@inheritDoc} */
         @Override
         @Nullable public Assertion apply(@Nullable final ProfileRequestContext input) {
-            if (input != null && input.getOutboundMessageContext() != null) {
-                final Object outboundMessage = input.getOutboundMessageContext().getMessage();
+            final MessageContext omc = input != null ? input.getOutboundMessageContext() : null;  
+
+            if (omc != null) {
+                final Object outboundMessage = omc.getMessage();
                 if (outboundMessage == null) {
                     final Assertion ret = SAML2ActionSupport.buildAssertion(AddAuthnStatementToAssertion.this,
                             getIdGenerator(), getIssuerId());
-                    input.getOutboundMessageContext().setMessage(ret);
+                    omc.setMessage(ret);
                     return ret;
                 } else if (outboundMessage instanceof Assertion) {
                     return (Assertion) outboundMessage;
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ContinueSAMLAuthentication.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ContinueSAMLAuthentication.java
index f8dd6585a..24be85811 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ContinueSAMLAuthentication.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ContinueSAMLAuthentication.java
@@ -25,10 +25,12 @@ import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.authn.context.ExternalAuthenticationContext;
 
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.core.Status;
 import org.opensaml.saml.saml2.core.StatusCode;
 import org.slf4j.Logger;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -78,28 +80,31 @@ public class ContinueSAMLAuthentication extends AbstractAuthenticationAction {
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final AuthenticationContext authenticationContext) {
-
-        if (extContext.getAuthnError() != null) {
+        final MessageContext imc = profileRequestContext != null ? profileRequestContext.getInboundMessageContext() : null;  
+        final ExternalAuthenticationContext extContext = this.extContext;
+        assert extContext!= null;
+        final String authnError = extContext.getAuthnError(); 
+        if (authnError != null) {
             log.info("{} SAML authentication attempt signaled an error: {}", getLogPrefix(),
-                    extContext.getAuthnError());
-            ActionSupport.buildEvent(profileRequestContext, extContext.getAuthnError());
-        } else if (profileRequestContext.getInboundMessageContext() == null) {
+                    authnError);
+            ActionSupport.buildEvent(profileRequestContext, authnError);
+        } else if (imc == null) {
             log.info("{} No inbound SAML Response found", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
-        } else if (!(profileRequestContext.getInboundMessageContext().getMessage() instanceof Response)) {
+        } else if (!(imc.getMessage() instanceof Response)) {
             log.info("{} Inbound message was not a SAML Response", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_PROC_ERROR);
         }
         
-        final Response response = (Response) profileRequestContext.getInboundMessageContext().getMessage();
-        if (response.getStatus() == null || response.getStatus().getStatusCode() == null ||
-                response.getStatus().getStatusCode().getValue() == null) {
+        final Response response = (Response) imc.getMessage();
+        final Status status = response.getStatus() ;
+        final StatusCode statusCode = status == null ? null : status.getStatusCode(); 
+        if (status == null || statusCode == null || statusCode.getValue() == null) {
             log.info("{} SAML response did not contain a StatusCode", getLogPrefix());
             authenticationContext.removeSubcontext(SAMLAuthnContext.class);
             ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_PROC_ERROR);
-        } else if (!StatusCode.SUCCESS.equals(response.getStatus().getStatusCode().getValue())) {
-            log.info("{} SAML response contained error status: {}", getLogPrefix(),
-                    response.getStatus().getStatusCode().getValue());
+        } else if (!StatusCode.SUCCESS.equals(statusCode.getValue())) {
+            log.info("{} SAML response contained error status: {}", getLogPrefix(), statusCode.getValue());
             authenticationContext.removeSubcontext(SAMLAuthnContext.class);
             ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_PROC_ERROR);
         }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/EnforceDisallowedSSOFeatures.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/EnforceDisallowedSSOFeatures.java
index 3ee972a97..d99aba5a0 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/EnforceDisallowedSSOFeatures.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/EnforceDisallowedSSOFeatures.java
@@ -36,6 +36,7 @@ import net.shibboleth.shared.primitive.LoggerFactory;
 
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration;
+import net.shibboleth.profile.config.ProfileConfiguration;
 import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.shared.logic.Constraint;
 
@@ -116,15 +117,17 @@ public class EnforceDisallowedSSOFeatures extends AbstractProfileAction {
     /** {@inheritDoc} */
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
         final RelyingPartyContext rpContext = relyingPartyContextLookupStrategy.apply(profileRequestContext);
-        if (rpContext == null || !(rpContext.getProfileConfig() instanceof BrowserSSOProfileConfiguration)) {
+        final ProfileConfiguration pc = rpContext == null ? null : rpContext.getProfileConfig();
+        
+        if (rpContext == null || pc == null || !(pc instanceof BrowserSSOProfileConfiguration)) {
             log.debug("{} No BrowserSSOProfileConfiguration available, skipping feature enforcement", getLogPrefix());
             return;
         }
         
-        final BrowserSSOProfileConfiguration profileConfiguration =
-                (BrowserSSOProfileConfiguration) rpContext.getProfileConfig();
-        
-        final Boolean forceAuthn = authnRequest.isForceAuthn();
+        @Nonnull final BrowserSSOProfileConfiguration profileConfiguration = (BrowserSSOProfileConfiguration) pc;
+        final AuthnRequest localAuthnRequest = this.authnRequest;
+        assert localAuthnRequest!= null;
+        final Boolean forceAuthn = localAuthnRequest.isForceAuthn();
         if (forceAuthn != null && forceAuthn &&
                 profileConfiguration.isFeatureDisallowed(profileRequestContext,
                         BrowserSSOProfileConfiguration.FEATURE_FORCEAUTHN)) {
@@ -133,7 +136,7 @@ public class EnforceDisallowedSSOFeatures extends AbstractProfileAction {
             return;
         }
         
-        final NameIDPolicy nidPolicy = authnRequest.getNameIDPolicy();
+        final NameIDPolicy nidPolicy = localAuthnRequest.getNameIDPolicy();
         if (nidPolicy != null) {
             if (nidPolicy.getFormat() != null &&
                     profileConfiguration.isFeatureDisallowed(profileRequestContext,
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java
index e6f5afa92..29bcce955 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java
@@ -143,9 +143,9 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
             return false;
         }
         
-        query = queryLookupStrategy.apply(profileRequestContext);
+        final AttributeQuery localQuery = query = queryLookupStrategy.apply(profileRequestContext);
         
-        if (query == null || query.getAttributes().isEmpty()) {
+        if (localQuery == null || localQuery.getAttributes().isEmpty()) {
             log.debug("No queried Attributes found, nothing to do ");
             return false;
         }
@@ -156,6 +156,7 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
             return false;
         }
 
+        assert attributeContext!=null;
         if (attributeContext.getIdPAttributes().isEmpty()) {
             log.debug("{} No attributes to filter", getLogPrefix());
             return false;
@@ -169,11 +170,13 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
                 
         final Multimap<String,IdPAttribute> mapped = HashMultimap.create();
-
+        final AttributeQuery localQuery = query;
+        AttributeContext localAttributeContext = attributeContext;
+        assert localQuery!=null && localAttributeContext!=null;
         try (final ServiceableComponent<AttributeTranscoderRegistry> component =
                 transcoderRegistry.getServiceableComponent()) {
 
-            for (final Attribute designator : query.getAttributes()) {
+            for (final Attribute designator : localQuery.getAttributes()) {
                 try {
                     decodeAttribute(component.getComponent(), profileRequestContext, designator, mapped);
                 } catch (final AttributeDecodingException e) {
@@ -188,9 +191,9 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
                 
         log.debug("{} Query content mapped to attribute IDs: {}", getLogPrefix(), mapped.keySet());
 
-        final Collection<IdPAttribute> keepers = new ArrayList<>(query.getAttributes().size());
+        final Collection<IdPAttribute> keepers = new ArrayList<>(localQuery.getAttributes().size());
         
-        for (final IdPAttribute attribute : attributeContext.getIdPAttributes().values()) {
+        for (final IdPAttribute attribute : localAttributeContext.getIdPAttributes().values()) {
             
             final Collection<IdPAttribute> requested = mapped.get(attribute.getId());
             
@@ -212,7 +215,7 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
             }
         }
         
-        attributeContext.setIdPAttributes(keepers);
+        localAttributeContext.setIdPAttributes(keepers);
     }
     
     /**
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/IdPInitiatedSSORequestMessageDecoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/IdPInitiatedSSORequestMessageDecoder.java
index b3ca2d703..00fe03489 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/IdPInitiatedSSORequestMessageDecoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/IdPInitiatedSSORequestMessageDecoder.java
@@ -114,16 +114,17 @@ public class IdPInitiatedSSORequestMessageDecoder extends BaseIdPInitiatedSSOReq
      */
     @Nonnull protected AuthnRequest buildAuthnRequest() throws MessageDecodingException {
         final AuthnRequest authnRequest = requestBuilder.buildObject();
-        
+        final IdPInitiatedSSORequest ssoReq= ssoRequest;
+        assert ssoReq !=null;
         final Issuer requestIssuer = issuerBuilder.buildObject();
-        requestIssuer.setValue(ssoRequest.getEntityId());
+        requestIssuer.setValue(ssoReq.getEntityId());
         authnRequest.setIssuer(requestIssuer);
         
         final NameIDPolicy nip = nipBuilder.buildObject();
         nip.setAllowCreate(true);
         authnRequest.setNameIDPolicy(nip);
-        authnRequest.setAssertionConsumerServiceURL(ssoRequest.getAssertionConsumerServiceURL());
-        authnRequest.setIssueInstant(ssoRequest.getTime());
+        authnRequest.setAssertionConsumerServiceURL(ssoReq.getAssertionConsumerServiceURL());
+        authnRequest.setIssueInstant(ssoReq.getTime());
         authnRequest.setVersion(SAMLVersion.VERSION_20);
         authnRequest.setID(getMessageID());
         
@@ -136,10 +137,11 @@ public class IdPInitiatedSSORequestMessageDecoder extends BaseIdPInitiatedSSOReq
      * @param messageContext the current message context
      */
     protected void populateBindingContext(@Nonnull final MessageContext messageContext) {
+        assert ssoRequest!=null;
         final String relayState = ssoRequest.getRelayState();
         log.debug("Decoded SAML RelayState of: {}", relayState);
         
-        final SAMLBindingContext bindingContext = messageContext.getSubcontext(SAMLBindingContext.class, true);
+        final SAMLBindingContext bindingContext = messageContext.getOrCreateSubcontext(SAMLBindingContext.class);
         bindingContext.setRelayState(relayState);
         
         bindingContext.setBindingUri(getBindingURI());
@@ -158,7 +160,9 @@ public class IdPInitiatedSSORequestMessageDecoder extends BaseIdPInitiatedSSOReq
         }
         
         final StringBuilder builder = new StringBuilder();
+        assert ssoRequest!=null;
         builder.append("SAML 2 IdP-initiated request was: " + ssoRequest.toString());
+
         builder.append("\nSynthetically constructed SAML 2 AuthnRequest was: \n");
         
         try {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/MapRequestedAttributesInAttributeConsumingService.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/MapRequestedAttributesInAttributeConsumingService.java
index fc292115c..958b76541 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/MapRequestedAttributesInAttributeConsumingService.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/MapRequestedAttributesInAttributeConsumingService.java
@@ -90,7 +90,7 @@ public class MapRequestedAttributesInAttributeConsumingService extends AbstractP
      * @param registry the registry service
      */
     public void setTranscoderRegistry(@Nonnull final ReloadableService<AttributeTranscoderRegistry> registry) {
-        transcoderRegistry = Constraint.isNotNull(registry, "AttributeResolver cannot be null");
+        transcoderRegistry = Constraint.isNotNull(registry, "Attribute Transcoding Registry cannot be null");
     }
 
     /** {@inheritDoc} */
@@ -98,6 +98,11 @@ public class MapRequestedAttributesInAttributeConsumingService extends AbstractP
     protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
         acsContext = attributeConsumingServiceContextLookupStrategy.apply(profileRequestContext);
+        
+        if (transcoderRegistry == null) {
+            log.warn("{} No Transcoder Regsitry set", getLogPrefix());
+            return false;
+        }
         return true;
     }
 
@@ -124,6 +129,7 @@ public class MapRequestedAttributesInAttributeConsumingService extends AbstractP
         }
         
         try {
+            assert transcoderRegistry!=null;
             final AttributeMappingNodeProcessor processor = new AttributeMappingNodeProcessor(transcoderRegistry);
             log.debug("{} Decoding RequestedAttributes for generated AttributeConsumingService", getLogPrefix());
             processor.process(acs);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/PopulateEncryptionParameters.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/PopulateEncryptionParameters.java
index ed6f5c301..7abbd2ee2 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/PopulateEncryptionParameters.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/PopulateEncryptionParameters.java
@@ -26,6 +26,7 @@ import javax.annotation.Nullable;
 import javax.xml.namespace.QName;
 
 import org.opensaml.core.criterion.EntityIdCriterion;
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
@@ -38,6 +39,7 @@ import org.opensaml.saml.criterion.ProtocolCriterion;
 import org.opensaml.saml.criterion.RoleDescriptorCriterion;
 import org.opensaml.saml.saml2.core.AuthnRequest;
 import org.opensaml.saml.saml2.core.NameID;
+import org.opensaml.saml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml.saml2.profile.context.EncryptionContext;
 import org.opensaml.xmlsec.EncryptionConfiguration;
 import org.opensaml.xmlsec.EncryptionParameters;
@@ -46,7 +48,6 @@ import org.opensaml.xmlsec.SecurityConfigurationSupport;
 import org.opensaml.xmlsec.criterion.EncryptionConfigurationCriterion;
 import org.opensaml.xmlsec.criterion.EncryptionOptionalCriterion;
 import org.slf4j.Logger;
-import net.shibboleth.shared.primitive.LoggerFactory;
 
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.idp.profile.IdPEventIds;
@@ -59,6 +60,7 @@ import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 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.resolver.CriteriaSet;
 import net.shibboleth.shared.resolver.ResolverException;
@@ -247,9 +249,10 @@ public class PopulateEncryptionParameters extends AbstractProfileAction {
             return false;
         }
                 
+        final MessageContext imc = profileRequestContext.getInboundMessageContext();  
         Object msg = null;
-        if (profileRequestContext.getInboundMessageContext() != null) {
-            msg = profileRequestContext.getInboundMessageContext().getMessage();
+        if (imc != null) {
+            msg = imc.getMessage();
         }
         
         if (msg instanceof AuthnRequest) {
@@ -267,7 +270,7 @@ public class PopulateEncryptionParameters extends AbstractProfileAction {
         }
         
         final SAML2ProfileConfiguration profileConfiguration = (SAML2ProfileConfiguration) rpContext.getProfileConfig();
-        
+        assert profileConfiguration!=null;
         if (!encryptIdentifiers) {
             encryptIdentifiers = profileConfiguration.isEncryptNameIDs(profileRequestContext);
             // Encryption can only be optional if the request didn't specify it above.
@@ -309,12 +312,13 @@ public class PopulateEncryptionParameters extends AbstractProfileAction {
         }
         
         try {
-            if (encryptionConfigurations == null || encryptionConfigurations.isEmpty()) {
+            final List<EncryptionConfiguration> configs = encryptionConfigurations ;
+            if (configs == null || configs.isEmpty()) {
                 throw new ResolverException("No EncryptionConfigurations returned by lookup strategy");
             }
             
             final EncryptionParameters params =
-                    encParamsresolver.resolveSingle(buildCriteriaSet(profileRequestContext));
+                    encParamsresolver.resolveSingle(buildCriteriaSet(profileRequestContext, configs));
             log.debug("{} {} EncryptionParameters", getLogPrefix(),
                     params != null ? "Resolved" : "Failed to resolve");
             if (params != null) {
@@ -351,21 +355,23 @@ public class PopulateEncryptionParameters extends AbstractProfileAction {
      * Build the criteria used as input to the {@link EncryptionParametersResolver}.
      * 
      * @param profileRequestContext current profile request context
+     * @param configurations the {@link EncryptionConfiguration}s
      * 
      * @return  the criteria set to use
      */
-    @Nonnull private CriteriaSet buildCriteriaSet(@Nonnull final ProfileRequestContext profileRequestContext) {
+    @Nonnull private CriteriaSet buildCriteriaSet(@Nonnull final ProfileRequestContext profileRequestContext, @Nonnull List<EncryptionConfiguration> configurations) {
         
-        final CriteriaSet criteria = new CriteriaSet(new EncryptionConfigurationCriterion(encryptionConfigurations));
+        final CriteriaSet criteria = new CriteriaSet(new EncryptionConfigurationCriterion(configurations));
         
         criteria.add(new EncryptionOptionalCriterion(encryptionOptional));
 
         if (peerContextLookupStrategy != null) {
             final SAMLPeerEntityContext peerCtx = peerContextLookupStrategy.apply(profileRequestContext);
             if (peerCtx != null) {
-                if (peerCtx.getEntityId() != null) {
+                final String peerEntityId = peerCtx.getEntityId(); 
+                if (peerEntityId != null) {
                     log.debug("{} Adding entityID to resolution criteria", getLogPrefix());
-                    criteria.add(new EntityIdCriterion(peerCtx.getEntityId()));
+                    criteria.add(new EntityIdCriterion(peerEntityId));
                     if (samlProtocol != null) {
                         criteria.add(new ProtocolCriterion(samlProtocol));
                     }
@@ -374,9 +380,10 @@ public class PopulateEncryptionParameters extends AbstractProfileAction {
                     }
                 }
                 final SAMLMetadataContext metadataCtx = peerCtx.getSubcontext(SAMLMetadataContext.class);
-                if (metadataCtx != null && metadataCtx.getRoleDescriptor() != null) {
+                final RoleDescriptor roleDescriptor = metadataCtx == null ? null : metadataCtx.getRoleDescriptor();
+                if (roleDescriptor != null) {
                     log.debug("{} Adding role metadata to resolution criteria", getLogPrefix());
-                    criteria.add(new RoleDescriptorCriterion(metadataCtx.getRoleDescriptor()));
+                    criteria.add(new RoleDescriptorCriterion(roleDescriptor));
                 }
             }
         }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/PreProcessLogoutMessage.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/PreProcessLogoutMessage.java
index 40ab60ec0..d1fc48ba0 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/PreProcessLogoutMessage.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/PreProcessLogoutMessage.java
@@ -21,6 +21,7 @@ import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
@@ -33,6 +34,7 @@ import org.opensaml.saml.ext.saml2aslo.Asynchronous;
 import org.opensaml.saml.saml2.core.Extensions;
 import org.opensaml.saml.saml2.core.LogoutRequest;
 import org.opensaml.saml.saml2.core.LogoutResponse;
+import org.opensaml.saml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml.saml2.metadata.SSODescriptor;
 import org.opensaml.saml.saml2.metadata.SingleLogoutService;
 import org.slf4j.Logger;
@@ -123,12 +125,13 @@ public class PreProcessLogoutMessage extends AbstractProfileAction {
         if (!super.doPreExecute(profileRequestContext)) {
             return false;
         }
+        final MessageContext imc = profileRequestContext.getInboundMessageContext();  
         
-        if (profileRequestContext.getInboundMessageContext() == null) {
+        if (imc == null) {
             log.warn("{} No inbound message context", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
             return false;
-        } else if (!(profileRequestContext.getInboundMessageContext().getMessage() instanceof SAMLObject)) {
+        } else if (!(imc.getMessage() instanceof SAMLObject)) {
             log.warn("{} No inbound SAML message", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
             return false;
@@ -139,7 +142,9 @@ public class PreProcessLogoutMessage extends AbstractProfileAction {
     
     /** {@inheritDoc} */
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
-        final SAMLObject msg = (SAMLObject) profileRequestContext.getInboundMessageContext().getMessage();
+        final MessageContext imc = profileRequestContext.getInboundMessageContext();
+        assert imc != null;
+        final SAMLObject msg = (SAMLObject) imc.getMessage();
         if (msg instanceof LogoutResponse) {
             ActionSupport.buildEvent(profileRequestContext, IS_LOGOUT_RESPONSE);
             return;
@@ -157,8 +162,9 @@ public class PreProcessLogoutMessage extends AbstractProfileAction {
         
         if (assumeAsync) {
             final SAMLMetadataContext mdCtx = metadataContextLookupStrategy.apply(profileRequestContext);
-            if (mdCtx == null || !(mdCtx.getRoleDescriptor() instanceof SSODescriptor) ||
-                    ((SSODescriptor) mdCtx.getRoleDescriptor()).getSingleLogoutServices().isEmpty()) {
+            final RoleDescriptor roleDescriptor = mdCtx == null ? null : mdCtx.getRoleDescriptor();
+            if (roleDescriptor  == null || !(roleDescriptor instanceof SSODescriptor) ||
+                    ((SSODescriptor) roleDescriptor).getSingleLogoutServices().isEmpty()) {
                 log.debug("{} LogoutRequest treated as Asynchronous due to lack of metadata", getLogPrefix());
                 ActionSupport.buildEvent(profileRequestContext, IS_LOGOUT_REQUEST_ASYNC);
             }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessAssertionsForAuthentication.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessAssertionsForAuthentication.java
index dd47cba81..ff61535ae 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessAssertionsForAuthentication.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessAssertionsForAuthentication.java
@@ -29,6 +29,7 @@ import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -47,6 +48,7 @@ import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
@@ -59,16 +61,16 @@ public class ProcessAssertionsForAuthentication extends AbstractAuthenticationAc
     private final Logger log = LoggerFactory.getLogger(ProcessAssertionsForAuthentication.class);
     
     /** The resolver for the response to be processed. */
-    @NonnullAfterInit private Function<ProfileRequestContext, Response> responseResolver;
+    @Nonnull private Function<ProfileRequestContext, Response> responseResolver;
     
     /** Lookup strategy to locate the SAML context. */
-    @NonnullAfterInit private Function<ProfileRequestContext,SAMLAuthnContext> samlContextLookupStrategy;
+    @Nonnull private Function<ProfileRequestContext,SAMLAuthnContext> samlContextLookupStrategy;
     
     /** Selection strategy for multiple valid authn Assertions. */
-    @NonnullAfterInit private Function<List<Assertion>,Assertion> authnAssertionSelectionStrategy;
+    @Nonnull private Function<List<Assertion>,Assertion> authnAssertionSelectionStrategy;
     
     /** Selection strategy for multiple AuthnStatements. */
-    @NonnullAfterInit private Function<Assertion,AuthnStatement> authnStatementSelectionStrategy;
+    @Nonnull private Function<Assertion,AuthnStatement> authnStatementSelectionStrategy;
     
     /** The Response to process. */
     private Response response;
@@ -263,8 +265,11 @@ public class ProcessAssertionsForAuthentication extends AbstractAuthenticationAc
     private class DefaultResponseResolver implements Function<ProfileRequestContext, Response> {
 
         /** {@inheritDoc} */
-        public Response apply(@Nonnull final ProfileRequestContext profileContext) {
-            final SAMLObject message = (SAMLObject) profileContext.getInboundMessageContext().getMessage();
+        public Response apply(final @Nullable ProfileRequestContext profileContext) {
+            assert profileContext!= null;
+            final MessageContext imc = Constraint.isNotNull(profileContext.getInboundMessageContext(), "No inbound Message Context");;
+
+            final SAMLObject message = (SAMLObject) imc.getMessage();
             if (message instanceof Response) {
                 return (Response) message;
             }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessLogoutRequest.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessLogoutRequest.java
index 4b2bfcafe..fed0de738 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessLogoutRequest.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessLogoutRequest.java
@@ -34,6 +34,7 @@ import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.opensaml.saml.common.profile.SAMLEventIds;
+import org.opensaml.saml.saml2.core.Issuer;
 import org.opensaml.saml.saml2.core.LogoutRequest;
 import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.SessionIndex;
@@ -133,9 +134,14 @@ public class ProcessLogoutRequest extends AbstractProfileAction {
         
         sessionResolverCriteriaStrategy = new Function<>() {
             public CriteriaSet apply(final ProfileRequestContext input) {
-                if (logoutRequest != null && logoutRequest.getIssuer() != null && logoutRequest.getNameID() != null) {
-                    return new CriteriaSet(new SPSessionCriterion(logoutRequest.getIssuer().getValue(),
-                            logoutRequest.getNameID().getValue()));
+                final LogoutRequest req = logoutRequest;
+                final NameID nameID = req==null ? null : req.getNameID();
+                final Issuer issuer = req==null ? null : req.getIssuer();
+                if (req != null && issuer != null && nameID != null) {
+                    final String nameIDString = nameID.getValue();
+                    final String issuerString = issuer.getValue();
+                    assert issuerString!=null && nameIDString!=null;
+                    return new CriteriaSet(new SPSessionCriterion(issuerString, nameIDString));
                 }
                 return new CriteriaSet();
             }
@@ -281,16 +287,16 @@ public class ProcessLogoutRequest extends AbstractProfileAction {
             return false;
         }
         
-        logoutRequest = logoutRequestLookupStrategy.apply(profileRequestContext);
-        if (logoutRequest == null) {
+        final LogoutRequest request = logoutRequest = logoutRequestLookupStrategy.apply(profileRequestContext);
+        if (request == null) {
             log.warn("{} No LogoutRequest found to process", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
             return false;
-        } else if (logoutRequest.getNameID() == null) {
+        } else if (request.getNameID() == null) {
             log.warn("{} LogoutRequest did not contain NameID", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
             return false;
-        } else if (logoutRequest.getNameID().getValue() == null) {
+        } else if (request.getNameID().getValue() == null) {
             log.warn("{} LogoutRequest contained an empty (therefore invalid) NameID", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
             return false;
@@ -315,6 +321,7 @@ public class ProcessLogoutRequest extends AbstractProfileAction {
             
             while (sessionIterator.hasNext()) {
                 final IdPSession session = sessionIterator.next();
+                assert session!=null;
                 
                 if (!sessionMatches(profileRequestContext, session)) {
                     log.debug("{} IdP session {} does not contain a matching SP session", getLogPrefix(),
@@ -341,6 +348,7 @@ public class ProcessLogoutRequest extends AbstractProfileAction {
                 logoutCtx.getIdPSessions().add(session);
                 
                 for (final SPSession spSession : session.getSPSessions()) {
+                    assert spSession!=null;
                     if (!sessionMatches(profileRequestContext, spSession)) {
                         logoutCtx.getSessionMap().put(spSession.getId(), spSession);
                         logoutCtx.getKeyedSessionMap().put(Integer.toString(count++), spSession);
@@ -377,6 +385,7 @@ public class ProcessLogoutRequest extends AbstractProfileAction {
             @Nonnull final IdPSession session) {
         
         for (final SPSession spSession : session.getSPSessions()) {
+            assert spSession!=null;
             if (sessionMatches(profileRequestContext, spSession)) {
                 return true;
             }
@@ -398,9 +407,10 @@ public class ProcessLogoutRequest extends AbstractProfileAction {
             @Nonnull final SPSession session) {
         if (session instanceof SAML2SPSession) {
             final SAML2SPSession saml2Session = (SAML2SPSession) session;
-            
+            final LogoutRequest request = logoutRequest;
+            assert request != null;
             // Make sure the SP matches.
-            if (!saml2Session.getId().equals(logoutRequest.getIssuer().getValue())) {
+            if (!saml2Session.getId().equals(request.getIssuer().getValue())) {
                 return false;
             } 
             
@@ -415,28 +425,29 @@ public class ProcessLogoutRequest extends AbstractProfileAction {
                     || qualifiedNameIDFormats.contains(format)) {
                 
                 if (assertingParty == null) {
-                    assertingParty = assertingPartyLookupStrategy.apply(profileRequestContext);
+                    assertingParty = Constraint.isNotNull(assertingPartyLookupStrategy, "assertingPartyLookupStrategy not set").apply(profileRequestContext);
                 }
                 if (relyingParty == null) {
-                    relyingParty = relyingPartyLookupStrategy.apply(profileRequestContext);
+                    relyingParty = Constraint.isNotNull(relyingPartyLookupStrategy, "relyingPartyLookupStrategy not set").apply(profileRequestContext);
                 }
                 
-                if (!SAML2ObjectSupport.areNameIDsEquivalent(logoutRequest.getNameID(), saml2Session.getNameID(),
+                if (!SAML2ObjectSupport.areNameIDsEquivalent(request.getNameID(), saml2Session.getNameID(),
                         assertingParty, relyingParty)) {
                     return false;
                 }
-            } else if (!SAML2ObjectSupport.areNameIDsEquivalent(logoutRequest.getNameID(), saml2Session.getNameID())) {
+            } else if (!SAML2ObjectSupport.areNameIDsEquivalent(request.getNameID(), saml2Session.getNameID())) {
                 return false;
             }
             
             // Check SessionIndex match.
             
-            if (logoutRequest.getSessionIndexes().isEmpty()) {
+            if (request.getSessionIndexes().isEmpty()) {
                 return true;
             }
             
-            for (final SessionIndex index : logoutRequest.getSessionIndexes()) {
-                if (index.getValue() != null && index.getValue().equals(saml2Session.getSessionIndex())) {
+            for (final SessionIndex index : request.getSessionIndexes()) {
+                final String value = index.getValue();
+                if (value != null && value.equals(saml2Session.getSessionIndex())) {
                     return true;
                 }
             }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContext.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContext.java
index e51116e32..5f3ffe77b 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContext.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContext.java
@@ -49,6 +49,7 @@ import net.shibboleth.idp.authn.context.RequestedPrincipalContext;
 import net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal;
 import net.shibboleth.idp.saml.authn.principal.AuthnContextDeclRefPrincipal;
 import net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration;
+import net.shibboleth.profile.config.ProfileConfiguration;
 import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.logic.Constraint;
@@ -157,6 +158,7 @@ public class ProcessRequestedAuthnContext extends AbstractAuthenticationAction {
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final AuthenticationContext authenticationContext) {
         
+        assert authnRequest!=null;
         final RequestedAuthnContext requestedCtx = authnRequest.getRequestedAuthnContext();
         if (requestedCtx == null) {
             log.debug("{} AuthnRequest did not contain a RequestedAuthnContext, nothing to do", getLogPrefix());
@@ -167,9 +169,10 @@ public class ProcessRequestedAuthnContext extends AbstractAuthenticationAction {
         
         if (!requestedCtx.getAuthnContextClassRefs().isEmpty()) {
             for (final AuthnContextClassRef ref : requestedCtx.getAuthnContextClassRefs()) {
-                if (ref.getURI() != null) {
-                    if (!ignoredContexts.contains(ref.getURI())) {
-                        principals.add(new AuthnContextClassRefPrincipal(ref.getURI()));
+                final String uri = ref.getURI();
+                if (uri!= null) {
+                    if (!ignoredContexts.contains(uri)) {
+                        principals.add(new AuthnContextClassRefPrincipal(uri));
                     } else {
                         log.info("{} Ignoring AuthnContextClassRef: {}", getLogPrefix(), ref.getURI());
                     }
@@ -177,9 +180,10 @@ public class ProcessRequestedAuthnContext extends AbstractAuthenticationAction {
             }
         } else if (!requestedCtx.getAuthnContextDeclRefs().isEmpty()) {
             for (final AuthnContextDeclRef ref : requestedCtx.getAuthnContextDeclRefs()) {
-                if (ref.getURI() != null) {
-                    if (!ignoredContexts.contains(ref.getURI())) {
-                        principals.add(new AuthnContextDeclRefPrincipal(ref.getURI()));
+                final String uri = ref.getURI();
+                if (uri != null) {
+                    if (!ignoredContexts.contains(uri)) {
+                        principals.add(new AuthnContextDeclRefPrincipal(uri));
                     } else {
                         log.info("{} Ignoring AuthnContextDeclRef: {}", getLogPrefix(), ref.getURI());
                     }
@@ -194,8 +198,9 @@ public class ProcessRequestedAuthnContext extends AbstractAuthenticationAction {
 
         // Check if permitted.
         final RelyingPartyContext rpContext = relyingPartyContextLookupStrategy.apply(profileRequestContext);
-        if (rpContext != null && rpContext.getProfileConfig() != null) {
-            if (rpContext.getProfileConfig().isFeatureDisallowed(
+        final ProfileConfiguration profileConfig = rpContext==null ? null : rpContext.getProfileConfig();
+        if (profileConfig != null) {            
+            if (profileConfig.isFeatureDisallowed(
                     profileRequestContext, BrowserSSOProfileConfiguration.FEATURE_AUTHNCONTEXT)) {
                 log.warn("{} Incoming RequestedAuthnContext disallowed by profile configuration", getLogPrefix());
                 ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/SAMLAuthnController.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/SAMLAuthnController.java
index e2984499a..c33cad224 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/SAMLAuthnController.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/SAMLAuthnController.java
@@ -31,6 +31,7 @@ import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.messaging.decoder.MessageDecoder;
 import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.messaging.handler.MessageHandler;
 import org.opensaml.messaging.handler.MessageHandlerException;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.EventContext;
@@ -53,6 +54,7 @@ import net.shibboleth.idp.authn.ExternalAuthenticationException;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.component.AbstractInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
@@ -130,7 +132,7 @@ public class SAMLAuthnController extends AbstractInitializableComponent {
             bindingMap = new HashMap<>(bindings.size());
             bindings.forEach(b -> bindingMap.put(b.getShortName(), b));
         } else {
-            bindingMap = Collections.emptyMap();
+            bindingMap = CollectionSupport.emptyMap();
         }
     }
 
@@ -170,15 +172,16 @@ public class SAMLAuthnController extends AbstractInitializableComponent {
         }
         
         // Fill in the AuthnRequest's ACS URL and set RelayState to the EA key.
-        if (nestedPRC.getOutboundMessageContext() != null &&
-                nestedPRC.getOutboundMessageContext().getMessage() instanceof AuthnRequest) {
-            SAMLBindingSupport.setRelayState(nestedPRC.getOutboundMessageContext(), key);
+        final MessageContext nestedOmc = nestedPRC.getOutboundMessageContext();
+        if (nestedOmc != null && nestedOmc.getMessage() instanceof AuthnRequest) {
+            final AuthnRequest authnRequest = Constraint.isNotNull((AuthnRequest) nestedOmc.getMessage(), "Outbound messages was null");
+            SAMLBindingSupport.setRelayState(nestedOmc, key);
             final StringBuffer url = httpRequest.getRequestURL();
-            ((AuthnRequest) nestedPRC.getOutboundMessageContext().getMessage()).setAssertionConsumerServiceURL(
+            authnRequest.setAssertionConsumerServiceURL(
                     url.substring(0, url.lastIndexOf("/start")));
             final BindingDescriptor bd = bindingMap.get(binding);
             if (bd != null) {
-                ((AuthnRequest) nestedPRC.getOutboundMessageContext().getMessage()).setProtocolBinding(bd.getId());
+                authnRequest.setProtocolBinding(bd.getId());
             }
         } else {
             log.error("Outbound AuthnContext message not found");
@@ -188,17 +191,18 @@ public class SAMLAuthnController extends AbstractInitializableComponent {
         }
         
         try {
-            if (samlContext.getOutboundMessageHandler() != null) {
-                samlContext.getOutboundMessageHandler().invoke(nestedPRC.getOutboundMessageContext());
+            final MessageHandler handler = samlContext.getOutboundMessageHandler();
+            if (handler!= null) {
+                handler.invoke(nestedOmc);
             }
             
             samlContext.getEncodeMessageAction().execute(nestedPRC);
             final EventContext eventCtx = nestedPRC.getSubcontext(EventContext.class);
-            if (eventCtx != null && eventCtx.getEvent() != null
-                    && !EventIds.PROCEED_EVENT_ID.equals(eventCtx.getEvent())) {
-                log.error("Message encoding action signaled non-proceed event {}", eventCtx.getEvent());
+            final Object event = eventCtx != null ? eventCtx.getEvent() : null;  
+            if (event != null && !EventIds.PROCEED_EVENT_ID.equals(event)) {
+                log.error("Message encoding action signaled non-proceed event {}", event);
                 httpRequest.setAttribute(ExternalAuthentication.AUTHENTICATION_ERROR_KEY,
-                        eventCtx.getEvent().toString());
+                        event.toString());
                 ExternalAuthentication.finishExternalAuthentication(key, httpRequest, httpResponse);
                 return;
             }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/SOAPLogoutRequest.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/SOAPLogoutRequest.java
index a53c38681..6e86079d4 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/SOAPLogoutRequest.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/SOAPLogoutRequest.java
@@ -24,6 +24,7 @@ import javax.annotation.Nullable;
 
 import org.opensaml.messaging.MessageException;
 import org.opensaml.messaging.context.InOutOperationContext;
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.messaging.context.navigate.MessageLookup;
 import org.opensaml.profile.action.ActionSupport;
@@ -40,6 +41,7 @@ import org.opensaml.saml.saml2.core.LogoutRequest;
 import org.opensaml.saml.saml2.core.LogoutResponse;
 import org.opensaml.saml.saml2.core.Status;
 import org.opensaml.saml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.metadata.Endpoint;
 import org.opensaml.security.SecurityException;
 import org.opensaml.soap.client.SOAPClient;
 import org.opensaml.soap.client.http.PipelineFactoryHttpSOAPClient;
@@ -234,8 +236,9 @@ public class SOAPLogoutRequest extends AbstractProfileAction {
             return false;
         }
 
-        epContext = endpointContextLookupStrategy.apply(profileRequestContext);
-        if (epContext == null || epContext.getEndpoint() == null || epContext.getEndpoint().getLocation() == null) {
+        final SAMLEndpointContext ctx = epContext = endpointContextLookupStrategy.apply(profileRequestContext);
+        final Endpoint ep = ctx == null ? null : ctx.getEndpoint(); 
+        if (ep == null|| ep.getLocation() == null) {
             log.warn("{} No destination endpoint found", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
             return false;
@@ -258,13 +261,20 @@ public class SOAPLogoutRequest extends AbstractProfileAction {
                     .setPeerRoleDescriptor(mdContext != null ? mdContext.getRoleDescriptor() : null)
                     .build();
             
-            logoutRequest.setDestination(epContext.getEndpoint().getLocation());
+            final SAMLEndpointContext ctx = epContext;
+            assert ctx != null;
+            final Endpoint ep = ctx.getEndpoint();
+            final LogoutRequest lReq = logoutRequest;
+            assert ep != null && lReq != null && opContext != null;
+            lReq.setDestination(ep.getLocation());
         
             log.debug("{} Executing LogoutRequest over SOAP 1.1 binding to endpoint: {}", getLogPrefix(),
-                    logoutRequest.getDestination());
+                    lReq.getDestination());
             
-            soapClient.send(logoutRequest.getDestination(), opContext);
-            final Object response = opContext.getInboundMessageContext().getMessage();
+            soapClient.send(lReq.getDestination(), opContext);
+            final MessageContext opImc = opContext.getInboundMessageContext();
+            assert opImc != null;
+            final Object response = opImc.getMessage();
             
             if (response == null) {
                 throw new MessageException("No response message received");
@@ -274,15 +284,20 @@ public class SOAPLogoutRequest extends AbstractProfileAction {
             
             // Store off message so audit extraction works.
             // Also mock/copy SAMLBindingContext for the same reason (it's SOAP in both directions).
-            profileRequestContext.getInboundMessageContext().setMessage(response);
-            final SAMLBindingContext bctx =
-                    profileRequestContext.getInboundMessageContext().getSubcontext(SAMLBindingContext.class, true);
-            bctx.setBindingDescriptor(
-                    profileRequestContext.getOutboundMessageContext().getSubcontext(
-                            SAMLBindingContext.class).getBindingDescriptor());
+            final MessageContext prcImc = profileRequestContext.getInboundMessageContext();
+            assert prcImc != null;
+            
+            prcImc.setMessage(response);
+            final SAMLBindingContext bctx = prcImc.getOrCreateSubcontext(SAMLBindingContext.class);
+            final MessageContext prcOmc = profileRequestContext.getOutboundMessageContext();
+            assert prcOmc != null;
+            final SAMLBindingContext omcBc = prcOmc.getSubcontext(SAMLBindingContext.class);
+            assert omcBc != null;
+            
+            bctx.setBindingDescriptor(omcBc.getBindingDescriptor());
             
             log.debug("{} Processing LogoutResponse received via SOAP 1.1 binding from endpoint: {}", getLogPrefix(),
-                    logoutRequest.getDestination());
+                    lReq.getDestination());
             handleResponse(profileRequestContext, (LogoutResponse) response);
         } catch (final ClassCastException e) {
             log.warn("{} SOAP message payload was not an instance of LogoutResponse", getLogPrefix());
@@ -309,6 +324,7 @@ public class SOAPLogoutRequest extends AbstractProfileAction {
                     code = code.getStatusCode();
                     if (code == null || code.getValue() == null || !StatusCode.PARTIAL_LOGOUT.equals(code.getValue())) {
                         log.debug("{} Logout successful", getLogPrefix());
+                        assert propagationContext != null;
                         propagationContext.setResult(Result.Success);
                     } else {
                         log.debug("{} Logout partially successful", getLogPrefix());
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ValidateSAMLAuthentication.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ValidateSAMLAuthentication.java
index e2638843d..cadfb0efa 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ValidateSAMLAuthentication.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ValidateSAMLAuthentication.java
@@ -18,8 +18,10 @@
 package net.shibboleth.idp.saml.saml2.profile.impl;
 
 import java.security.Principal;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -27,6 +29,8 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.security.auth.Subject;
 
+import org.opensaml.messaging.context.BaseContext;
+import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
 import org.opensaml.profile.action.ActionSupport;
@@ -39,6 +43,8 @@ import org.opensaml.saml.saml2.core.AttributeStatement;
 import org.opensaml.saml.saml2.core.Audience;
 import org.opensaml.saml.saml2.core.AuthenticatingAuthority;
 import org.opensaml.saml.saml2.core.AuthnContext;
+import org.opensaml.saml.saml2.core.AuthnStatement;
+import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.ProxyRestriction;
 import org.opensaml.saml.saml2.core.Response;
 import org.slf4j.Logger;
@@ -59,6 +65,7 @@ import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
 import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.authn.AbstractValidationAction;
+import net.shibboleth.idp.authn.AuthenticationResult;
 import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.authn.principal.IdPAttributePrincipal;
@@ -262,40 +269,46 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
         if (transcoderRegistry != null) {
             processAttributes(profileRequestContext);
         }
+        final Function<ProfileRequestContext,Collection<IdPAttribute>> aes = attributeExtractionStrategy;
+        AttributeContext ac = attributeContext;
         
-        if (attributeExtractionStrategy != null) {
+        if (aes != null) {
             log.debug("{} Applying custom extraction strategy function", getLogPrefix());
-            if (attributeContext == null) {
-                attributeContext = profileRequestContext
-                        .getSubcontext(RelyingPartyContext.class)
-                        .getSubcontext(AttributeContext.class, true);
+            if (ac == null) {
+                final RelyingPartyContext rpcCtx = profileRequestContext.getSubcontext(RelyingPartyContext.class);
+                assert rpcCtx!= null;
+                ac = attributeContext = rpcCtx.getOrCreateSubcontext(AttributeContext.class);
             }
-            final Collection<IdPAttribute> attributes = new ArrayList<>(attributeContext.getIdPAttributes().values());
-            final Collection<IdPAttribute> newAttributes = attributeExtractionStrategy.apply(profileRequestContext);
+            final Collection<IdPAttribute> attributes = new ArrayList<>(ac.getIdPAttributes().values());
+            final Collection<IdPAttribute> newAttributes = aes.apply(profileRequestContext);
             if (newAttributes != null) {
                 if (log.isDebugEnabled()) {
                     log.debug("{} Extracted attributes with custom strategy: {}", getLogPrefix(),
                             newAttributes.stream().map(IdPAttribute::getId).collect(Collectors.toUnmodifiableList()));
                 }
                 attributes.addAll(newAttributes);
-                attributeContext.setIdPAttributes(attributes);
+                ac.setIdPAttributes(attributes);
             }
         }
 
         logSuccess();
         
-        authnContextTranslator = profileConfiguration.getAuthnContextTranslationStrategy(profileRequestContext);
-        authnContextTranslatorEx = profileConfiguration.getAuthnContextTranslationStrategyEx(profileRequestContext);
+        final BrowserSSOProfileConfiguration prConfig = profileConfiguration;
+        assert prConfig!=null;
+        authnContextTranslator = prConfig.getAuthnContextTranslationStrategy(profileRequestContext);
+        authnContextTranslatorEx = prConfig.getAuthnContextTranslationStrategyEx(profileRequestContext);
         
         buildAuthenticationResult(profileRequestContext, authenticationContext);
-        
-        if (authenticationContext.getAuthenticationResult() != null
-                && profileConfiguration.isProxiedAuthnInstant(profileRequestContext)) {
-            log.debug("{} Resetting authentication time to proxied value: {}", getLogPrefix(),
-                    samlAuthnContext.getAuthnStatement().getAuthnInstant());
-            if (samlAuthnContext.getAuthnStatement().getAuthnInstant() != null) {
-                authenticationContext.getAuthenticationResult().setAuthenticationInstant(
-                        samlAuthnContext.getAuthnStatement().getAuthnInstant());
+        final AuthenticationResult ar = authenticationContext.getAuthenticationResult();
+        if (ar != null && prConfig.isProxiedAuthnInstant(profileRequestContext)) {
+            assert samlAuthnContext != null;
+            final AuthnStatement as = samlAuthnContext.getAuthnStatement();
+            assert as != null;
+            final Instant ai = as.getAuthnInstant();
+            assert ai != null;
+            log.debug("{} Resetting authentication time to proxied value: {}", getLogPrefix(),ai);
+            if (as.getAuthnInstant() != null) {
+                ar.setAuthenticationInstant(ai);
             }
         }
     }
@@ -311,10 +324,12 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
                 nameToLog = attrToLog.getValues().get(0).getDisplayValue();
             }
         }
+
+        assert samlAuthnContext != null;
+        final org.opensaml.saml.saml2.core.Subject samlSubject = samlAuthnContext.getSubject();
         
-        if (nameToLog == null && samlAuthnContext.getSubject() != null
-                && samlAuthnContext.getSubject().getNameID() != null) {
-            nameToLog = samlAuthnContext.getSubject().getNameID().getValue();
+        if (nameToLog == null && samlSubject != null && samlSubject .getNameID() != null) {
+            nameToLog = samlSubject.getNameID().getValue();
         }
 
         log.info("{} SAML authentication succeeded for '{}'", getLogPrefix(), nameToLog);
@@ -325,18 +340,27 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
     @Override
     @Nonnull protected Subject populateSubject(@Nonnull final Subject subject) {
         
-        if (samlAuthnContext.getSubject() != null && samlAuthnContext.getSubject().getNameID() != null) {
-            subject.getPrincipals().add(new NameIDPrincipal(samlAuthnContext.getSubject().getNameID()));
+        final SAMLAuthnContext localSamlAuthnContext = samlAuthnContext;
+        final AttributeContext localAttributeContext = attributeContext;
+        assert localSamlAuthnContext != null && localAttributeContext!=null;;
+        final BaseContext localSamlAuthnContextParent = localSamlAuthnContext.getParent();
+        assert localSamlAuthnContextParent!=null;
+        
+        final org.opensaml.saml.saml2.core.Subject samlSubject = localSamlAuthnContext.getSubject();
+        final NameID nameID = samlSubject==null ? null : samlSubject.getNameID(); 
+        if (nameID!= null) {
+            subject.getPrincipals().add(new NameIDPrincipal(nameID));
         }
+        final AuthnStatement authnStatement = localSamlAuthnContext.getAuthnStatement();
+        assert authnStatement!=null;
+        final AuthnContext authnContext = Constraint.isNotNull(authnStatement.getAuthnContext(), "No Authn Context");
 
-        final AuthnContext authnContext = samlAuthnContext.getAuthnStatement().getAuthnContext();
-        
         boolean principalsAdded = false;
         
         if (authnContextTranslatorEx != null) {
             // PRC is up (AuthenticationContext) and then down (to nested PRC).
             final Collection<Principal> translated = authnContextTranslatorEx.apply(
-                    samlAuthnContext.getParent().getSubcontext(ProfileRequestContext.class));
+                    localSamlAuthnContextParent.getSubcontext(ProfileRequestContext.class));
             if (translated != null && !translated.isEmpty()) {
                 subject.getPrincipals().addAll(translated);
                 if (log.isDebugEnabled()) {
@@ -385,12 +409,12 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
         
         subject.getPrincipals().add(buildProxyPrincipal(authnContext));
         
-        if (attributeContext != null && !attributeContext.getIdPAttributes().isEmpty()) {
+        if (localAttributeContext != null && !localAttributeContext.getIdPAttributes().isEmpty()) {
             log.debug("{} Adding filtered inbound attributes to Subject", getLogPrefix());
             subject.getPrincipals().addAll(
-                attributeContext.getIdPAttributes().values()
+                localAttributeContext.getIdPAttributes().values()
                     .stream()
-                    .map(a -> new IdPAttributePrincipal(a))
+                    .map(a -> {assert a != null; return new IdPAttributePrincipal(a);})
                     .collect(Collectors.toUnmodifiableList()));
         }
         
@@ -409,7 +433,11 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
         
         final ProxyAuthenticationPrincipal proxied = new ProxyAuthenticationPrincipal();
         
-        final Assertion assertion = (Assertion) samlAuthnContext.getAuthnStatement().getParent();
+        assert samlAuthnContext != null;
+        AuthnStatement authnStatement = samlAuthnContext.getAuthnStatement();
+        assert authnStatement != null;
+        final Assertion assertion = (Assertion) authnStatement.getParent();
+        assert assertion != null;
         if (!authnContext.getAuthenticatingAuthorities().isEmpty()) {
             proxied.getAuthorities().addAll(
                     authnContext.getAuthenticatingAuthorities()
@@ -423,9 +451,9 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
         final ProxyRestriction condition = assertion.getConditions().getProxyRestriction();
         if (condition != null) {
             proxied.setProxyCount(condition.getProxyCount());
-            if (condition.getAudiences() != null) {
-                proxied.getAudiences().addAll(
-                        condition.getAudiences()
+            final List<Audience> audiences = condition.getAudiences() ; 
+            if (audiences!= null) {
+                proxied.getAudiences().addAll(audiences
                             .stream()
                             .map(Audience::getURI)
                             .filter(a -> !Strings.isNullOrEmpty(a))
@@ -446,14 +474,19 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
         log.debug("{} Decoding incoming SAML Attributes", getLogPrefix());
         
         final Multimap<String,IdPAttribute> mapped = HashMultimap.create();
+        assert mapped != null;
 
+        assert transcoderRegistry!= null;
         try (final ServiceableComponent<AttributeTranscoderRegistry> component =
                 transcoderRegistry.getServiceableComponent()) {
-
-            final Response response = (Response) profileRequestContext.getInboundMessageContext().getMessage();
+            final MessageContext imc = profileRequestContext.getInboundMessageContext();
+            assert imc != null;
+            final Response response = (Response) imc.getMessage();
+            assert response != null;
             for (final Assertion assertion : response.getAssertions()) {
                 for (final AttributeStatement statement : assertion.getAttributeStatements()) {
                     for (final Attribute designator : statement.getAttributes()) {
+                        assert designator!=null;
                         try {
                             decodeAttribute(component.getComponent(), profileRequestContext, designator, mapped);
                         } catch (final AttributeDecodingException e) {
@@ -470,11 +503,11 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
         log.debug("{} Incoming SAML Attributes mapped to attribute IDs: {}", getLogPrefix(), mapped.keySet());
 
         if (!mapped.isEmpty()) {
-            attributeContext = profileRequestContext
-                    .getSubcontext(RelyingPartyContext.class)
-                    .getSubcontext(AttributeContext.class, true);
-            attributeContext.setUnfilteredIdPAttributes(mapped.values());
-            attributeContext.setIdPAttributes(null);
+            final RelyingPartyContext rpCtx = profileRequestContext.getSubcontext(RelyingPartyContext.class);
+            assert rpCtx != null;
+            final AttributeContext ac = attributeContext = rpCtx.getOrCreateSubcontext(AttributeContext.class);
+            ac.setUnfilteredIdPAttributes(mapped.values());
+            ac.setIdPAttributes(null);
             filterAttributes(profileRequestContext);
         }
     }
@@ -502,6 +535,7 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
         }
         
         for (final TranscodingRule rules : transcodingRules) {
+            assert rules != null;
             final AttributeTranscoder<Attribute> transcoder = TranscoderSupport.getTranscoder(rules);
             final IdPAttribute decodedAttribute = transcoder.decode(profileRequestContext, input, rules);
             if (decodedAttribute != null) {
@@ -516,20 +550,23 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
      * @param profileRequestContext current profile request context
      */
     private void filterAttributes(@Nonnull final ProfileRequestContext profileRequestContext) {
-        if (attributeFilterService == null) {
+        final ReloadableService<AttributeFilter> service = attributeFilterService;
+        if (service == null) {
             log.warn("{} No AttributeFilter service provided", getLogPrefix());
             return;
         }
 
         final AttributeFilterContext filterContext =
-                profileRequestContext.getSubcontext(AttributeFilterContext.class, true);
+                profileRequestContext.getOrCreateSubcontext(AttributeFilterContext.class);
 
         populateFilterContext(profileRequestContext, filterContext);
-
-        try (final ServiceableComponent<AttributeFilter> component = attributeFilterService.getServiceableComponent()) {
+        try (final ServiceableComponent<AttributeFilter> component = service.getServiceableComponent()) {
             final AttributeFilter filter = component.getComponent();
             filter.filterAttributes(filterContext);
-            filterContext.getParent().removeSubcontext(filterContext);
+            final BaseContext parent = filterContext.getParent();
+            assert parent != null;
+            parent.removeSubcontext(filterContext);
+            assert attributeContext!=null;
             attributeContext.setIdPAttributes(filterContext.getFilteredIdPAttributes().values());
         } catch (final AttributeFilterException e) {
             log.error("{} Error while filtering inbound attributes", getLogPrefix(), e);
@@ -546,17 +583,23 @@ public class ValidateSAMLAuthentication extends AbstractValidationAction {
      */
     private void populateFilterContext(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final AttributeFilterContext filterContext) {
+        final AttributeContext ac = attributeContext;
+        assert ac != null;
         
         filterContext.setDirection(Direction.INBOUND)
-            .setPrefilteredIdPAttributes(attributeContext.getUnfilteredIdPAttributes().values())
+            .setPrefilteredIdPAttributes(ac.getUnfilteredIdPAttributes().values())
             .setMetadataResolver(metadataResolver)
             .setRequesterMetadataContextLookupStrategy(null)
             .setIssuerMetadataContextLookupStrategy(
                     new SAMLMetadataContextLookupFunction().compose(
                             new RecursiveTypedParentContextLookup<>(ProfileRequestContext.class)))
             .setProxiedRequesterContextLookupStrategy(null)
-            .setAttributeIssuerID(getResponderLookupStrategy().apply(profileRequestContext))
-            .setAttributeRecipientID(getRequesterLookupStrategy().apply(profileRequestContext));
+            .setAttributeIssuerID(
+                    Constraint.isNotNull(getResponderLookupStrategy(), "No responder Strategy").
+                    apply(profileRequestContext))
+            .setAttributeRecipientID(
+                    Constraint.isNotNull(getRequesterLookupStrategy(), "No requester strategy").
+                    apply(profileRequestContext));
     }
 
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/AddLogoutRequest.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/AddLogoutRequest.java
index 6ee64b441..f153ce493 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/AddLogoutRequest.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/AddLogoutRequest.java
@@ -197,6 +197,7 @@ public class AddLogoutRequest extends AbstractProfileAction {
         }
         
         saml2Session = (SAML2SPSession) logoutPropCtx.getSession();
+        assert saml2Session!=null;
         if (saml2Session.getId() == null) {
             log.debug("{} SAML2SPSession in logout propagation context did not contain a service ID", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
@@ -219,16 +220,18 @@ public class AddLogoutRequest extends AbstractProfileAction {
 
         final LogoutRequest object = requestBuilder.buildObject();
         
+        assert idGenerator!=null;
         object.setID(idGenerator.generateIdentifier());
         object.setIssueInstant(Instant.now());
         object.setVersion(SAMLVersion.VERSION_20);
-
+        final SAML2SPSession s2Session = saml2Session;
+        assert s2Session!=null;
         try {
-            final NameID nameId = XMLObjectSupport.cloneXMLObject(saml2Session.getNameID());
+            final NameID nameId = XMLObjectSupport.cloneXMLObject(s2Session.getNameID());
             object.setNameID(nameId);
         } catch (final MarshallingException|UnmarshallingException e) {
             log.error("{} Error cloning NameID for use in LogoutRequest for {}", getLogPrefix(),
-                    saml2Session.getId(), e);
+                    s2Session.getId(), e);
             ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_PROC_ERROR);
             return;
         }
@@ -249,11 +252,13 @@ public class AddLogoutRequest extends AbstractProfileAction {
                     (SAMLObjectBuilder<SessionIndex>) bf.<SessionIndex>getBuilderOrThrow(
                             SessionIndex.DEFAULT_ELEMENT_NAME);
             final SessionIndex index = indexBuilder.buildObject();
-            index.setValue(saml2Session.getSessionIndex());
+            index.setValue(s2Session.getSessionIndex());
             object.getSessionIndexes().add(index);
         }
         
-        profileRequestContext.getOutboundMessageContext().setMessage(object);
+        final MessageContext outboundMessageCtx = profileRequestContext.getOutboundMessageContext();
+        assert outboundMessageCtx!=null;
+        outboundMessageCtx.setMessage(object);
     }
 // Checkstyle: CyclomaticComplexity ON
     
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/BestMatchLocationLookupStrategy.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/BestMatchLocationLookupStrategy.java
index 337d5abc1..cbbfe3565 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/BestMatchLocationLookupStrategy.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/BestMatchLocationLookupStrategy.java
@@ -28,6 +28,7 @@ import org.opensaml.saml.criterion.BestMatchLocationCriterion;
 import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
 
 import net.shibboleth.idp.saml.session.SAML2SPSession;
+import net.shibboleth.idp.session.SPSession;
 import net.shibboleth.idp.session.context.LogoutPropagationContext;
 import net.shibboleth.shared.logic.Constraint;
 
@@ -66,8 +67,9 @@ public class BestMatchLocationLookupStrategy implements Function<ProfileRequestC
     @Nullable public BestMatchLocationCriterion apply(@Nullable final ProfileRequestContext input) {
         
         final LogoutPropagationContext propCtx = logoutPropagationContextLookupStrategy.apply(input);
-        if (propCtx != null && propCtx.getSession() instanceof SAML2SPSession) {
-            final String acsLocation = ((SAML2SPSession) propCtx.getSession()).getACSLocation();
+        SPSession session = propCtx != null ? propCtx.getSession() : null;
+        if (session != null && session instanceof SAML2SPSession) {
+            final String acsLocation = ((SAML2SPSession) session).getACSLocation();
             if (acsLocation != null) {
                 return new BestMatchLocationCriterion(acsLocation);
             }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/PrepareInboundMessageContext.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/PrepareInboundMessageContext.java
index e733af386..a4e9a6c0d 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/PrepareInboundMessageContext.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/PrepareInboundMessageContext.java
@@ -33,6 +33,7 @@ import net.shibboleth.shared.primitive.LoggerFactory;
 
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.idp.saml.session.SAML2SPSession;
+import net.shibboleth.idp.session.SPSession;
 import net.shibboleth.idp.session.context.LogoutPropagationContext;
 import net.shibboleth.shared.logic.Constraint;
 
@@ -118,13 +119,15 @@ public class PrepareInboundMessageContext extends AbstractProfileAction {
             log.debug("{} No logout propagation context", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
             return false;
-        } else if (logoutPropCtx.getSession() == null || !(logoutPropCtx.getSession() instanceof SAML2SPSession)) {
+        }
+        final SPSession session = logoutPropCtx.getSession(); 
+        if (session == null || !(session instanceof SAML2SPSession)) {
             log.debug("{} Logout propagation context did not contain a SAML2SPSession", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
             return false;
         }
         
-        relyingPartyId = ((SAML2SPSession) logoutPropCtx.getSession()).getId();
+        relyingPartyId = ((SAML2SPSession) session).getId();
         return true;
     }
 
@@ -134,7 +137,7 @@ public class PrepareInboundMessageContext extends AbstractProfileAction {
         final MessageContext msgCtx = new MessageContext();
         profileRequestContext.setInboundMessageContext(msgCtx);
 
-        final SAMLPeerEntityContext peerContext = msgCtx.getSubcontext(SAMLPeerEntityContext.class, true);
+        final SAMLPeerEntityContext peerContext = msgCtx.getOrCreateSubcontext(SAMLPeerEntityContext.class);
         peerContext.setEntityId(relyingPartyId);
 
         log.debug("{} Initialized inbound context for message to {}", getLogPrefix(), relyingPartyId);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/SAML2SPSessionCreationStrategy.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/SAML2SPSessionCreationStrategy.java
index e1cbaf310..46c795fe4 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/SAML2SPSessionCreationStrategy.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/SAML2SPSessionCreationStrategy.java
@@ -25,6 +25,7 @@ import java.util.function.Function;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.opensaml.messaging.context.BaseContext;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.messaging.context.navigate.MessageLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -36,6 +37,7 @@ import org.opensaml.saml.saml2.core.AuthnStatement;
 import org.opensaml.saml.saml2.core.Response;
 import org.opensaml.saml.saml2.core.SubjectConfirmation;
 import org.opensaml.saml.saml2.core.SubjectConfirmationData;
+import org.opensaml.saml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
 import org.slf4j.Logger;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -121,7 +123,7 @@ public class SAML2SPSessionCreationStrategy implements Function<ProfileRequestCo
             log.debug("No relying party ID, no SAML2SPSession created");
             return null;
         }
-        
+        assert input != null;
         final Pair<Assertion, AuthnStatement> result = getAssertionAndStatement(input);
         if (result == null) {
             log.info("Creating BasicSPSession in the absence of necessary information");
@@ -130,7 +132,10 @@ public class SAML2SPSessionCreationStrategy implements Function<ProfileRequestCo
         }
         
         final Instant now = Instant.now();
-        final Instant sessionBound = result.getSecond().getSessionNotOnOrAfter();
+        final Assertion first = result.getFirst();
+        final AuthnStatement second = result.getSecond();
+        assert first!=null && second!=null;
+        final Instant sessionBound = second.getSessionNotOnOrAfter();
         final Instant expiration;
         if (sessionBound != null) {
             expiration = sessionBound;
@@ -139,7 +144,7 @@ public class SAML2SPSessionCreationStrategy implements Function<ProfileRequestCo
         }
         
         String acsLocation = null;
-        final List<SubjectConfirmation> sc = result.getFirst().getSubject().getSubjectConfirmations();
+        final List<SubjectConfirmation> sc = first.getSubject().getSubjectConfirmations();
         if (sc != null && !sc.isEmpty()) {
             final SubjectConfirmationData scData = sc.get(0).getSubjectConfirmationData();
             if (scData != null) {
@@ -150,17 +155,19 @@ public class SAML2SPSessionCreationStrategy implements Function<ProfileRequestCo
         // Do a basic check for outbound logout capability to the SP based on metadata.
         // This may optimize out subsequent need to process the session for propagation.
         boolean supportLogoutPropagation = false;
-        if (rpCtx.getRelyingPartyIdContextTree() instanceof SAMLPeerEntityContext) {
+        final BaseContext rpIdCtxTree = rpCtx.getRelyingPartyIdContextTree();
+        if (rpIdCtxTree  instanceof SAMLPeerEntityContext) {
             final SAMLMetadataContext mdCtx =
-                    rpCtx.getRelyingPartyIdContextTree().getSubcontext(SAMLMetadataContext.class);
-            if (mdCtx != null && mdCtx.getRoleDescriptor() instanceof SPSSODescriptor) {
+                    rpIdCtxTree.getSubcontext(SAMLMetadataContext.class);
+            final RoleDescriptor roleDescriptor = mdCtx != null ? mdCtx.getRoleDescriptor() : null;
+            if (roleDescriptor != null && roleDescriptor instanceof SPSSODescriptor) {
                 supportLogoutPropagation =
-                        !((SPSSODescriptor) mdCtx.getRoleDescriptor()).getSingleLogoutServices().isEmpty();
+                        !((SPSSODescriptor) roleDescriptor).getSingleLogoutServices().isEmpty();
             }
         }
         
-        return new SAML2SPSession(issuer, now, expiration, result.getFirst().getSubject().getNameID(),
-                result.getSecond().getSessionIndex(), acsLocation, supportLogoutPropagation);
+        return new SAML2SPSession(issuer, now, expiration, first.getSubject().getNameID(),
+                second.getSessionIndex(), acsLocation, supportLogoutPropagation);
     }
 // Checkstyle: CyclomaticComplexity ON
 
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/SAML2SPSessionSerializer.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/SAML2SPSessionSerializer.java
index 5440253b4..6800f9dd5 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/SAML2SPSessionSerializer.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/session/impl/SAML2SPSessionSerializer.java
@@ -122,7 +122,7 @@ public class SAML2SPSessionSerializer extends AbstractSPSessionSerializer {
         final JsonString acsLocation = obj.getJsonString(ACS_LOC_FIELD);
         final boolean supportsLogoutProp = obj.getBoolean(LOGOUT_PROP_FIELD, true);
         
-        if (rawNameID == null && sessionIndex == null) {
+        if (rawNameID == null || sessionIndex == null) {
             throw new IOException("Serialized SAML2SPSession missing required fields");
         }
         

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


More information about the commits mailing list