[java-idp-oidc] branch main updated: Null cleanup of some parts of the impl-module.

Henri Mikkonen henri.mikkonen at iki.fi
Wed Mar 27 18:07:00 UTC 2024


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

hjmikkon pushed a commit to branch main
in repository java-idp-oidc.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-oidc.git;a=commit;h=2a7d4e37d71aa5a7ce7730e82aab6f617a436059

The following commit(s) were added to refs/heads/main by this push:
     new 2a7d4e37 Null cleanup of some parts of the impl-module.
2a7d4e37 is described below

commit 2a7d4e37d71aa5a7ce7730e82aab6f617a436059
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Wed Mar 27 20:06:08 2024 +0200

    Null cleanup of some parts of the impl-module.
---
 .../idp/plugin/oidc/op/OIDCOPPlugin.java           |  6 +-
 .../admin/impl/AbstractAdminApiProfileAction.java  |  3 +-
 .../op/admin/impl/DoClientManagementOperation.java |  6 +-
 .../admin/impl/IssueRegistrationAccessToken.java   | 65 ++++++++++++++--------
 .../AttributeInOIDCRequestedClaimsMatcher.java     | 20 ++++---
 .../impl/AttributeOIDCScopePolicyRule.java         | 15 +++--
 .../AttributeInOIDCRequestedClaimsRuleParser.java  |  2 +-
 .../impl/AttributeOIDCScopeRuleParser.java         |  3 +-
 ...thenticationContextReferenceAuditExtractor.java |  9 ++-
 .../AuthenticationRequestClaimsAuditExtractor.java |  8 ++-
 .../op/audit/impl/IdTokenClaimsAuditExtractor.java |  3 +-
 .../ExtractClientAuthenticationFromRequest.java    |  9 +--
 .../oidc/op/authn/impl/JWTCredentialValidator.java | 43 +++++++++-----
 .../impl/OIDCClientInfoCredentialValidator.java    | 28 ++++++++--
 .../impl/ValidateClientAuthenticationType.java     | 50 ++++++++++++-----
 .../impl/OIDCAuthenticationRequestDecoder.java     |  2 +-
 .../impl/OIDCClientRegistrationRequestDecoder.java |  2 +-
 .../op/decoding/impl/OIDCLogoutRequestDecoder.java |  8 ++-
 .../op/decoding/impl/OIDCTokenRequestDecoder.java  |  2 +-
 .../decoding/impl/OIDCUserInfoRequestDecoder.java  |  2 +-
 .../op/encoding/impl/NimbusResponseEncoder.java    | 26 ++++-----
 .../encoding/impl/OIDCResponseEncoderFactory.java  |  2 +-
 ...ractOIDCBackChannelLogoutPropagationAction.java |  7 ++-
 .../impl/AbstractOIDCLogoutPropagationAction.java  |  5 +-
 .../impl/AbstractOIDCRpInitiatedLogoutAction.java  | 16 ++++--
 .../impl/ExecuteBackChannelLogoutRequest.java      | 40 ++++++++-----
 .../impl/FormOutboundLogoutRequestMessage.java     | 17 ++++--
 .../impl/FormRpInitiatedLogoutResponse.java        | 22 +++++---
 .../logout/profile/impl/PopulateLogoutContext.java | 18 ++++--
 .../impl/PopulateRpInitiatedLogoutContext.java     | 20 ++++---
 .../impl/PrepareBackChannelLogoutRequest.java      | 18 ++++--
 .../impl/ProcessRpInitiatedLogoutRequest.java      | 22 ++++++--
 .../op/logout/profile/impl/RevokeTokenChain.java   | 16 ++++--
 .../profile/impl/SetFrontChannelLogoutSuccess.java |  6 +-
 .../logout/profile/impl/ValidateIdTokenHint.java   | 29 ++++++----
 .../impl/ValidatePostLogoutRedirectURI.java        |  9 ++-
 .../messaging/impl/RpInitiatedLogoutResponse.java  |  1 +
 .../profile/impl/ValidateIdTokenHintTest.java      | 19 +++++--
 38 files changed, 386 insertions(+), 193 deletions(-)

diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/OIDCOPPlugin.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/OIDCOPPlugin.java
index d5536044..b22579e1 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/OIDCOPPlugin.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/OIDCOPPlugin.java
@@ -15,12 +15,12 @@
 package net.shibboleth.idp.plugin.oidc.op;
 
 import java.io.IOException;
-import java.util.Collections;
 
 import net.shibboleth.idp.module.IdPModule;
 import net.shibboleth.idp.plugin.impl.FirstPartyIdPPlugin;
 import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.profile.plugin.PluginException;
+import net.shibboleth.shared.collection.CollectionSupport;
 
 /**
  * Details about the OIDC OP plugin.
@@ -37,8 +37,8 @@ public class OIDCOPPlugin extends FirstPartyIdPPlugin {
         super(OIDCOPPlugin.class);
         try {
             final IdPModule module = new OIDCOPModule();
-            setEnableOnInstall(Collections.singleton(module));
-            setDisableOnRemoval(Collections.singleton(module));
+            setEnableOnInstall(CollectionSupport.singleton(module));
+            setDisableOnRemoval(CollectionSupport.singleton(module));
         } catch (final IOException e) {
             throw e;
         } catch (final ModuleException e) {
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/AbstractAdminApiProfileAction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/AbstractAdminApiProfileAction.java
index 815a21db..696dee2d 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/AbstractAdminApiProfileAction.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/AbstractAdminApiProfileAction.java
@@ -23,7 +23,6 @@ import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.github.jasminb.jsonapi.models.errors.Error;
@@ -35,6 +34,7 @@ import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Base class for admin flow actions producing JSON responses.
@@ -106,6 +106,7 @@ public class AbstractAdminApiProfileAction extends AbstractProfileAction {
             @Nonnull @NotEmpty final String detail) throws IOException {
         
         final HttpServletResponse response = getHttpServletResponse();
+        assert response != null;
         response.setContentType("application/json");
         response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
         response.setStatus(status);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/DoClientManagementOperation.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/DoClientManagementOperation.java
index c718d8af..1d28f987 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/DoClientManagementOperation.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/DoClientManagementOperation.java
@@ -28,6 +28,7 @@ import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.resolver.CriteriaSet;
 import net.shibboleth.shared.resolver.ResolverException;
 
@@ -35,7 +36,6 @@ import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.webflow.execution.RequestContext;
 
 import com.google.common.base.Strings;
@@ -157,7 +157,9 @@ public class DoClientManagementOperation extends AbstractAdminApiProfileAction {
         try {
             final HttpServletRequest request = getHttpServletRequest();
             final HttpServletResponse response = getHttpServletResponse();
-            
+            assert request != null;
+            assert response != null;
+
             response.setContentType("application/json");
             response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
             
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/IssueRegistrationAccessToken.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/IssueRegistrationAccessToken.java
index abe90401..51e1a269 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/IssueRegistrationAccessToken.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/admin/impl/IssueRegistrationAccessToken.java
@@ -29,7 +29,6 @@ import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.nimbusds.oauth2.sdk.AccessTokenResponse;
@@ -38,7 +37,9 @@ import com.nimbusds.oauth2.sdk.token.AccessToken;
 import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
 import com.nimbusds.oauth2.sdk.token.Tokens;
 
+import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+import net.shibboleth.idp.authn.AuthenticationResult;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.authn.context.SubjectContext;
 import net.shibboleth.idp.plugin.oidc.op.cli.IssueRegistrationAccessTokenArguments;
@@ -51,6 +52,7 @@ import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.primitive.StringSupport;
 import net.shibboleth.shared.security.AccessControlService;
 import net.shibboleth.shared.security.DataSealer;
@@ -123,7 +125,7 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
     @Nullable private Map<String,MetadataPolicy> metadataPolicy;
 
     /** The token issuer. */
-    @Nonnull private String issuer;
+    @Nullable private String issuer;
     
     /** The policy location. */
     @Nullable private String policyLocation;
@@ -406,10 +408,13 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
         final String lifetimeString = tokenLifetimeLookupStrategy.apply(profileRequestContext);
         if (lifetimeString != null) {
             try {
-                tokenLifetime = Duration.parse(lifetimeString);
-                if (tokenLifetime.compareTo(defaultTokenLifetime) > 0) {
+                final Duration lifetime = Duration.parse(lifetimeString);
+                assert lifetime != null;
+                if (lifetime.compareTo(defaultTokenLifetime) > 0) {
                     log.warn("Requested token lifetime greater than default, lowering to default", getLogPrefix());
                     tokenLifetime = defaultTokenLifetime;
+                } else {
+                    tokenLifetime = lifetime;
                 }
             } catch (final DateTimeParseException e) {
                 log.warn("{} Token lifetime was not in a supported format", getLogPrefix(), e);
@@ -431,7 +436,8 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
         if (!checkAccess(profileRequestContext)) {
             return;
         }
-        
+
+        assert idGenerator != null;
         final String id = idGenerator.generateIdentifier(xmlSafeIdentifier);
         
         final Instant now = Instant.now();
@@ -449,6 +455,7 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
                 .withReplacement(Boolean.valueOf(replacementLookupStrategy.apply(profileRequestContext)));
         }
 
+        assert builder != null;
         addAuthenticationClaims(profileRequestContext, builder);
         
         final RegistrationClaimsSet claimsSet = builder.build();
@@ -458,8 +465,10 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
         try {
             final String value = getObjectMapper().writeValueAsString(claimsSet);
             log.debug("{} Built the following JSON to be sealed {}", getLogPrefix(), value);
+            assert value != null;
             final String encryptedValue = dataSealer.wrap(value, claimsSet.getExpiration());
             log.debug("{} Encrypted the JSON into {}", getLogPrefix(), encryptedValue);
+            assert tokenLifetime != null;
             accessToken = new BearerAccessToken(encryptedValue, tokenLifetime.getSeconds(), null);
         } catch (final JsonProcessingException e) {
             log.error("{} Could not build JSON", getLogPrefix(), e);
@@ -487,6 +496,8 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
      * @return true iff checks pass
      */
     private boolean checkAccess(@Nonnull final ProfileRequestContext profileRequestContext) {
+        final HttpServletRequest httpServletRequest = getHttpServletRequest();
+        assert httpServletRequest != null;
         try {
             if (policyId != null) {
                 if (policyIdPolicyName == null) {
@@ -494,11 +505,14 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
                     sendError(HttpServletResponse.SC_FORBIDDEN,
                             "Access Denied", "No policy name govering policyId usage, disallowing access.");
                     return false;
-                } else if (!accessControlService.getInstance(policyIdPolicyName).checkAccess(getHttpServletRequest(),
-                        "read", policyId)) {
-                    sendError(HttpServletResponse.SC_FORBIDDEN,
-                            "Access Denied", "Operation is not allowed with the current policy.");
-                    return false;
+                } else {
+                    assert policyIdPolicyName != null;
+                    if (!accessControlService.getInstance(policyIdPolicyName).checkAccess(httpServletRequest,
+                            "read", policyId)) {
+                        sendError(HttpServletResponse.SC_FORBIDDEN,
+                                "Access Denied", "Operation is not allowed with the current policy.");
+                        return false;
+                    }
                 }
             }
 
@@ -508,11 +522,14 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
                     sendError(HttpServletResponse.SC_FORBIDDEN,
                             "Access Denied", "No policy name govering policyId usage, disallowing access.");
                     return false;
-                } else if (!accessControlService.getInstance(policyLocationPolicyName).checkAccess(
-                        getHttpServletRequest(), "read", policyLocation)) {
-                    sendError(HttpServletResponse.SC_FORBIDDEN,
-                            "Access Denied", "Operation is not allowed with the current policy.");
-                    return false;
+                } else {
+                    assert policyLocationPolicyName != null;
+                    if (!accessControlService.getInstance(policyLocationPolicyName).checkAccess(
+                            httpServletRequest, "read", policyLocation)) {
+                        sendError(HttpServletResponse.SC_FORBIDDEN,
+                                "Access Denied", "Operation is not allowed with the current policy.");
+                        return false;
+                    }
                 }
             }
 
@@ -522,11 +539,14 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
                     sendError(HttpServletResponse.SC_FORBIDDEN,
                             "Access Denied", "No policy name govering policyId usage, disallowing access.");
                     return false;
-                } else if (!accessControlService.getInstance(clientIdPolicyName).checkAccess(getHttpServletRequest(),
-                        "write", clientId)) {
-                    sendError(HttpServletResponse.SC_FORBIDDEN,
-                            "Access Denied", "Operation is not allowed with the current policy.");
-                    return false;
+                } else {
+                    assert clientIdPolicyName != null;
+                    if (!accessControlService.getInstance(clientIdPolicyName).checkAccess(httpServletRequest,
+                            "write", clientId)) {
+                        sendError(HttpServletResponse.SC_FORBIDDEN,
+                                "Access Denied", "Operation is not allowed with the current policy.");
+                        return false;
+                    }
                 }
             }
         } catch (final IOException e) {
@@ -551,8 +571,9 @@ public class IssueRegistrationAccessToken extends AbstractAdminApiProfileAction
         
         final AuthenticationContext authnContext = profileRequestContext.getSubcontext(AuthenticationContext.class);
         if (authnContext != null) {
-            if (authnContext.getAuthenticationResult() != null) {
-                builder.withAuthTime(authnContext.getAuthenticationResult().getAuthenticationInstant());
+            final AuthenticationResult authnResult = authnContext.getAuthenticationResult();
+            if (authnResult != null) {
+                builder.withAuthTime(authnResult.getAuthenticationInstant());
             }
         }
         
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/matcher/impl/AttributeInOIDCRequestedClaimsMatcher.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/matcher/impl/AttributeInOIDCRequestedClaimsMatcher.java
index d5b4ada1..33d99b43 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/matcher/impl/AttributeInOIDCRequestedClaimsMatcher.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/matcher/impl/AttributeInOIDCRequestedClaimsMatcher.java
@@ -23,8 +23,8 @@ import javax.annotation.Nonnull;
 import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
+import net.shibboleth.idp.attribute.AttributesMapContainer;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.IdPRequestedAttribute;
@@ -32,6 +32,7 @@ import net.shibboleth.idp.attribute.filter.Matcher;
 import net.shibboleth.idp.attribute.filter.context.AttributeFilterContext;
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /** Class for matching attribute to requested claims. */
 public class AttributeInOIDCRequestedClaimsMatcher extends AbstractIdentifiableInitializableComponent
@@ -141,7 +142,7 @@ public class AttributeInOIDCRequestedClaimsMatcher extends AbstractIdentifiableI
             log.trace("{} No outbound message context", getLogPrefix());
             return Collections.emptySet();
         }
-        final OIDCAuthenticationResponseContext respCtx = profileRequestContext.getOutboundMessageContext()
+        final OIDCAuthenticationResponseContext respCtx = profileRequestContext.ensureOutboundMessageContext()
                 .getSubcontext(OIDCAuthenticationResponseContext.class);
         if (respCtx == null) {
             log.debug("{} No oidc response ctx for this comparison", getLogPrefix());
@@ -160,9 +161,10 @@ public class AttributeInOIDCRequestedClaimsMatcher extends AbstractIdentifiableI
         }
         
         // Are we able to release the values based on claim being requested for id token?
-        if (respCtx.getMappedIdTokenRequestedClaims() != null && !getMatchOnlyUserInfo()) {
-            if (respCtx.getMappedIdTokenRequestedClaims().get().containsKey(attribute.getId())) {
-                if (verifyEssentiality(respCtx.getMappedIdTokenRequestedClaims().get().get(attribute.getId()))) {
+        final AttributesMapContainer idTokenRequestedClaims = respCtx.getMappedIdTokenRequestedClaims();
+        if (idTokenRequestedClaims != null && !getMatchOnlyUserInfo()) {
+            if (idTokenRequestedClaims.get().containsKey(attribute.getId())) {
+                if (verifyEssentiality(idTokenRequestedClaims.get().get(attribute.getId()))) {
                     log.debug("{} All values matched, as {} is a requested ID token claim", getLogPrefix(),
                             attribute.getId());
                     return Set.copyOf(attribute.getValues());
@@ -171,9 +173,10 @@ public class AttributeInOIDCRequestedClaimsMatcher extends AbstractIdentifiableI
         }
         
         // Are we able to release the values based on claim being requested for user info response?
-        if (respCtx.getMappedUserinfoRequestedClaims() != null && !getMatchOnlyIDToken()) {
-            if (respCtx.getMappedUserinfoRequestedClaims().get().containsKey(attribute.getId())) {
-                if (verifyEssentiality(respCtx.getMappedUserinfoRequestedClaims().get().get(attribute.getId()))) {
+        final AttributesMapContainer userInfoRequestedClaims = respCtx.getMappedUserinfoRequestedClaims();
+        if (userInfoRequestedClaims != null && !getMatchOnlyIDToken()) {
+            if (userInfoRequestedClaims.get().containsKey(attribute.getId())) {
+                if (verifyEssentiality(userInfoRequestedClaims.get().get(attribute.getId()))) {
                     log.debug("{} All values matched, as {} is a requested Userinfo claim", getLogPrefix(),
                             attribute.getId());
                     return Set.copyOf(attribute.getValues());
@@ -221,6 +224,7 @@ public class AttributeInOIDCRequestedClaimsMatcher extends AbstractIdentifiableI
                 logPrefix = prefix;
             }
         }
+        assert prefix != null;
         return prefix;
     }
 
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/policyrule/impl/AttributeOIDCScopePolicyRule.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/policyrule/impl/AttributeOIDCScopePolicyRule.java
index 4b4b4059..5796bb5b 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/policyrule/impl/AttributeOIDCScopePolicyRule.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/policyrule/impl/AttributeOIDCScopePolicyRule.java
@@ -20,11 +20,13 @@ import javax.annotation.Nonnull;
 import net.shibboleth.idp.attribute.filter.context.AttributeFilterContext;
 import net.shibboleth.idp.attribute.filter.policyrule.impl.AbstractStringPolicyRule;
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import com.nimbusds.oauth2.sdk.Scope;
 
 /**
  * Compare the scopes of oidc authentication request with the provided value.
@@ -50,13 +52,18 @@ public class AttributeOIDCScopePolicyRule extends AbstractStringPolicyRule {
             log.trace("{} No outbound message context", getLogPrefix());
             return Tristate.FALSE;
         }
-        final OIDCAuthenticationResponseContext ctx = profileRequestContext.getOutboundMessageContext()
+        final OIDCAuthenticationResponseContext ctx = profileRequestContext.ensureOutboundMessageContext()
                 .getSubcontext(OIDCAuthenticationResponseContext.class);
-        if (ctx == null || ctx.getScope() == null) {
+        if (ctx == null) {
+            log.trace("{} No OIDC authentication response context found", getLogPrefix());
+            return Tristate.FALSE;
+        }
+        final Scope ctxScope = ctx.getScope();
+        if (ctxScope == null) {
             log.trace("{} No verified requested scopes for oidc found", getLogPrefix());
             return Tristate.FALSE;
         }
-        final List<String> scopes = ctx.getScope().toStringList();
+        final List<String> scopes = ctxScope.toStringList();
         if (scopes == null || scopes.isEmpty()) {
             log.warn("{} No scopes in oidc request, should not happen", getLogPrefix());
             return Tristate.FAIL;
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/spring/matcher/impl/AttributeInOIDCRequestedClaimsRuleParser.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/spring/matcher/impl/AttributeInOIDCRequestedClaimsRuleParser.java
index 3767a93d..0ea21fbe 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/spring/matcher/impl/AttributeInOIDCRequestedClaimsRuleParser.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/spring/matcher/impl/AttributeInOIDCRequestedClaimsRuleParser.java
@@ -31,7 +31,7 @@ import org.w3c.dom.Element;
 public class AttributeInOIDCRequestedClaimsRuleParser extends BaseAttributeValueMatcherParser {
 
     /** Schema type - afp. */
-    public static final QName SCHEMA_TYPE_AFP =
+    @Nonnull public static final QName SCHEMA_TYPE_AFP =
             new QName(AttributeFilterNamespaceHandler.NAMESPACE, "AttributeInOIDCRequestedClaims");
 
     /** {@inheritDoc} */
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/spring/policyrule/impl/AttributeOIDCScopeRuleParser.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/spring/policyrule/impl/AttributeOIDCScopeRuleParser.java
index dcecf2e2..fca297af 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/spring/policyrule/impl/AttributeOIDCScopeRuleParser.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/attribute/filter/spring/policyrule/impl/AttributeOIDCScopeRuleParser.java
@@ -27,7 +27,8 @@ import net.shibboleth.idp.plugin.oidc.op.attribute.filter.spring.impl.AttributeF
 public class AttributeOIDCScopeRuleParser extends AbstractStringPolicyRuleParser {
 
     /** Schema type. */
-    public static final QName SCHEMA_TYPE_AFP = new QName(AttributeFilterNamespaceHandler.NAMESPACE, "OIDCScope");
+    @Nonnull public static final QName SCHEMA_TYPE_AFP =
+            new QName(AttributeFilterNamespaceHandler.NAMESPACE, "OIDCScope");
 
     /** {@inheritDoc} */
     @Override
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/AuthenticationContextReferenceAuditExtractor.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/AuthenticationContextReferenceAuditExtractor.java
index 0dd16bd2..b4e5998a 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/AuthenticationContextReferenceAuditExtractor.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/AuthenticationContextReferenceAuditExtractor.java
@@ -21,6 +21,8 @@ import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 
+import com.nimbusds.openid.connect.sdk.claims.ACR;
+
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.OIDCAuthenticationResponseContextLookupFunction;
 import net.shibboleth.shared.logic.Constraint;
@@ -57,8 +59,11 @@ public class AuthenticationContextReferenceAuditExtractor implements Function<Pr
     @Nullable
     public String apply(@Nullable final ProfileRequestContext input) {
         final OIDCAuthenticationResponseContext context = ctxLookupStrategy.apply(input);
-        if (context != null && context.getAcr() != null) {
-            return context.getAcr().getValue();
+        if (context != null) {
+            final ACR acr = context.getAcr();
+            if (acr != null) {
+                return acr.getValue();
+            }
         }
 
         return null;
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/AuthenticationRequestClaimsAuditExtractor.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/AuthenticationRequestClaimsAuditExtractor.java
index d5d01f69..91dfffe8 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/AuthenticationRequestClaimsAuditExtractor.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/AuthenticationRequestClaimsAuditExtractor.java
@@ -22,12 +22,13 @@ import javax.annotation.Nonnull;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
+import com.nimbusds.jwt.JWT;
 import com.nimbusds.openid.connect.sdk.AuthenticationRequest;
 
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.AbstractAuthenticationRequestLookupFunction;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * A function that resolves a claim value from the authentication request. If request object was involved and contains
@@ -55,9 +56,10 @@ public class AuthenticationRequestClaimsAuditExtractor extends AbstractAuthentic
     /** {@inheritDoc} */
     @Override
     protected String doLookup(@Nonnull final AuthenticationRequest request) {
+        final JWT requestObject = getRequestObject();
         try {
-            if (getRequestObject() != null && getRequestObject().getJWTClaimsSet().getClaim(key) != null) {
-                return getRequestObject().getJWTClaimsSet().getStringClaim(key);
+            if (requestObject != null && requestObject.getJWTClaimsSet().getClaim(key) != null) {
+                return requestObject.getJWTClaimsSet().getStringClaim(key);
             }
         } catch (final ParseException e) {
             log.error("Unable to parse response mode from request object response_mode value");
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/IdTokenClaimsAuditExtractor.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/IdTokenClaimsAuditExtractor.java
index 3a555772..4c58bc82 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/IdTokenClaimsAuditExtractor.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/audit/impl/IdTokenClaimsAuditExtractor.java
@@ -17,6 +17,7 @@ package net.shibboleth.idp.plugin.oidc.op.audit.impl;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 
@@ -59,7 +60,7 @@ public class IdTokenClaimsAuditExtractor implements Function<ProfileRequestConte
 
     /** {@inheritDoc} */
     @Override
-    public String apply(@Nonnull final ProfileRequestContext input) {
+    public String apply(@Nullable final ProfileRequestContext input) {
         final ClaimsSet claims = idTokenClaimsLookupStrategy.apply(input);
         if (claims != null) {
             return claims.toJSONObject().getAsString(key);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequest.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequest.java
index 4af15e5f..ef0a65a5 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequest.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequest.java
@@ -24,7 +24,6 @@ import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.AbstractOptionallyAuthenticatedRequest;
 import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
@@ -42,6 +41,7 @@ import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
 import net.shibboleth.oidc.profile.config.navigate.TokenEndpointAuthMethodLookupFunction;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Extracts OAuth 2 client authentication details from a request and stores them in an
@@ -101,9 +101,9 @@ public class ExtractClientAuthenticationFromRequest extends AbstractExtractionAc
         }
         
         if (profileRequestContext.getInboundMessageContext() != null) {
-            final Object msg = profileRequestContext.getInboundMessageContext().getMessage();
-            if (msg instanceof AbstractOptionallyAuthenticatedRequest) {
-                request = (AbstractOptionallyAuthenticatedRequest) msg;
+            final Object msg = profileRequestContext.ensureInboundMessageContext().getMessage();
+            if (msg instanceof AbstractOptionallyAuthenticatedRequest aoar) {
+                request = aoar;
                 return true;
             }
         }
@@ -119,6 +119,7 @@ public class ExtractClientAuthenticationFromRequest extends AbstractExtractionAc
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final AuthenticationContext authenticationContext) {
 
+        assert request != null;
         final ClientAuthentication clientAuthentication = request.getClientAuthentication();
         
         final OAuth2ClientAuthenticationContext ctx =
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java
index 848f6a87..4f1c8fac 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java
@@ -34,12 +34,12 @@ import net.shibboleth.oidc.security.jose.context.SecurityParametersContext;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.SignedJWT;
@@ -76,11 +76,17 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
     /** Constructor. */
     public JWTCredentialValidator() {
         // PRC -> AuthenticationContext -> OAuth2ClientAuthenticationContext
-        clientAuthContextLookupStrategy = new ChildContextLookup<>(OAuth2ClientAuthenticationContext.class).compose(
-                new ChildContextLookup<>(AuthenticationContext.class));
+        final Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> cacls =
+                new ChildContextLookup<>(OAuth2ClientAuthenticationContext.class).compose(
+                        new ChildContextLookup<>(AuthenticationContext.class));
+        assert cacls != null;
+        clientAuthContextLookupStrategy = cacls;
         // PRC -> INBOUND -> SPC
-        securityParametersLookupStrategy = new ChildContextLookup<>(SecurityParametersContext.class).compose(
-                new InboundMessageContextLookup());
+        final Function<ProfileRequestContext,SecurityParametersContext> spls =
+                new ChildContextLookup<>(SecurityParametersContext.class).compose(
+                        new InboundMessageContextLookup());
+        assert spls != null;
+        securityParametersLookupStrategy = spls;
         
         claimsValidatorLookupStrategy = new ClaimsValidatorLookupFunction();
     }
@@ -147,12 +153,16 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
         
         final OAuth2ClientAuthenticationContext clientAuthContext =
                 clientAuthContextLookupStrategy.apply(profileRequestContext);
-        if (clientAuthContext == null || clientAuthContext.getClientAuthentication() == null) {
+        if (clientAuthContext == null) {
             log.debug("{} No OAuth 2.0 client authentication information found", getLogPrefix());
             return null;
         }
         
         final ClientAuthentication clientAuth = clientAuthContext.getClientAuthentication();
+        if (clientAuth == null) {
+            log.debug("{} No OAuth 2.0 client authentication information found", getLogPrefix());
+            return null;
+        }
         if (!ClientAuthenticationMethod.CLIENT_SECRET_JWT.equals(clientAuth.getMethod()) &&
                 !ClientAuthenticationMethod.PRIVATE_KEY_JWT.equals(clientAuth.getMethod())) {
             log.debug("{} OAuth client authentication for '{}' of unsupported type: {}", getLogPrefix(),
@@ -173,9 +183,12 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
         }
 
         final JWTAuthentication jwtAuth = (JWTAuthentication) clientAuth;
-
+        final SignedJWT clientAssertion = jwtAuth.getClientAssertion();
+        final ClientID clientId = clientAuth.getClientID();
+        assert clientAssertion != null;
+        assert clientId != null;
         try {
-            validateJWTClaims(profileRequestContext, jwtAuth.getClientAssertion(), clientAuth.getClientID());
+            validateJWTClaims(profileRequestContext, clientAssertion, clientId);
         } catch (final Exception e) {
             log.info("{} Login by '{}' failed", getLogPrefix(), clientAuth.getClientID());
             if (errorHandler != null) { 
@@ -187,7 +200,7 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
         
         log.info("{} Login by '{}' succeeded", getLogPrefix(), clientAuth.getClientID());
         
-        return populateSubject(clientAuth.getClientID(), jwtAuth.getClientAssertion());
+        return populateSubject(clientId, clientAssertion);
     }    
 // Checkstyle: CyclomaticComplexity ON
 
@@ -219,7 +232,8 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
             log.warn("{} Could not parse the JWT from client '{}' into claims set", getLogPrefix(), clientId);
             throw e;
         }
-        
+
+        assert claimsSet != null;
         try {
             validator.validate(claimsSet, profileRequestContext);
         } catch (final JWTValidationException e) {
@@ -240,9 +254,12 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
            @Nonnull final SignedJWT token) {
       
        final Subject subject = new Subject();
-       subject.getPrincipals().add(new UsernamePrincipal(clientId.getValue()));
-       if (saveTokenToCredentialSet) {
-           subject.getPublicCredentials().add(token);
+       final String clientIdValue = clientId.getValue();
+       if (clientIdValue != null) {
+           subject.getPrincipals().add(new UsernamePrincipal(clientIdValue));
+           if (saveTokenToCredentialSet) {
+               subject.getPublicCredentials().add(token);
+           }
        }
       
        return super.populateSubject(subject);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java
index b6ad080f..6a46b6d0 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java
@@ -34,15 +34,16 @@ import net.shibboleth.shared.codec.StringDigester;
 import net.shibboleth.shared.codec.StringDigester.OutputFormat;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
 import com.nimbusds.oauth2.sdk.client.ClientMetadata;
+import com.nimbusds.oauth2.sdk.id.ClientID;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 
 /**
@@ -63,8 +64,11 @@ public class OIDCClientInfoCredentialValidator extends AbstractUsernamePasswordC
 
     /** Constructor. */
     public OIDCClientInfoCredentialValidator() {
-        oidcMetadataContextLookupStrategy = new ChildContextLookup<>(OIDCMetadataContext.class).compose(
-                new InboundMessageContextLookup());
+        final Function<ProfileRequestContext,OIDCMetadataContext> omcls =
+                new ChildContextLookup<>(OIDCMetadataContext.class).compose(
+                        new InboundMessageContextLookup());
+        assert omcls != null;
+        oidcMetadataContextLookupStrategy = omcls;
     }
     
     /**
@@ -101,18 +105,24 @@ public class OIDCClientInfoCredentialValidator extends AbstractUsernamePasswordC
 
         final OIDCMetadataContext oidcMetadataContext = oidcMetadataContextLookupStrategy.apply(profileRequestContext);
         
-        if (oidcMetadataContext == null || oidcMetadataContext.getClientInformation() == null 
-                || oidcMetadataContext.getClientInformation() == null) {
+        if (oidcMetadataContext == null || oidcMetadataContext.getClientInformation() == null ) {
             log.debug("{} OIDC client metadata is missing", getLogPrefix());
             return null;
         }
 
         final OIDCClientInformation clientInformation = oidcMetadataContext.getClientInformation();
+        assert clientInformation != null;
         final ClientMetadata clientMetadata = clientInformation.getMetadata();
+        assert clientMetadata != null;
         if (ClientAuthenticationMethod.NONE.equals(clientMetadata.getTokenEndpointAuthMethod())) {
             log.debug("{} OIDC client metadata contains 'none' type for endpoint authentication");
             final Subject subject = new Subject();
-            subject.getPrincipals().add(new UsernamePrincipal(applyTransforms(clientInformation.getID().getValue())));
+            final ClientID clientId = clientInformation.getID();
+            assert clientId != null;
+            final String clientIdValue = clientId.getValue();
+            if (clientIdValue != null) {
+                subject.getPrincipals().add(new UsernamePrincipal(applyTransforms(clientIdValue)));
+            }
             return super.populateSubject(subject);
         } else if (clientInformation.getSecret() == null) {
             log.debug("{} OIDC client metadata for '{}' missing client secret", getLogPrefix(),
@@ -132,7 +142,13 @@ public class OIDCClientInfoCredentialValidator extends AbstractUsernamePasswordC
             @Nullable final ErrorHandler errorHandler) throws Exception {
 
         final OIDCMetadataContext oidcMetadataContext = oidcMetadataContextLookupStrategy.apply(profileRequestContext);
+        if (oidcMetadataContext == null || oidcMetadataContext.getClientInformation() == null ) {
+            log.debug("{} OIDC client metadata is missing", getLogPrefix());
+            return null;
+        }
+
         final OIDCClientInformation clientInformation = oidcMetadataContext.getClientInformation();
+        assert clientInformation != null;
 
         final String username = usernamePasswordContext.getTransformedUsername();
         log.debug("{} Attempting to authenticate effective client ID '{}' ", getLogPrefix(), username);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationType.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationType.java
index 3b0780df..b100a1ed 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationType.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationType.java
@@ -27,10 +27,11 @@ import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
 import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
+import com.nimbusds.oauth2.sdk.id.ClientID;
+import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
 
 import net.shibboleth.idp.authn.AbstractAuthenticationAction;
@@ -40,6 +41,7 @@ import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
 import net.shibboleth.oidc.profile.config.navigate.TokenEndpointAuthMethodLookupFunction;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Validates the client authentication type with the token_endpoint_auth_method stored in the client's metadata
@@ -61,7 +63,7 @@ public class ValidateClientAuthenticationType extends AbstractAuthenticationActi
     @Nonnull private Function<ProfileRequestContext,OIDCMetadataContext> oidcMetadataContextLookupStrategy;
     
     /** Strategy to obtain enabled token endpoint authentication methods. */
-    @Nullable private Function<ProfileRequestContext,Set<ClientAuthenticationMethod>> 
+    @Nonnull private Function<ProfileRequestContext,Set<ClientAuthenticationMethod>> 
         tokenEndpointAuthMethodsLookupStrategy;
     
     /** The attached OIDC metadata context. */
@@ -77,8 +79,11 @@ public class ValidateClientAuthenticationType extends AbstractAuthenticationActi
      * Constructor.
      */
     public ValidateClientAuthenticationType() {
-        oidcMetadataContextLookupStrategy = new ChildContextLookup<>(OIDCMetadataContext.class).compose(
-                new InboundMessageContextLookup());
+        final Function<ProfileRequestContext,OIDCMetadataContext> omcls =
+                new ChildContextLookup<>(OIDCMetadataContext.class).compose(
+                        new InboundMessageContextLookup());
+        assert omcls != null;
+        oidcMetadataContextLookupStrategy = omcls;
         tokenEndpointAuthMethodsLookupStrategy = new TokenEndpointAuthMethodLookupFunction();
     }
         
@@ -89,7 +94,7 @@ public class ValidateClientAuthenticationType extends AbstractAuthenticationActi
      */
     public void setOIDCMetadataContextLookupStrategy(
             @Nonnull final Function<ProfileRequestContext, OIDCMetadataContext> strategy) {
-        ifInitializedThrowUnmodifiabledComponentException();
+        checkSetterPreconditions();
 
         oidcMetadataContextLookupStrategy =
                 Constraint.isNotNull(strategy, "OIDCMetadataContext lookup strategy cannot be null");
@@ -101,6 +106,8 @@ public class ValidateClientAuthenticationType extends AbstractAuthenticationActi
      */
     public void setTokenEndpointAuthMethodsLookupStrategy(@Nonnull final Function<ProfileRequestContext, 
             Set<ClientAuthenticationMethod>> strategy) {
+        checkSetterPreconditions();
+
         tokenEndpointAuthMethodsLookupStrategy = Constraint.isNotNull(strategy, 
                 "Strategy to obtain enabled token endpoint authentication methods cannot be null");
         
@@ -139,10 +146,15 @@ public class ValidateClientAuthenticationType extends AbstractAuthenticationActi
 
         // Pull the client's registered authn method, or default to client_secret_basic.
         // If no metadata exists, leave null.
-        if (oidcMetadataContext != null && oidcMetadataContext.getClientInformation() != null) {
-            final OIDCClientMetadata clientMetadata = oidcMetadataContext.getClientInformation().getOIDCMetadata();
-            registeredMethod = clientMetadata.getTokenEndpointAuthMethod() != null ? 
-                    clientMetadata.getTokenEndpointAuthMethod() : ClientAuthenticationMethod.CLIENT_SECRET_BASIC;
+        if (oidcMetadataContext != null) {
+            final OIDCClientInformation clientInformation = oidcMetadataContext.getClientInformation();
+            if (clientInformation != null) {
+                final OIDCClientMetadata clientMetadata = clientInformation.getOIDCMetadata();
+                registeredMethod = clientMetadata.getTokenEndpointAuthMethod() != null ? 
+                        clientMetadata.getTokenEndpointAuthMethod() : ClientAuthenticationMethod.CLIENT_SECRET_BASIC;
+            } else {
+                registeredMethod = null;
+            }
         } else {
             registeredMethod = null;
         }
@@ -157,7 +169,10 @@ public class ValidateClientAuthenticationType extends AbstractAuthenticationActi
             log.warn("{} Client '{}' registered {} but attempted {}", getLogPrefix(), getClientID(),
                     registeredMethod, used);
             ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
-        } else if (!enabledMethods.contains(used)) {
+            return;
+        }
+        assert enabledMethods != null;
+        if (!enabledMethods.contains(used)) {
             log.warn("{} Requested method {} not enabled in profile configuration", getLogPrefix(), used);
             ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
         }
@@ -169,12 +184,19 @@ public class ValidateClientAuthenticationType extends AbstractAuthenticationActi
      * @return client ID, or null it it couldn't be found.
      */
     @Nullable private String getClientID() {
-        if (oidcMetadataContext != null && oidcMetadataContext.getClientInformation() != null) {
-            return oidcMetadataContext.getClientInformation().getID().getValue();
+        if (oidcMetadataContext != null) {
+            final OIDCClientInformation clientInformation = oidcMetadataContext.getClientInformation();
+            if (clientInformation != null) {
+                return getClientIDValue(clientInformation.getID());
+            }
         }
-        if (clientAuthentication != null && clientAuthentication.getClientID() != null) {
-            return clientAuthentication.getClientID().getValue();
+        if (clientAuthentication != null) {
+            return getClientIDValue(clientAuthentication.getClientID());
         }
         return null;
     }
+
+    @Nullable private String getClientIDValue(@Nullable final ClientID clientId) {
+        return clientId == null ? null : clientId.getValue();
+    }
 }
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCAuthenticationRequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCAuthenticationRequestDecoder.java
index 6ab68ac1..2b17f6a5 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCAuthenticationRequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCAuthenticationRequestDecoder.java
@@ -21,7 +21,6 @@ import javax.annotation.Nullable;
 
 import org.opensaml.messaging.decoder.MessageDecodingException;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.base.MoreObjects;
 import com.nimbusds.oauth2.sdk.http.HTTPRequest;
@@ -29,6 +28,7 @@ import com.nimbusds.oauth2.sdk.http.JakartaServletUtils;
 import com.nimbusds.openid.connect.sdk.AuthenticationRequest;
 
 import net.shibboleth.idp.plugin.oidc.op.oauth2.decoding.impl.BaseOAuth2RequestDecoder;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Message decoder decoding OpenID Connect {@link AuthenticationRequest}s.
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCClientRegistrationRequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCClientRegistrationRequestDecoder.java
index cf7a9557..283a2759 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCClientRegistrationRequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCClientRegistrationRequestDecoder.java
@@ -21,7 +21,6 @@ import javax.annotation.Nullable;
 
 import org.opensaml.messaging.decoder.MessageDecodingException;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.base.MoreObjects;
@@ -36,6 +35,7 @@ import net.shibboleth.idp.plugin.oidc.op.oauth2.decoding.impl.BaseOAuth2RequestD
 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;
 
 /**
  * Message decoder decoding OpenID Connect {@link ClientRegistrationRequest}s.
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCLogoutRequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCLogoutRequestDecoder.java
index db1c5bd6..049d006a 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCLogoutRequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCLogoutRequestDecoder.java
@@ -21,7 +21,6 @@ import javax.annotation.Nullable;
 
 import org.opensaml.messaging.decoder.MessageDecodingException;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.base.MoreObjects;
 import com.nimbusds.oauth2.sdk.http.HTTPRequest;
@@ -29,6 +28,7 @@ import com.nimbusds.oauth2.sdk.http.JakartaServletUtils;
 import com.nimbusds.openid.connect.sdk.LogoutRequest;
 
 import net.shibboleth.idp.plugin.oidc.op.oauth2.decoding.impl.BaseOAuth2RequestDecoder;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Message decoder decoding OpenID Connect {@link LogoutRequest}s.
@@ -45,7 +45,11 @@ public class OIDCLogoutRequestDecoder extends BaseOAuth2RequestDecoder<LogoutReq
         try {
             final HTTPRequest httpReq = JakartaServletUtils.createHTTPRequest(getHttpServletRequest());
             getProtocolMessageLogger().trace("Inbound request {}", RequestUtil.toString(httpReq));
-            return LogoutRequest.parse(httpReq);
+            final LogoutRequest logoutRequest = LogoutRequest.parse(httpReq);
+            if (logoutRequest == null) {
+                throw new MessageDecodingException("LogoutRequest could not be parsed");
+            }
+            return logoutRequest;
         } catch (final com.nimbusds.oauth2.sdk.ParseException | IOException e) {
             log.error("Unable to decode inbound request: {}", e.getMessage());
             throw new MessageDecodingException(e);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCTokenRequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCTokenRequestDecoder.java
index eae66cea..681beceb 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCTokenRequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCTokenRequestDecoder.java
@@ -20,7 +20,6 @@ import javax.annotation.Nullable;
 
 import org.opensaml.messaging.decoder.MessageDecodingException;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.base.MoreObjects;
 import com.nimbusds.oauth2.sdk.ParseException;
@@ -29,6 +28,7 @@ import com.nimbusds.oauth2.sdk.http.HTTPRequest;
 import com.nimbusds.oauth2.sdk.http.JakartaServletUtils;
 
 import net.shibboleth.idp.plugin.oidc.op.oauth2.decoding.impl.BaseOAuth2RequestDecoder;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Message decoder decoding OpenID Connect {@link TokenRequest}s.
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCUserInfoRequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCUserInfoRequestDecoder.java
index 5c10ac95..32f973dd 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCUserInfoRequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/decoding/impl/OIDCUserInfoRequestDecoder.java
@@ -20,7 +20,6 @@ import javax.annotation.Nullable;
 
 import org.opensaml.messaging.decoder.MessageDecodingException;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.base.MoreObjects;
 import com.nimbusds.oauth2.sdk.ParseException;
@@ -29,6 +28,7 @@ import com.nimbusds.oauth2.sdk.http.JakartaServletUtils;
 import com.nimbusds.openid.connect.sdk.UserInfoRequest;
 
 import net.shibboleth.idp.plugin.oidc.op.oauth2.decoding.impl.BaseOAuth2RequestDecoder;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Message decoder decoding OpenID Connect {@link UserInfoRequest}s.
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/encoding/impl/NimbusResponseEncoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/encoding/impl/NimbusResponseEncoder.java
index 97aade66..eb0fe77c 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/encoding/impl/NimbusResponseEncoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/encoding/impl/NimbusResponseEncoder.java
@@ -27,8 +27,6 @@ import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.VelocityEngine;
 import org.opensaml.messaging.encoder.MessageEncodingException;
 import org.opensaml.messaging.encoder.servlet.AbstractHttpServletResponseMessageEncoder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.nimbusds.oauth2.sdk.AuthorizationResponse;
@@ -55,9 +53,6 @@ public class NimbusResponseEncoder extends AbstractHttpServletResponseMessageEnc
     /** Default template ID for using FORM POST response mode. */
     @Nonnull @NotEmpty public static final String DEFAULT_TEMPLATE_ID = "/templates/oidc-form-post.vm";
 
-    /** Class logger. */
-    @Nonnull private final Logger log = LoggerFactory.getLogger(NimbusResponseEncoder.class);
-
     /** Velocity engine used to evaluate the template when using FORM POST response mode. */
     @Nullable private VelocityEngine velocityEngine;
 
@@ -90,8 +85,8 @@ public class NimbusResponseEncoder extends AbstractHttpServletResponseMessageEnc
      */
     public void setVelocityTemplateId(final String newVelocityTemplateId) {
         checkSetterPreconditions();
-        Constraint.isNotEmpty(newVelocityTemplateId, "Velocity template id must not not be null or empty");
-        velocityTemplateId = newVelocityTemplateId;
+        velocityTemplateId = Constraint.isNotEmpty(newVelocityTemplateId,
+                "Velocity template id must not not be null or empty");
     }
 
     /**
@@ -176,31 +171,34 @@ public class NimbusResponseEncoder extends AbstractHttpServletResponseMessageEnc
     /** {@inheritDoc} */
     protected void doEncode() throws MessageEncodingException {
         
-        if (!(getMessageContext().getMessage() instanceof Response)) {
+        final Object message = getMessageContext().getMessage();
+        if (!(message instanceof Response)) {
             throw new MessageEncodingException("Incorrect message type");
         }
 
         try {
             final HttpServletResponse response = getHttpServletResponse();
-            if (impliesFormPost(getMessageContext().getMessage())) {
-                if (velocityEngine == null) {
+            assert response != null;
+            if (impliesFormPost(message) && message instanceof AuthorizationResponse authzResponse) {
+                final VelocityEngine engine = velocityEngine;
+                if (engine == null) {
                     throw new MessageEncodingException("VelocityEngine must be supplied for form post response mode");
                 }
-                final VelocityContext context = doPostEncode((AuthorizationResponse) getMessageContext().getMessage());
+                final VelocityContext context = doPostEncode(authzResponse);
                 HttpServletSupport.addNoCacheHeaders(response);
                 HttpServletSupport.setUTF8Encoding(response);
                 HttpServletSupport.setContentType(response, "text/html");
                 final Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
-                velocityEngine.mergeTemplate(velocityTemplateId, "UTF-8", context, out);
+                engine.mergeTemplate(velocityTemplateId, "UTF-8", context, out);
                 out.flush();
                 out.close();
                 // Write it also to log
                 final StringWriter writer = new StringWriter();
-                velocityEngine.mergeTemplate(velocityTemplateId, "UTF-8", context, writer);
+                engine.mergeTemplate(velocityTemplateId, "UTF-8", context, writer);
                 getProtocolMessageLogger().trace("Outbound response {}", ResponseUtil.toString(response, writer.toString()));
                 return;
             }
-            final HTTPResponse resp = ((Response) getMessageContext().getMessage()).toHTTPResponse();
+            final HTTPResponse resp = ((Response) message).toHTTPResponse();
             getProtocolMessageLogger().trace("Outbound response {}", ResponseUtil.toString(resp, objectMapper));
             JakartaServletUtils.applyHTTPResponse(resp, response);
         } catch (final IOException e) {
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/encoding/impl/OIDCResponseEncoderFactory.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/encoding/impl/OIDCResponseEncoderFactory.java
index bbf233bf..4f90248a 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/encoding/impl/OIDCResponseEncoderFactory.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/encoding/impl/OIDCResponseEncoderFactory.java
@@ -23,7 +23,6 @@ import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.encoder.MessageEncoder;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.Response;
 
@@ -31,6 +30,7 @@ import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.component.AbstractInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * A source of encoders that first verifies a message being an instance of Nimbus
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCBackChannelLogoutPropagationAction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCBackChannelLogoutPropagationAction.java
index e698c6f2..9d8c3453 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCBackChannelLogoutPropagationAction.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCBackChannelLogoutPropagationAction.java
@@ -15,12 +15,13 @@
 package net.shibboleth.idp.plugin.oidc.op.logout.profile.impl;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCBackChannelLogoutPropagationContext;
+import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCLogoutPropagationContext;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -44,8 +45,10 @@ public class AbstractOIDCBackChannelLogoutPropagationAction extends AbstractOIDC
             return false;
         }
 
+        final OIDCLogoutPropagationContext logoutContext = getOidcLogoutContext();
+        assert logoutContext != null;
         oidcBackChannelLogoutContext =
-                getOidcLogoutContext().getSubcontext(OIDCBackChannelLogoutPropagationContext.class);
+                logoutContext.getSubcontext(OIDCBackChannelLogoutPropagationContext.class);
         if (oidcBackChannelLogoutContext == null) {
             log.error("{} No OIDC back-channel logout context found", this.getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCLogoutPropagationAction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCLogoutPropagationAction.java
index 2be84f24..5cbb68b8 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCLogoutPropagationAction.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCLogoutPropagationAction.java
@@ -19,13 +19,13 @@ import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractOIDCResponseAction
 import net.shibboleth.idp.plugin.oidc.op.session.OIDCRPSession;
 import net.shibboleth.idp.session.context.LogoutPropagationContext;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.util.function.Function;
 
@@ -78,7 +78,7 @@ public class AbstractOIDCLogoutPropagationAction extends AbstractOIDCResponseAct
         }
 
         oidcLogoutContext =
-                profileRequestContext.getOutboundMessageContext().getSubcontext(OIDCLogoutPropagationContext.class);
+                profileRequestContext.ensureOutboundMessageContext().getSubcontext(OIDCLogoutPropagationContext.class);
         if (oidcLogoutContext == null) {
             log.error("{} No OIDC logout context found", this.getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
@@ -92,6 +92,7 @@ public class AbstractOIDCLogoutPropagationAction extends AbstractOIDCResponseAct
             return false;
         }
         
+        assert logoutPropagationContext != null;
         if (logoutPropagationContext.getSession() instanceof OIDCRPSession rpSession) {
             oidcRPSession = rpSession;
         } else {
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCRpInitiatedLogoutAction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCRpInitiatedLogoutAction.java
index 8fa687c1..3f9888df 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCRpInitiatedLogoutAction.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/AbstractOIDCRpInitiatedLogoutAction.java
@@ -18,6 +18,7 @@ import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCRpInitiatedLogout
 import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractOIDCRequestAction;
 import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
@@ -26,7 +27,6 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.openid.connect.sdk.LogoutRequest;
 
@@ -60,10 +60,16 @@ public class AbstractOIDCRpInitiatedLogoutAction extends AbstractOIDCRequestActi
      * Constructor.
      */
     public AbstractOIDCRpInitiatedLogoutAction() {
-        oidcMetadataCtxLookupStrategy = new ChildContextLookup<>(OIDCMetadataContext.class).compose(
-                new InboundMessageContextLookup());
-        oidcRpInitatedLogoutCtxLookupStrategy = new ChildContextLookup<>(OIDCRpInitiatedLogoutContext.class).compose(
-                new OutboundMessageContextLookup());
+        final Function<ProfileRequestContext, OIDCMetadataContext> omcls = 
+                new ChildContextLookup<>(OIDCMetadataContext.class).compose(
+                        new InboundMessageContextLookup());
+        assert omcls != null;
+        oidcMetadataCtxLookupStrategy = omcls;
+        final Function<ProfileRequestContext, OIDCRpInitiatedLogoutContext> orilcls =
+                new ChildContextLookup<>(OIDCRpInitiatedLogoutContext.class).compose(
+                        new OutboundMessageContextLookup());
+        assert orilcls != null;
+        oidcRpInitatedLogoutCtxLookupStrategy = orilcls;
     }
 
     /**
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ExecuteBackChannelLogoutRequest.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ExecuteBackChannelLogoutRequest.java
index b751cabb..342a3db1 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ExecuteBackChannelLogoutRequest.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ExecuteBackChannelLogoutRequest.java
@@ -18,11 +18,14 @@ import com.nimbusds.common.contenttype.ContentType;
 import com.nimbusds.jwt.JWT;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 
+import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCLogoutPropagationContext;
+import net.shibboleth.idp.plugin.oidc.op.session.OIDCRPSession;
 import net.shibboleth.idp.session.context.LogoutPropagationContext;
 import net.shibboleth.oidc.profile.config.navigate.ClientInformationStringValueLookupFunction;
 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;
 
 import org.apache.hc.client5.http.classic.HttpClient;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
@@ -40,7 +43,6 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.security.httpclient.HttpClientSecurityParameters;
 import org.opensaml.security.httpclient.HttpClientSecuritySupport;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -152,15 +154,19 @@ public class ExecuteBackChannelLogoutRequest extends AbstractOIDCBackChannelLogo
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
-        final String relyingPartyId = getOidcRPSession().getId();
-        final String subject = getOidcRPSession().getSubject();
-        final String sessionId = getOidcRPSession().getSessionIdentifier();
+        final OIDCRPSession rpSession = getOidcRPSession();
+        assert rpSession != null;
+        final String relyingPartyId = rpSession.getId();
+        final String subject = rpSession.getSubject();
+        final String sessionId = rpSession.getSessionIdentifier();
 
         final HttpPost httpRequest = new HttpPost(backChannelLogoutURI);
 
         final List<NameValuePair> nvps = new ArrayList<>();
-        nvps.add(new BasicNameValuePair("logout_token", logoutToken.serialize()));
-        log.trace("{} Logout token to be used in the request: {}", getLogPrefix(), logoutToken.serialize());
+        assert logoutToken != null;
+        final String serializedToken = logoutToken.serialize();
+        nvps.add(new BasicNameValuePair("logout_token", serializedToken));
+        log.trace("{} Logout token to be used in the request: {}", getLogPrefix(), serializedToken);
         final UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8);
         httpRequest.setEntity(urlEncodedFormEntity);
 
@@ -169,30 +175,37 @@ public class ExecuteBackChannelLogoutRequest extends AbstractOIDCBackChannelLogo
         final HttpClientContext httpContext = buildHttpContext(httpRequest);
         log.debug("{} Sending the back-channel logout request to {}", getLogPrefix(), backChannelLogoutURI);
 
+        final LogoutPropagationContext logoutPropContext = getLogoutPropagationContext();
+        assert logoutPropContext != null;
+
         try (final ClassicHttpResponse response = httpClient.executeOpen(null, httpRequest, httpContext)) {
 
-            HttpClientSecuritySupport.checkTLSCredentialEvaluated(httpContext, httpRequest.getUri().getScheme());
+            final String scheme = httpRequest.getUri().getScheme();
+            assert scheme != null;
+            HttpClientSecuritySupport.checkTLSCredentialEvaluated(httpContext, scheme);
 
+            final OIDCLogoutPropagationContext oidcLogouPropContext = getOidcLogoutContext();
+            assert oidcLogouPropContext != null;
             if (response.getCode() == HttpStatus.SC_OK || response.getCode() == HttpStatus.SC_NO_CONTENT) {
-                if (!getOidcLogoutContext().hasRevocationError()) {
-                    getLogoutPropagationContext().setResult(LogoutPropagationContext.Result.Success);
+                if (!oidcLogouPropContext.hasRevocationError()) {
+                    logoutPropContext.setResult(LogoutPropagationContext.Result.Success);
                     log.debug("{} back-channel logout for rp '{}', sub '{}' and sid '{}' succeeded.", getLogPrefix(),
                             relyingPartyId, subject, sessionId);
                 } else {
-                    getLogoutPropagationContext().setResult(LogoutPropagationContext.Result.Failure);
+                    logoutPropContext.setResult(LogoutPropagationContext.Result.Failure);
                     log.debug("{} back-channel logout for rp '{}', sub '{}' and sid '{}' succeeded, but overall " +
                             "result remains 'failure' due to previous error",
                             getLogPrefix(), relyingPartyId, subject, sessionId);
                 }
             } else {
-                getLogoutPropagationContext().setResult(LogoutPropagationContext.Result.Failure);
+                logoutPropContext.setResult(LogoutPropagationContext.Result.Failure);
                 log.error("{} back-channel logout for rp '{}', sub '{}' and sid '{}' failed. HTTP code: {}",
                         getLogPrefix(), relyingPartyId, subject, sessionId, response.getCode());
             }
         } catch (final IOException | URISyntaxException e) {
             log.error("{} back-channel logout for rp '{}' with token '{}' failed.", getLogPrefix(), relyingPartyId,
-                    logoutToken.serialize(), e);
-            getLogoutPropagationContext().setResult(LogoutPropagationContext.Result.Failure);
+                    serializedToken, e);
+            logoutPropContext.setResult(LogoutPropagationContext.Result.Failure);
         }
     }
 
@@ -205,6 +218,7 @@ public class ExecuteBackChannelLogoutRequest extends AbstractOIDCBackChannelLogo
     @Nonnull
     private HttpClientContext buildHttpContext(@Nonnull final HttpUriRequest request) {
         final HttpClientContext clientContext = HttpClientContext.create();
+        assert clientContext != null;
         HttpClientSecuritySupport.marshalSecurityParameters(clientContext, httpClientSecurityParameters, false);
         HttpClientSecuritySupport.addDefaultTLSTrustEngineCriteria(clientContext, request);
         return clientContext;
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/FormOutboundLogoutRequestMessage.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/FormOutboundLogoutRequestMessage.java
index d57fd6ad..19553f9a 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/FormOutboundLogoutRequestMessage.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/FormOutboundLogoutRequestMessage.java
@@ -23,14 +23,15 @@ import javax.annotation.Nullable;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.impl.FrontChannelLogoutPropagationResponse;
+import net.shibboleth.idp.plugin.oidc.op.session.OIDCRPSession;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.profile.context.navigate.IssuerLookupFunction;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.primitive.StringSupport;
 
 /**
@@ -92,6 +93,7 @@ public class FormOutboundLogoutRequestMessage extends AbstractOIDCLogoutPropagat
         }
 
         clientInformation = getMetadataContext().getClientInformation();
+        assert clientInformation != null;
         frontChannelLogoutUri = clientInformation.getOIDCMetadata().getFrontChannelLogoutURI();
         if (frontChannelLogoutUri == null) {
             log.error("{} No front-channel logout URI registered for the client", getLogPrefix());
@@ -107,12 +109,17 @@ public class FormOutboundLogoutRequestMessage extends AbstractOIDCLogoutPropagat
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
         final FrontChannelLogoutPropagationResponse response;
+        assert frontChannelLogoutUri != null;
+        final String uri = frontChannelLogoutUri.toString();
+        assert uri != null;
+        assert clientInformation != null;
         if (clientInformation.getOIDCMetadata().requiresFrontChannelLogoutSession()) {
-            response = new FrontChannelLogoutPropagationResponse(frontChannelLogoutUri.toString(), issuer,
-                    getOidcRPSession().getSessionIdentifier());
+            final OIDCRPSession rpSession = getOidcRPSession();
+            assert rpSession != null;
+            response = new FrontChannelLogoutPropagationResponse(uri, issuer, rpSession.getSessionIdentifier());
         } else {
-            response = new FrontChannelLogoutPropagationResponse(frontChannelLogoutUri.toString());
+            response = new FrontChannelLogoutPropagationResponse(uri);
         }
-        profileRequestContext.getOutboundMessageContext().setMessage(response);
+        profileRequestContext.ensureOutboundMessageContext().setMessage(response);
     }
 }
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/FormRpInitiatedLogoutResponse.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/FormRpInitiatedLogoutResponse.java
index 4261703f..0512d133 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/FormRpInitiatedLogoutResponse.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/FormRpInitiatedLogoutResponse.java
@@ -21,9 +21,10 @@ import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
+import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCRpInitiatedLogoutContext;
 import net.shibboleth.idp.plugin.oidc.op.messaging.impl.RpInitiatedLogoutResponse;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Action that forms outbound message based on request and response context. Formed message is set to
@@ -47,12 +48,14 @@ public class FormRpInitiatedLogoutResponse extends AbstractOIDCRpInitiatedLogout
             return false;
         }
 
-        postLogoutRedirectUri = getRpInitiatedLogoutContext().getPostLogoutRedirectUri();
+        final OIDCRpInitiatedLogoutContext rpInitiatedLogoutContext = getRpInitiatedLogoutContext();
+        assert rpInitiatedLogoutContext != null;
+        postLogoutRedirectUri = rpInitiatedLogoutContext.getPostLogoutRedirectUri();
         if (postLogoutRedirectUri == null) {
             log.debug("{} No post logout redirection URI set in the context", getLogPrefix());
         }
 
-        state = getRpInitiatedLogoutContext().getState();
+        state = rpInitiatedLogoutContext.getState();
 
         return true;
     }
@@ -62,15 +65,16 @@ public class FormRpInitiatedLogoutResponse extends AbstractOIDCRpInitiatedLogout
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
         final RpInitiatedLogoutResponse response;
-        if (postLogoutRedirectUri == null) {
-            response = new RpInitiatedLogoutResponse(null);
-        } else {
+        if (postLogoutRedirectUri != null) {
+            final String uri = postLogoutRedirectUri.toString();
             if (state == null) {
-                response = new RpInitiatedLogoutResponse(postLogoutRedirectUri.toString());
+                response = new RpInitiatedLogoutResponse(uri);
             } else {
-                response = new RpInitiatedLogoutResponse(postLogoutRedirectUri.toString(), state);
+                response = new RpInitiatedLogoutResponse(uri, state);
             }
+        } else {
+            response = new RpInitiatedLogoutResponse(null);
         }
-        profileRequestContext.getOutboundMessageContext().setMessage(response);
+        profileRequestContext.ensureOutboundMessageContext().setMessage(response);
     }
 }
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PopulateLogoutContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PopulateLogoutContext.java
index c2f72be7..98f53174 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PopulateLogoutContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PopulateLogoutContext.java
@@ -18,6 +18,7 @@ import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCLogoutPropagation
 import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractInitializeOutboundResponseMessageContext;
 import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
@@ -26,7 +27,6 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
@@ -58,10 +58,17 @@ public class PopulateLogoutContext extends AbstractInitializeOutboundResponseMes
      * Constructor.
      */
     public PopulateLogoutContext() {
-        oidcLogoutContextCreationStrategy = new ChildContextLookup<>(OIDCLogoutPropagationContext.class, true)
-                .compose(new OutboundMessageContextLookup());
-        oidcMetadataContextLookupStrategy = new ChildContextLookup<>(OIDCMetadataContext.class)
-                .compose(new InboundMessageContextLookup());
+        final Function<ProfileRequestContext, OIDCLogoutPropagationContext> olccs =
+                new ChildContextLookup<>(OIDCLogoutPropagationContext.class, true)
+                    .compose(new OutboundMessageContextLookup());
+        assert olccs != null;
+        oidcLogoutContextCreationStrategy = olccs;
+        
+        final Function<ProfileRequestContext, OIDCMetadataContext> omcls =
+                new ChildContextLookup<>(OIDCMetadataContext.class)
+                    .compose(new InboundMessageContextLookup());
+        assert omcls != null;
+        oidcMetadataContextLookupStrategy = omcls;
     }
 
     /**
@@ -115,6 +122,7 @@ public class PopulateLogoutContext extends AbstractInitializeOutboundResponseMes
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
             return;
         }
+        assert clientInformation != null;
         final OIDCClientMetadata metadata = clientInformation.getOIDCMetadata();
         logoutContext.setBackChannelLogoutUri(metadata.getBackChannelLogoutURI());
         logoutContext.setFrontChannelLogoutUri(metadata.getFrontChannelLogoutURI());
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PopulateRpInitiatedLogoutContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PopulateRpInitiatedLogoutContext.java
index f92c9253..1ab758f9 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PopulateRpInitiatedLogoutContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PopulateRpInitiatedLogoutContext.java
@@ -21,9 +21,7 @@ import javax.annotation.Nonnull;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Predicates;
 import com.nimbusds.jwt.EncryptedJWT;
 import com.nimbusds.jwt.JWT;
 import com.nimbusds.oauth2.sdk.id.ClientID;
@@ -32,6 +30,8 @@ import com.nimbusds.oauth2.sdk.id.State;
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCRpInitiatedLogoutContext;
 import net.shibboleth.oidc.profile.core.OidcEventIds;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.PredicateSupport;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.primitive.StringSupport;
 
 /**
@@ -49,7 +49,7 @@ public class PopulateRpInitiatedLogoutContext extends AbstractOIDCRpInitiatedLog
      * Constructor.
      */
     public PopulateRpInitiatedLogoutContext() {
-        idTokenHintEnforcedPredicate = Predicates.alwaysFalse();
+        idTokenHintEnforcedPredicate = PredicateSupport.alwaysFalse();
     }
 
     /**
@@ -84,22 +84,24 @@ public class PopulateRpInitiatedLogoutContext extends AbstractOIDCRpInitiatedLog
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
         final JWT requestedIdTokenHint = getLogoutRequest().getIDTokenHint();
+        final OIDCRpInitiatedLogoutContext rpInitiatedLogoutContext = getRpInitiatedLogoutContext();
+        assert rpInitiatedLogoutContext != null;
         if (requestedIdTokenHint != null) {
-            getRpInitiatedLogoutContext().setRequestedIdTokenHint(requestedIdTokenHint);
+            rpInitiatedLogoutContext.setRequestedIdTokenHint(requestedIdTokenHint);
             if (!(requestedIdTokenHint instanceof EncryptedJWT)) {
                 log.debug("{} ID token hint is not encrypted, setting it to processedIdTokenHint.", getLogPrefix());
-                getRpInitiatedLogoutContext().setProcessedIdTokenHint(requestedIdTokenHint);
+                rpInitiatedLogoutContext.setProcessedIdTokenHint(requestedIdTokenHint);
             }
         }
-        getRpInitiatedLogoutContext().setLogoutHint(StringSupport.trimOrNull(getLogoutRequest().getLogoutHint()));
-        getRpInitiatedLogoutContext().setPostLogoutRedirectUri(getLogoutRequest().getPostLogoutRedirectionURI());
+        rpInitiatedLogoutContext.setLogoutHint(StringSupport.trimOrNull(getLogoutRequest().getLogoutHint()));
+        rpInitiatedLogoutContext.setPostLogoutRedirectUri(getLogoutRequest().getPostLogoutRedirectionURI());
         final ClientID clientId = getLogoutRequest().getClientID();
         if (clientId != null) {
-            getRpInitiatedLogoutContext().setRequestedClientId(clientId.getValue());
+            rpInitiatedLogoutContext.setRequestedClientId(clientId.getValue());
         }
         final State state = getLogoutRequest().getState();
         if (state != null) {
-            getRpInitiatedLogoutContext().setState(state.getValue());
+            rpInitiatedLogoutContext.setState(state.getValue());
         }
     }
 }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequest.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequest.java
index 843d3aa4..d7b37371 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequest.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequest.java
@@ -22,8 +22,10 @@ import com.nimbusds.openid.connect.sdk.claims.LogoutTokenClaimsSet;
 import com.nimbusds.openid.connect.sdk.claims.SessionID;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCBackChannelLogoutPropagationContext;
+import net.shibboleth.idp.plugin.oidc.op.session.OIDCRPSession;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.security.IdentifierGenerationStrategy;
 import net.shibboleth.shared.security.impl.SecureRandomIdentifierGenerationStrategy;
 
@@ -31,7 +33,6 @@ import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -110,14 +111,19 @@ public class PrepareBackChannelLogoutRequest extends AbstractOIDCBackChannelLogo
     /** {@inheritDoc} */
     @Override
     protected void doExecute(@Nonnull ProfileRequestContext profileRequestContext) {
-        final Issuer iss = new Issuer(getOidcRPSession().getIssuer());
-        final Subject sub = new Subject(getOidcRPSession().getSubject());
-        final List<Audience> aud = Collections.singletonList(new Audience(getOidcRPSession().getId()));
+        final OIDCRPSession rpSession = getOidcRPSession();
+        assert rpSession != null;
+        final Issuer iss = new Issuer(rpSession.getIssuer());
+        final Subject sub = new Subject(rpSession.getSubject());
+        final List<Audience> aud = Collections.singletonList(new Audience(rpSession.getId()));
         final Date iat = Calendar.getInstance().getTime();
+        assert idGenerator != null;
         final JWTID jti = new JWTID(idGenerator.generateIdentifier(xmlSafeIdentifier));
-        final SessionID sid = new SessionID(getOidcRPSession().getSessionIdentifier());
+        final SessionID sid = new SessionID(rpSession.getSessionIdentifier());
 
         final LogoutTokenClaimsSet logoutTokenClaimsSet = new LogoutTokenClaimsSet(iss, sub, aud, iat, jti, sid);
-        getOidcBackChannelLogoutContext().setLogoutTokenClaimsSet(logoutTokenClaimsSet);
+        final OIDCBackChannelLogoutPropagationContext bcLogoutContext = getOidcBackChannelLogoutContext();
+        assert bcLogoutContext != null;
+        bcLogoutContext.setLogoutTokenClaimsSet(logoutTokenClaimsSet);
     }
 }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ProcessRpInitiatedLogoutRequest.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ProcessRpInitiatedLogoutRequest.java
index 93970f20..b0725171 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ProcessRpInitiatedLogoutRequest.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ProcessRpInitiatedLogoutRequest.java
@@ -113,19 +113,26 @@ public class ProcessRpInitiatedLogoutRequest extends AbstractOIDCRpInitiatedLogo
         subjectContextCreationStrategy = new ChildContextLookup<>(SubjectContext.class, true);
         sessionContextCreationStrategy = new ChildContextLookup<>(SessionContext.class, true);
         logoutContextCreationStrategy = new ChildContextLookup<>(LogoutContext.class, true);
-        issuerLookupStrategy = new LogoutRequestClientIDLookupFunction().compose(new InboundMessageContextLookup());
+        final Function<ProfileRequestContext,ClientID> ils = new LogoutRequestClientIDLookupFunction().compose(
+                new InboundMessageContextLookup());
+        assert ils != null;
+        issuerLookupStrategy = ils;
         sessionResolverCriteriaStrategy = new Function<>() {
             public CriteriaSet apply(final ProfileRequestContext input) {
                 final ClientID clientID = issuerLookupStrategy.apply(input);
-                final JWT processedIdTokenHint = getRpInitiatedLogoutContext().getProcessedIdTokenHint();
+                final OIDCRpInitiatedLogoutContext rpInitiatedLogoutContext = getRpInitiatedLogoutContext();
+                assert rpInitiatedLogoutContext != null;
+                final JWT processedIdTokenHint = rpInitiatedLogoutContext.getProcessedIdTokenHint();
                 if (clientID != null && processedIdTokenHint != null) {
+                    final String clientIdValue = clientID.getValue();
+                    assert clientIdValue != null;
                     log.debug("{} Building criteria set with clientID {} and idTokenHint {}", getLogPrefix(),
-                            clientID.getValue(), processedIdTokenHint);
+                            clientIdValue, processedIdTokenHint);
                     try {
                         final String sessionId =
                                 processedIdTokenHint.getJWTClaimsSet().getStringClaim(TokenClaimsSet.KEY_SESSION_ID);
                         if (sessionId != null) {
-                            return new CriteriaSet(new SPSessionCriterion(clientID.getValue(), sessionId));
+                            return new CriteriaSet(new SPSessionCriterion(clientIdValue, sessionId));
                         }
                     } catch (final ParseException e) {
                         log.error("{} Could not parse session ID from id_token_hint", getLogPrefix(), e);
@@ -343,13 +350,16 @@ public class ProcessRpInitiatedLogoutRequest extends AbstractOIDCRpInitiatedLogo
             
             // Make sure the RP matches.
             if (issuer == null || !oidcRpSession.getId().equals(issuer.getValue())) {
+                assert issuer != null;
                 log.trace("{} The session ID {} did not match with the issuer {}", getLogPrefix(),
                         oidcRpSession.getId(), issuer.getValue());
                 return false;
             } 
 
             // Match subject
-            final JWT idTokenHint = getRpInitiatedLogoutContext().getProcessedIdTokenHint();
+            final OIDCRpInitiatedLogoutContext rpInitiatedLogoutContext = getRpInitiatedLogoutContext();
+            assert rpInitiatedLogoutContext != null;
+            final JWT idTokenHint = rpInitiatedLogoutContext.getProcessedIdTokenHint();
             if (idTokenHint != null) {
                 try {
                     final String subject = idTokenHint.getJWTClaimsSet().getSubject();
@@ -365,7 +375,7 @@ public class ProcessRpInitiatedLogoutRequest extends AbstractOIDCRpInitiatedLogo
                 return false;
             }
 
-            final String logoutHint = getRpInitiatedLogoutContext().getLogoutHint();
+            final String logoutHint = rpInitiatedLogoutContext.getLogoutHint();
             final BiPredicate<String,SPSession> matchingPredicate =
                     logoutHintMatchingStrategyLookupStrategy.apply(profileRequestContext);
             if (matchingPredicate != null && matchingPredicate.test(logoutHint, oidcRpSession)) {
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/RevokeTokenChain.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/RevokeTokenChain.java
index 6c7b922d..fab085ee 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/RevokeTokenChain.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/RevokeTokenChain.java
@@ -14,17 +14,19 @@
 
 package net.shibboleth.idp.plugin.oidc.op.logout.profile.impl;
 
+import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCLogoutPropagationContext;
 import net.shibboleth.idp.plugin.oidc.op.profile.logic.DefaultChainRevocationLifetimeLookupStrategy;
+import net.shibboleth.idp.plugin.oidc.op.session.OIDCRPSession;
 import net.shibboleth.idp.plugin.oidc.op.storage.RevocationCacheContexts;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.storage.RevocationCache;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -96,7 +98,9 @@ public class RevokeTokenChain extends AbstractOIDCLogoutPropagationAction {
             return false;
         }
 
-        rootTokenIdentifier = getOidcRPSession().getRootTokenIdentifier();
+        final OIDCRPSession rpSession = getOidcRPSession();
+        assert rpSession != null;
+        rootTokenIdentifier = rpSession.getRootTokenIdentifier();
         if (rootTokenIdentifier == null) {
             log.debug("{} OIDCRPSession context did not contain a root jti, nothing to revoke.", getLogPrefix());
             return false;
@@ -110,12 +114,16 @@ public class RevokeTokenChain extends AbstractOIDCLogoutPropagationAction {
      */
     @Override
     protected void doExecute(@Nonnull ProfileRequestContext profileRequestContext) {
+        final OIDCLogoutPropagationContext oidcLogoutPropContext = getOidcLogoutContext();
+        assert oidcLogoutPropContext != null;
+        assert rootTokenIdentifier != null;
+        assert revocationLifetime != null;
         if (revocationCache.revoke(
                 RevocationCacheContexts.AUTHORIZATION_CODE, rootTokenIdentifier, revocationLifetime)) {
-            getOidcLogoutContext().setRevocationError(false);
+            oidcLogoutPropContext.setRevocationError(false);
             log.debug("{} Revoked all tokens based on ID '{}'", getLogPrefix(), rootTokenIdentifier);
         } else {
-            getOidcLogoutContext().setRevocationError(true);
+            oidcLogoutPropContext.setRevocationError(true);
             log.warn("{} Failed to revoke tokens based on ID '{}'", getLogPrefix(), rootTokenIdentifier);
         }
     }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/SetFrontChannelLogoutSuccess.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/SetFrontChannelLogoutSuccess.java
index 9b14d804..5f2ffa31 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/SetFrontChannelLogoutSuccess.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/SetFrontChannelLogoutSuccess.java
@@ -18,10 +18,10 @@ import javax.annotation.Nonnull;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import net.shibboleth.idp.session.context.LogoutPropagationContext;
 import net.shibboleth.idp.session.context.LogoutPropagationContext.Result;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Action that sets the {@link LogoutPropagationContext#setResult(Result)} as 'success'.
@@ -35,6 +35,8 @@ public class SetFrontChannelLogoutSuccess extends AbstractOIDCLogoutPropagationA
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
         log.debug("{} Set front-channel logout propagation result 'success'", getLogPrefix());
-        getLogoutPropagationContext().setResult(Result.Success);
+        final LogoutPropagationContext logoutPropagationContext = getLogoutPropagationContext();
+        assert logoutPropagationContext != null;
+        logoutPropagationContext.setResult(Result.Success);
     }
 }
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidateIdTokenHint.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidateIdTokenHint.java
index 7045a860..b375d8d2 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidateIdTokenHint.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidateIdTokenHint.java
@@ -22,17 +22,19 @@ import javax.annotation.Nullable;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jwt.JWT;
+import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.SignedJWT;
 
+import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCRpInitiatedLogoutContext;
 import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
 import net.shibboleth.oidc.jwt.claims.JWTValidationException;
 import net.shibboleth.oidc.profile.core.OidcEventIds;
 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;
 
 /**
  * Action validates ID token hint in response context.
@@ -75,8 +77,10 @@ public class ValidateIdTokenHint extends AbstractOIDCRpInitiatedLogoutAction {
         if (!super.doPreExecute(profileRequestContext)) {
             return false;
         }
-        
-        idTokenHint = getRpInitiatedLogoutContext().getProcessedIdTokenHint();
+
+        final OIDCRpInitiatedLogoutContext rpInitiatedLogoutContext = getRpInitiatedLogoutContext();
+        assert rpInitiatedLogoutContext != null;
+        idTokenHint = rpInitiatedLogoutContext.getProcessedIdTokenHint();
         if (idTokenHint == null) {
             log.debug("{} No ID token hint, nothing to do", getLogPrefix());
             return false;
@@ -88,18 +92,21 @@ public class ValidateIdTokenHint extends AbstractOIDCRpInitiatedLogoutAction {
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
-        if (!(idTokenHint instanceof SignedJWT)) {
+        if (idTokenHint instanceof SignedJWT signedJwt) {
+            try {
+                final JWTClaimsSet claimsSet = signedJwt.getJWTClaimsSet();
+                assert claimsSet != null;
+                claimsValidator.validate(claimsSet, profileRequestContext);
+            } catch (final JWTValidationException | ParseException e) {
+                log.warn("{} JWT validation failed: {}", getLogPrefix(), e.getMessage());
+                ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_ID_TOKEN_HINT);
+                return;
+            }
+        } else {
             log.error("{} ID token hint is not signed", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_ID_TOKEN_HINT);
             return;
         }
-        try {
-            claimsValidator.validate(idTokenHint.getJWTClaimsSet(), profileRequestContext);
-        } catch (final JWTValidationException | ParseException e) {
-            log.warn("{} JWT validation failed: {}", getLogPrefix(), e.getMessage());
-            ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_ID_TOKEN_HINT);
-            return;
-        }
 
     }    
 
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidatePostLogoutRedirectURI.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidatePostLogoutRedirectURI.java
index 414fcfbf..59ecb3fe 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidatePostLogoutRedirectURI.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidatePostLogoutRedirectURI.java
@@ -23,11 +23,12 @@ import javax.annotation.Nullable;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
+import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCRpInitiatedLogoutContext;
 import net.shibboleth.idp.plugin.oidc.op.profile.logic.DefaultPostLogoutRedirectURIValidationPredicate;
 import net.shibboleth.oidc.profile.core.OidcEventIds;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Action that validates post redirect URI is expected if it's being requested.
@@ -67,8 +68,10 @@ public class ValidatePostLogoutRedirectURI extends AbstractOIDCRpInitiatedLogout
         if (!super.doPreExecute(profileRequestContext)) {
             return false;
         }
-        
-        requestedRedirectURI = getRpInitiatedLogoutContext().getPostLogoutRedirectUri();
+
+        final OIDCRpInitiatedLogoutContext rpInitiatedLogoutContext = getRpInitiatedLogoutContext();
+        assert rpInitiatedLogoutContext != null;
+        requestedRedirectURI = rpInitiatedLogoutContext.getPostLogoutRedirectUri();
         if (requestedRedirectURI == null) {
             log.debug("{} No post logout redirect URI found, nothing to do", getLogPrefix());
             return false;
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/impl/RpInitiatedLogoutResponse.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/impl/RpInitiatedLogoutResponse.java
index e93a4b98..2225c648 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/impl/RpInitiatedLogoutResponse.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/messaging/impl/RpInitiatedLogoutResponse.java
@@ -94,6 +94,7 @@ public class RpInitiatedLogoutResponse implements Response {
         final URI uri;
         try {
             if (state != null) {
+                assert postLogoutRedirectionUri != null;
                 if (postLogoutRedirectionUri.contains("?")) {
                     uri = new URI(serializeParameters(postLogoutRedirectionUri + "&"));
                 } else {
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidateIdTokenHintTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidateIdTokenHintTest.java
index 5875cd4a..b7df5ae6 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidateIdTokenHintTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/ValidateIdTokenHintTest.java
@@ -14,10 +14,15 @@
 
 package net.shibboleth.idp.plugin.oidc.op.logout.profile.impl;
 
+import java.text.ParseException;
+
+import javax.annotation.Nonnull;
+
 import org.mockito.Mockito;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.PlainJWT;
 import com.nimbusds.jwt.SignedJWT;
 
@@ -32,7 +37,7 @@ import net.shibboleth.shared.component.ComponentInitializationException;
  */
 public class ValidateIdTokenHintTest extends BaseOIDCRpInitiatedLogoutActionTest<ValidateIdTokenHint> {
 
-    ClaimsValidator validator = Mockito.mock(ClaimsValidator.class);
+    @Nonnull ClaimsValidator validator = Mockito.mock(ClaimsValidator.class);
 
     @Override
     protected ValidateIdTokenHint constructAction() {
@@ -64,16 +69,20 @@ public class ValidateIdTokenHintTest extends BaseOIDCRpInitiatedLogoutActionTest
     }
 
     @Test
-    public void notValidatedIdTokenHint() throws JWTValidationException {
+    public void notValidatedIdTokenHint() throws JWTValidationException, ParseException {
         Mockito.doThrow(JWTValidationException.class).when(validator).validate(Mockito.any(), Mockito.any());
-        rpInitiatedLogoutContext.setProcessedIdTokenHint(Mockito.mock(SignedJWT.class));
+        final SignedJWT signedJwt = Mockito.mock(SignedJWT.class);
+        Mockito.when(signedJwt.getJWTClaimsSet()).thenReturn(new JWTClaimsSet.Builder().build());
+        rpInitiatedLogoutContext.setProcessedIdTokenHint(signedJwt);
         ActionTestingSupport.assertEvent(action.execute(requestContext), OidcEventIds.INVALID_ID_TOKEN_HINT);
     }
 
     @Test
-    public void validatedIdTokenHint() throws JWTValidationException {
+    public void validatedIdTokenHint() throws JWTValidationException, ParseException {
         Mockito.doNothing().when(validator).validate(Mockito.any(), Mockito.any());
-        rpInitiatedLogoutContext.setProcessedIdTokenHint(Mockito.mock(SignedJWT.class));
+        final SignedJWT signedJwt = Mockito.mock(SignedJWT.class);
+        Mockito.when(signedJwt.getJWTClaimsSet()).thenReturn(new JWTClaimsSet.Builder().build());
+        rpInitiatedLogoutContext.setProcessedIdTokenHint(signedJwt);
         ActionTestingSupport.assertProceedEvent(action.execute(requestContext));
     }
 

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


More information about the commits mailing list