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

Henri Mikkonen henri.mikkonen at iki.fi
Thu Mar 28 10:46:43 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=88151a8638ecd938cb3036cafd8a63fb02536b80

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

commit 88151a8638ecd938cb3036cafd8a63fb02536b80
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Thu Mar 28 12:46:34 2024 +0200

    Null cleanup of some parts of the impl-module.
---
 .../impl/AlgorithmInfoMetadataValueResolver.java   |  13 ++-
 .../metadata/impl/ArrayMetadataValueResolver.java  |   2 +-
 .../impl/CredentialMetadataValueResolver.java      |  88 ++++++++-------
 .../DynamicFilesystemProviderMetadataResolver.java |  13 ++-
 .../impl/FilesystemMetadataValueResolver.java      |  11 +-
 .../impl/FilesystemProviderMetadataResolver.java   |  40 ++++---
 .../impl/FunctionMetadataValueResolver.java        |  14 ++-
 .../decoding/impl/BaseOAuth2RequestDecoder.java    |   6 +-
 .../impl/OAuth2AuthorizationRequestDecoder.java    |   2 +-
 .../impl/OAuth2IntrospectionRequestDecoder.java    |   9 +-
 .../impl/OAuth2RevocationRequestDecoder.java       |   2 +-
 .../impl/PopulateOIDCMetadataContext.java          |  21 +++-
 .../impl/SetEntityIdToSAMLPeerEntityContext.java   |   2 +-
 .../AbstractOAuthAuthorizationRequestAction.java   |   7 --
 .../AbstractOAuthAuthorizationResponseAction.java  |  14 ++-
 .../profile/impl/AbstractProcessTokenAction.java   |  27 ++++-
 .../op/oauth2/profile/impl/BuildAccessToken.java   | 122 +++++++++++++++------
 .../BuildRevokeTokenErrorResponseFromEvent.java    |   4 +-
 .../FormOutboundIntrospectionResponseMessage.java  |  11 +-
 .../FormOutboundRevokeTokenResponseMessage.java    |   2 +-
 .../oidc/op/oauth2/profile/impl/RevokeToken.java   |   9 +-
 .../impl/SetAccessTokenToResponseContext.java      |  43 ++++++--
 .../SetAuthorizationCodeToResponseContext.java     |  66 ++++++++---
 .../impl/SetRequestObjectToResponseContext.java    |  46 +++++---
 .../op/oauth2/profile/impl/ValidateAudience.java   |  27 +++--
 .../impl/ValidateAuthorizationRequestType.java     |   2 +-
 .../impl/ValidateClientIDAgainstPolicy.java        |  22 ++--
 .../oauth2/profile/impl/ValidateCodeChallenge.java |   9 +-
 .../oauth2/profile/impl/ValidateRedirectURI.java   |  28 +++--
 .../oauth2/profile/impl/ValidateRequestObject.java |  56 ++++------
 .../oauth2/profile/impl/ValidateResponseType.java  |  33 ++++--
 .../oidc/op/oauth2/profile/impl/ValidateScope.java |  31 ++++--
 .../impl/AbstractBuildErrorResponseFromEvent.java  |   5 +-
 33 files changed, 503 insertions(+), 284 deletions(-)

diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/AlgorithmInfoMetadataValueResolver.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/AlgorithmInfoMetadataValueResolver.java
index 23a04755..6180dad4 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/AlgorithmInfoMetadataValueResolver.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/AlgorithmInfoMetadataValueResolver.java
@@ -28,15 +28,16 @@ import org.opensaml.security.config.SecurityConfiguration;
 import org.opensaml.xmlsec.AlgorithmPolicyConfiguration;
 import org.opensaml.xmlsec.algorithm.AlgorithmSupport;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import net.shibboleth.idp.plugin.oidc.op.metadata.resolver.MetadataValueResolver;
 import net.shibboleth.oidc.profile.config.JSONSecurityConfiguration;
 import net.shibboleth.oidc.security.jose.EncryptionConfiguration;
 import net.shibboleth.oidc.security.jose.SignatureSigningConfiguration;
+import net.shibboleth.profile.config.ProfileConfiguration;
 import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.resolver.ResolverException;
 
 /**
@@ -47,7 +48,7 @@ public class AlgorithmInfoMetadataValueResolver extends AbstractIdentifiableInit
         implements MetadataValueResolver {
 
     /** Class logger. */
-    private final Logger log = LoggerFactory.getLogger(AlgorithmInfoMetadataValueResolver.class);
+    @Nonnull private final Logger log = LoggerFactory.getLogger(AlgorithmInfoMetadataValueResolver.class);
 
     /**
      * Strategy used to locate the {@link RelyingPartyContext} associated with a given {@link ProfileRequestContext}.
@@ -116,9 +117,11 @@ public class AlgorithmInfoMetadataValueResolver extends AbstractIdentifiableInit
             log.warn("Could not find profile configuration, nothing to do");
             return result;
         }
-        
+
+        final ProfileConfiguration profileConfig = rpCtx.getProfileConfig();
+        assert profileConfig != null;
         final SecurityConfiguration securityConfig =
-                rpCtx.getProfileConfig().getSecurityConfiguration(profileRequestContext);
+                profileConfig.getSecurityConfiguration(profileRequestContext);
         if (securityConfig == null) {
             log.warn("Could not find security configuration, nothing to do");
             return result;
@@ -163,7 +166,7 @@ public class AlgorithmInfoMetadataValueResolver extends AbstractIdentifiableInit
     protected void populateAlgorithmsAgainstPolicy(final List<String> algorithms, final List<String> candidates,
             final AlgorithmPolicyConfiguration policy) {
         for (final String candidate : candidates) {
-            if (!AlgorithmSupport.validateAlgorithmURI(candidate, 
+            if (candidate != null && !AlgorithmSupport.validateAlgorithmURI(candidate, 
                     policy.getIncludedAlgorithms(), 
                     policy.getExcludedAlgorithms())) {
                 log.debug("Algorithm failed include/exclude validation: {}", candidate);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/ArrayMetadataValueResolver.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/ArrayMetadataValueResolver.java
index 3e2a7a5a..aca0d242 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/ArrayMetadataValueResolver.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/ArrayMetadataValueResolver.java
@@ -23,7 +23,6 @@ import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import net.minidev.json.JSONArray;
 import net.minidev.json.JSONObject;
@@ -31,6 +30,7 @@ import net.shibboleth.idp.plugin.oidc.op.metadata.resolver.MetadataValueResolver
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.primitive.StringSupport;
 import net.shibboleth.shared.resolver.ResolverException;
 
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/CredentialMetadataValueResolver.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/CredentialMetadataValueResolver.java
index bbbc9e94..9e7a7d04 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/CredentialMetadataValueResolver.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/CredentialMetadataValueResolver.java
@@ -23,13 +23,14 @@ import java.util.List;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.security.config.SecurityConfiguration;
 import org.opensaml.security.credential.Credential;
+import org.opensaml.security.credential.UsageType;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jose.jwk.Curve;
 import com.nimbusds.jose.jwk.ECKey;
@@ -41,10 +42,13 @@ import net.minidev.json.JSONArray;
 import net.shibboleth.idp.plugin.oidc.op.metadata.resolver.MetadataValueResolver;
 import net.shibboleth.oidc.profile.config.JSONSecurityConfiguration;
 import net.shibboleth.oidc.security.credential.JWKCredential;
+import net.shibboleth.oidc.security.jose.SignatureSigningConfiguration;
+import net.shibboleth.profile.config.ProfileConfiguration;
 import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.resolver.ResolverException;
 
 /**
@@ -55,7 +59,7 @@ public class CredentialMetadataValueResolver extends AbstractIdentifiableInitial
         implements MetadataValueResolver {
 
     /** Class logger. */
-    private final Logger log = LoggerFactory.getLogger(CredentialMetadataValueResolver.class);
+    @Nonnull private final Logger log = LoggerFactory.getLogger(CredentialMetadataValueResolver.class);
 
     /**
      * Strategy used to locate the {@link RelyingPartyContext} associated with a given {@link ProfileRequestContext}.
@@ -96,15 +100,20 @@ public class CredentialMetadataValueResolver extends AbstractIdentifiableInitial
         final PublicKey publicKey = credential.getPublicKey();
         final String kid = credential instanceof JWKCredential ? ((JWKCredential) credential).getKid() : null;
         final KeyUse use;
-        switch (credential.getUsageType()) {
-            case SIGNING:
-                use = KeyUse.SIGNATURE;
-                break;
-            case ENCRYPTION:
-                use = KeyUse.ENCRYPTION;
-                break;
-            default:
-                use = null;
+        final UsageType usageType = credential.getUsageType();
+        if (usageType != null) {
+            switch (usageType) {
+                case SIGNING:
+                    use = KeyUse.SIGNATURE;
+                    break;
+                case ENCRYPTION:
+                    use = KeyUse.ENCRYPTION;
+                    break;
+                default:
+                    use = null;
+            }
+        } else {
+            use = null;
         }
         final JWK jwk;
         if (publicKey instanceof RSAPublicKey) {
@@ -122,7 +131,7 @@ public class CredentialMetadataValueResolver extends AbstractIdentifiableInitial
             jwk = builder.build();
         } else {
             // TODO: support other algorithms
-            log.warn("Unsupported public key {}", publicKey.getAlgorithm());
+            log.warn("Unsupported public key {}", publicKey == null ? null : publicKey.getAlgorithm());
             throw new ConstraintViolationException("Unsupported public key algorithm");
         }
         return jwk;
@@ -138,44 +147,45 @@ public class CredentialMetadataValueResolver extends AbstractIdentifiableInitial
             log.warn("Could not find profile configuration, nothing to do");
             return result;
         }
-        
-        final SecurityConfiguration securityConfig =
-                rpCtx.getProfileConfig().getSecurityConfiguration(profileRequestContext);
 
-        if (securityConfig == null) {
-            log.warn("Could not find security configuration, nothing to do");
-            return result;
-        }
+        final ProfileConfiguration profileConfig = rpCtx.getProfileConfig();
+        assert profileConfig != null;
 
-        if (!(securityConfig instanceof JSONSecurityConfiguration)) {
-            log.warn("Security configuration class was not expected: {}", securityConfig);
-            return result;
-        }
-        final JSONSecurityConfiguration jsonSecurityConfig = (JSONSecurityConfiguration) securityConfig;
+        final SecurityConfiguration securityConfig = profileConfig.getSecurityConfiguration(profileRequestContext);
 
-        if (jsonSecurityConfig.getJwtSignatureSigningConfiguration() == null) {
-            log.warn("Could not find signing configuration, nothing to do");
-            return result;
-        }
+        if (securityConfig instanceof JSONSecurityConfiguration jsonSecurityConfig) {
+            final SignatureSigningConfiguration jwtSignatureSigningConfiguration =
+                    jsonSecurityConfig.getJwtSignatureSigningConfiguration();
+            if (jwtSignatureSigningConfiguration == null) {
+                log.warn("Could not find signing configuration, nothing to do");
+                return result;
+            }
 
-        // currently only signing keys are included
-        final List<Credential> credentials =
-                jsonSecurityConfig.getJwtSignatureSigningConfiguration().getSigningCredentials();
-        final JSONArray jwkCredentials = new JSONArray();
-        for (final Credential credential : credentials) {
-            try {
-                jwkCredentials.add(parseJwkCredential(credential).toJSONObject());
-            } catch (final ConstraintViolationException e) {
-                log.warn("Ignoring key from the resulting list", e);
+            // currently only signing keys are included
+            final List<Credential> credentials = jwtSignatureSigningConfiguration.getSigningCredentials();
+            final JSONArray jwkCredentials = new JSONArray();
+            for (final Credential credential : credentials) {
+                assert credential != null;
+                try {
+                    jwkCredentials.add(parseJwkCredential(credential).toJSONObject());
+                } catch (final ConstraintViolationException e) {
+                    log.warn("Ignoring key from the resulting list", e);
+                }
             }
+            result.add(jwkCredentials);
+            return result;
+        }
+        if (securityConfig == null) {
+            log.warn("Could not find security configuration, nothing to do");
+        } else {
+            log.warn("Security configuration class was not expected: {}", securityConfig);
         }
-        result.add(jwkCredentials);
         return result;
     }
 
     /** {@inheritDoc} */
     @Override
-    public Object resolveSingle(@Nonnull final ProfileRequestContext profileRequestContext) throws ResolverException {
+    public Object resolveSingle(@Nullable final ProfileRequestContext profileRequestContext) throws ResolverException {
         final Iterator<Object> iterator = resolve(profileRequestContext).iterator();
         if (iterator.hasNext()) {
             return iterator.next();
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/DynamicFilesystemProviderMetadataResolver.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/DynamicFilesystemProviderMetadataResolver.java
index e24c5451..938c7d49 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/DynamicFilesystemProviderMetadataResolver.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/DynamicFilesystemProviderMetadataResolver.java
@@ -28,7 +28,6 @@ import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.core.io.Resource;
 
 import com.nimbusds.oauth2.sdk.ParseException;
@@ -38,6 +37,7 @@ import net.minidev.json.JSONObject;
 import net.shibboleth.idp.plugin.oidc.op.metadata.resolver.MetadataValueResolver;
 import net.shibboleth.idp.plugin.oidc.op.metadata.resolver.RefreshableMetadataValueResolver;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.resolver.ResolverException;
 
 /**
@@ -47,7 +47,7 @@ import net.shibboleth.shared.resolver.ResolverException;
 public class DynamicFilesystemProviderMetadataResolver extends FilesystemProviderMetadataResolver {
 
     /** Class logger. */
-    private final Logger log = LoggerFactory.getLogger(DynamicFilesystemProviderMetadataResolver.class);
+    @Nonnull private final Logger log = LoggerFactory.getLogger(DynamicFilesystemProviderMetadataResolver.class);
 
     /** The map of dynamic metadata value resolvers, key corresponding to the name of the metadata field. */
     private Map<String, ? extends MetadataValueResolver> dynamicResolvers = new HashMap<>();
@@ -128,12 +128,13 @@ public class DynamicFilesystemProviderMetadataResolver extends FilesystemProvide
         final Instant updateTime = super.getMetadataUpdateTime();
         for (final String id : dynamicResolvers.keySet()) {
             final MetadataValueResolver resolver = dynamicResolvers.get(id);
-            if (resolver instanceof RefreshableMetadataValueResolver) {
-                if (((RefreshableMetadataValueResolver) resolver).getLastUpdate() == null) {
+            if (resolver instanceof RefreshableMetadataValueResolver refreshableResolver) {
+                if (refreshableResolver.getLastUpdate() == null) {
                     return Instant.now();
                 }
-                if (((RefreshableMetadataValueResolver) resolver).getLastUpdate().isAfter(updateTime)) {
-                    return ((RefreshableMetadataValueResolver) resolver).getLastUpdate();
+                final Instant lastUpdate = refreshableResolver.getLastUpdate();
+                if (lastUpdate != null && lastUpdate.isAfter(updateTime)) {
+                    return refreshableResolver.getLastUpdate();
                 }
             }
         }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FilesystemMetadataValueResolver.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FilesystemMetadataValueResolver.java
index 867d0d77..8fcdfc91 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FilesystemMetadataValueResolver.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FilesystemMetadataValueResolver.java
@@ -30,6 +30,7 @@ import com.nimbusds.oauth2.sdk.id.Identifier;
 import net.minidev.json.JSONValue;
 import net.shibboleth.idp.plugin.oidc.op.metadata.resolver.RefreshableMetadataValueResolver;
 import net.shibboleth.oidc.metadata.impl.AbstractFileOIDCEntityResolver;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.resolver.ResolverException;
 
 /**
@@ -72,7 +73,7 @@ public class FilesystemMetadataValueResolver extends AbstractFileOIDCEntityResol
      * @throws ResolverException thrown if there is an error during resolution.
      */
     @Override
-    @Nullable public Iterable<Object> resolve(@Nullable final ProfileRequestContext profileRequestContext)
+    @Nonnull public Iterable<Object> resolve(@Nullable final ProfileRequestContext profileRequestContext)
             throws ResolverException {
         ifNotInitializedThrowUninitializedComponentException();
         ifDestroyedThrowDestroyedComponentException();
@@ -96,9 +97,13 @@ public class FilesystemMetadataValueResolver extends AbstractFileOIDCEntityResol
     }
 
     /** {@inheritDoc} */
-    @Override
+    @Override @Nonnull
     protected List<Object> parse(final byte[] bytes) throws ParseException {
-        return List.of(JSONValue.parse(bytes));
+        final Object json = JSONValue.parse(bytes);
+        if (json == null) {
+            throw new ParseException("Could not parse JSON object from the bytes");
+        }
+        return CollectionSupport.listOf(json);
     }
 
     /** {@inheritDoc} */
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FilesystemProviderMetadataResolver.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FilesystemProviderMetadataResolver.java
index 54e437ae..414c1c1b 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FilesystemProviderMetadataResolver.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FilesystemProviderMetadataResolver.java
@@ -27,7 +27,6 @@ import javax.annotation.Nullable;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.core.io.Resource;
 
 import com.nimbusds.oauth2.sdk.ParseException;
@@ -39,7 +38,10 @@ import net.shibboleth.idp.plugin.oidc.op.metadata.resolver.RefreshableProviderMe
 import net.shibboleth.oidc.metadata.impl.AbstractFileOIDCEntityResolver;
 import net.shibboleth.profile.config.OverriddenIssuerProfileConfiguration;
 import net.shibboleth.profile.context.RelyingPartyContext;
+import net.shibboleth.profile.relyingparty.RelyingPartyConfiguration;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.resolver.ResolverException;
 
 /**
@@ -99,7 +101,7 @@ public class FilesystemProviderMetadataResolver extends AbstractFileOIDCEntityRe
 
     /** {@inheritDoc} */
     @Override
-    @Nullable public Iterable<OIDCProviderMetadata> resolve(@Nullable final ProfileRequestContext profileRequestContext)
+    @Nonnull public Iterable<OIDCProviderMetadata> resolve(@Nullable final ProfileRequestContext profileRequestContext)
             throws ResolverException {
         ifNotInitializedThrowUninitializedComponentException();
         ifDestroyedThrowDestroyedComponentException();
@@ -112,20 +114,24 @@ public class FilesystemProviderMetadataResolver extends AbstractFileOIDCEntityRe
         }
         
         String responderId = null;
-        if (rpCtx.getProfileConfig() instanceof OverriddenIssuerProfileConfiguration) {
-            responderId =
-                    ((OverriddenIssuerProfileConfiguration) rpCtx.getProfileConfig()).getIssuer(profileRequestContext);
+        if (rpCtx.getProfileConfig() instanceof OverriddenIssuerProfileConfiguration overriddenIssuerProfileConfig) {
+            responderId = overriddenIssuerProfileConfig.getIssuer(profileRequestContext);
         }
         
         if (responderId == null) {
-            responderId = rpCtx.getConfiguration().getIssuer(profileRequestContext);
+            final RelyingPartyConfiguration rpConfig = rpCtx.getConfiguration();
+            if (rpConfig != null) {
+                responderId = rpConfig.getIssuer(profileRequestContext);
+            }
         }
         
         final String issuer = responderId;
-        return entities
+        final List<OIDCProviderMetadata> result = entities
                 .stream()
                 .filter(e -> e.getIssuer().getValue().equals(issuer))
                 .collect(Collectors.toUnmodifiableList());
+        assert result != null;
+        return result;
     }
 
     /** {@inheritDoc} */
@@ -133,25 +139,27 @@ public class FilesystemProviderMetadataResolver extends AbstractFileOIDCEntityRe
     @Nullable public OIDCProviderMetadata resolveSingle(@Nullable final ProfileRequestContext profileRequestContext)
             throws ResolverException {
         final Iterable<OIDCProviderMetadata> iterable = resolve(profileRequestContext);
-        if (iterable != null) {
-            final Iterator<OIDCProviderMetadata> iterator = iterable.iterator();
-            if (iterator != null && iterator.hasNext()) {
-                return iterator.next();
-            }
+        final Iterator<OIDCProviderMetadata> iterator = iterable.iterator();
+        if (iterator != null && iterator.hasNext()) {
+            return iterator.next();
         }
         log.warn("Could not find any clients with the given criteria");
         return null;
     }
 
     /** {@inheritDoc} */
-    @Override
+    @Override @Nonnull
     protected List<OIDCProviderMetadata> parse(final byte[] bytes) throws ParseException {
-        return List.of(OIDCProviderMetadata.parse(JSONObjectUtils.parse(new String(bytes))));
+        final OIDCProviderMetadata metadata = OIDCProviderMetadata.parse(JSONObjectUtils.parse(new String(bytes)));
+        assert metadata != null;
+        return CollectionSupport.listOf(metadata);
     }
 
     /** {@inheritDoc} */
-    @Override
+    @Override @Nonnull
     protected Issuer getKey(@Nonnull final OIDCProviderMetadata value) {
-        return value.getIssuer();
+        final Issuer issuer = value.getIssuer();
+        assert issuer != null;
+        return issuer;
     }
 }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FunctionMetadataValueResolver.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FunctionMetadataValueResolver.java
index 31c5f44e..5422dc91 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FunctionMetadataValueResolver.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/metadata/impl/FunctionMetadataValueResolver.java
@@ -14,15 +14,16 @@
 
 package net.shibboleth.idp.plugin.oidc.op.metadata.impl;
 
-import java.util.List;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 
 import net.shibboleth.idp.plugin.oidc.op.metadata.resolver.MetadataValueResolver;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
@@ -66,14 +67,15 @@ public class FunctionMetadataValueResolver extends AbstractIdentifiableInitializ
     }
 
     /** {@inheritDoc} */
-    @Override
-    public Iterable<Object> resolve(@Nonnull final ProfileRequestContext criteria) throws ResolverException {
-        return List.of(resolveSingle(criteria));
+    @Override @Nonnull
+    public Iterable<Object> resolve(@Nullable final ProfileRequestContext criteria) throws ResolverException {
+        final Object result = resolveSingle(criteria);
+        return result == null ? CollectionSupport.emptyList() : CollectionSupport.listOf(result);
     }
 
     /** {@inheritDoc} */
-    @Override
-    public Object resolveSingle(@Nonnull final ProfileRequestContext criteria) throws ResolverException {
+    @Override @Nullable
+    public Object resolveSingle(@Nullable final ProfileRequestContext criteria) throws ResolverException {
         return resolverFunction.apply(criteria);
     }
     
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/BaseOAuth2RequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/BaseOAuth2RequestDecoder.java
index ad558511..9cf747da 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/BaseOAuth2RequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/BaseOAuth2RequestDecoder.java
@@ -27,12 +27,13 @@ import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.decoder.MessageDecodingException;
 import org.opensaml.messaging.decoder.servlet.AbstractHttpServletRequestMessageDecoder;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.Request;
 import com.nimbusds.oauth2.sdk.http.HTTPRequest;
 
+import jakarta.servlet.http.HttpServletRequest;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestAudienceLookupFunction;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Base decoder for Nimbus OAuth2 request messages. 
@@ -108,7 +109,8 @@ public abstract class BaseOAuth2RequestDecoder<T extends Request> extends Abstra
      */
     @Nullable protected String getEndpointURI(final T message) {
         if (removeIpAddressFromEndpointUri) {
-            return getHttpServletRequest().getRequestURI();
+            final HttpServletRequest httpServletRequest = getHttpServletRequest();
+            return httpServletRequest != null ? httpServletRequest.getRequestURI() : null;
         } else {
             final URI endpointUri = message.getEndpointURI();
             return endpointUri != null ? endpointUri.toString() : null;
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2AuthorizationRequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2AuthorizationRequestDecoder.java
index 31a0c28b..d85ccd1c 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2AuthorizationRequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2AuthorizationRequestDecoder.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.AuthorizationRequest;
@@ -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.decoding.impl.RequestUtil;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Message decoder decoding OAuth2 {@link AuthorizationRequest}s.
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2IntrospectionRequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2IntrospectionRequestDecoder.java
index 5f9a6625..0288aeb5 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2IntrospectionRequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2IntrospectionRequestDecoder.java
@@ -20,14 +20,15 @@ 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.TokenIntrospectionRequest;
 import com.nimbusds.oauth2.sdk.http.HTTPRequest;
 import com.nimbusds.oauth2.sdk.http.JakartaServletUtils;
 
+import jakarta.servlet.http.HttpServletRequest;
 import net.shibboleth.idp.plugin.oidc.op.decoding.impl.RequestUtil;
+import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.primitive.StringSupport;
 
 /**
@@ -43,14 +44,16 @@ public class OAuth2IntrospectionRequestDecoder extends BaseOAuth2RequestDecoder<
     @Override
     protected TokenIntrospectionRequest parseMessage() throws MessageDecodingException {
         try {
-            final String query = StringSupport.trimOrNull(getHttpServletRequest().getQueryString());
+            final HttpServletRequest httpServletRequest = getHttpServletRequest();
+            final String query = httpServletRequest != null ?
+                    StringSupport.trimOrNull(httpServletRequest.getQueryString()) : null;
             // the spec mandates token to be sent in application/x-www-form-urlencoded data
             // Nimbus allows the use of query parameters too, so we deny it by ourselves
             if (query != null && query.contains("token=")) {
                 log.error("The query parameters contain 'token'");
                 throw new MessageDecodingException("The query parameters contain 'token'");
             }
-            final HTTPRequest httpReq = JakartaServletUtils.createHTTPRequest(getHttpServletRequest());
+            final HTTPRequest httpReq = JakartaServletUtils.createHTTPRequest(httpServletRequest);
             getProtocolMessageLogger().trace("Inbound request {}", RequestUtil.toString(httpReq));
             return TokenIntrospectionRequest.parse(httpReq);
         } catch (final com.nimbusds.oauth2.sdk.ParseException | IOException e) {
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2RevocationRequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2RevocationRequestDecoder.java
index d3d4031b..9f48e497 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2RevocationRequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/decoding/impl/OAuth2RevocationRequestDecoder.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.TokenRevocationRequest;
@@ -28,6 +27,7 @@ import com.nimbusds.oauth2.sdk.http.HTTPRequest;
 import com.nimbusds.oauth2.sdk.http.JakartaServletUtils;
 
 import net.shibboleth.idp.plugin.oidc.op.decoding.impl.RequestUtil;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Message decoder decoding OpenID Connect {@link TokenRevocationRequest}s.
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/messaging/impl/PopulateOIDCMetadataContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/messaging/impl/PopulateOIDCMetadataContext.java
index 251442f9..9accf50d 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/messaging/impl/PopulateOIDCMetadataContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/messaging/impl/PopulateOIDCMetadataContext.java
@@ -24,15 +24,16 @@ import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.messaging.handler.AbstractMessageHandler;
 import org.opensaml.saml.common.messaging.context.SAMLMetadataContext;
 import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 
 import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * A message handler that attempts to locate OIDC client information from the SAML entity descriptor containing role
@@ -52,8 +53,11 @@ public class PopulateOIDCMetadataContext extends AbstractMessageHandler {
      * Constructor.
      */
     public PopulateOIDCMetadataContext() {
-        samlMetadataContextLookupStrategy = new ChildContextLookup<>(SAMLMetadataContext.class).compose(
-                new ChildContextLookup<>(SAMLPeerEntityContext.class));
+        final Function<MessageContext,SAMLMetadataContext> smcls =
+                new ChildContextLookup<>(SAMLMetadataContext.class).compose(
+                        new ChildContextLookup<>(SAMLPeerEntityContext.class));
+        assert smcls != null;
+        samlMetadataContextLookupStrategy = smcls;
     }
     
     /**
@@ -79,13 +83,18 @@ public class PopulateOIDCMetadataContext extends AbstractMessageHandler {
             return;
         }
 
-        final List<RoleDescriptor> roleDescriptors 
-            = samlMetadataCtx.getEntityDescriptor().getRoleDescriptors(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+        final EntityDescriptor entityDescriptor = samlMetadataCtx.getEntityDescriptor();
+        if (entityDescriptor == null) {
+            log.error("Unable to locate EntityDescriptor");
+            return;
+        }
+        final List<RoleDescriptor> roleDescriptors =
+                entityDescriptor.getRoleDescriptors(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
         for (final RoleDescriptor roleDescriptor : roleDescriptors) {
             if (roleDescriptor instanceof SPSSODescriptor) {
                 final List<OIDCClientInformation> clientInformations 
                     = roleDescriptor.getObjectMetadata().get(OIDCClientInformation.class);
-                if (clientInformations != null && clientInformations.size() > 0) {
+                if (clientInformations.size() > 0) {
                     final OIDCMetadataContext oidcCtx = new OIDCMetadataContext();
                     oidcCtx.setClientInformation(clientInformations.get(0));
                     messageContext.addSubcontext(oidcCtx);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/messaging/impl/SetEntityIdToSAMLPeerEntityContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/messaging/impl/SetEntityIdToSAMLPeerEntityContext.java
index aae8456b..037d4e95 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/messaging/impl/SetEntityIdToSAMLPeerEntityContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/messaging/impl/SetEntityIdToSAMLPeerEntityContext.java
@@ -25,12 +25,12 @@ import org.opensaml.messaging.handler.MessageHandlerException;
 import org.opensaml.saml.common.messaging.context.AbstractSAMLEntityContext;
 import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.id.ClientID;
 
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultClientIDLookupFunction;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * {@link MessageHandler} that sets the entityID to the given {@link SAMLPeerEntityContext} class.
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractOAuthAuthorizationRequestAction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractOAuthAuthorizationRequestAction.java
index 8e1d5223..2791dbfb 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractOAuthAuthorizationRequestAction.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractOAuthAuthorizationRequestAction.java
@@ -14,11 +14,8 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl;
 
-import javax.annotation.Nonnull;
 import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.profile.context.ProfileRequestContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.AuthorizationRequest;
 
@@ -30,10 +27,6 @@ import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractOIDCRequestAction;
  */
 public abstract class AbstractOAuthAuthorizationRequestAction extends AbstractOIDCRequestAction<AuthorizationRequest> {
 
-    /** Class logger. */
-    @Nonnull
-    private Logger log = LoggerFactory.getLogger(AbstractOAuthAuthorizationRequestAction.class);
-
     /**
      * Returns OAuth authorization request.
      * 
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractOAuthAuthorizationResponseAction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractOAuthAuthorizationResponseAction.java
index 1ca637e0..511257d0 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractOAuthAuthorizationResponseAction.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractOAuthAuthorizationResponseAction.java
@@ -15,18 +15,19 @@
 package net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.AuthorizationRequest;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
 import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * 
@@ -41,11 +42,11 @@ public abstract class AbstractOAuthAuthorizationResponseAction extends AbstractO
     private Logger log = LoggerFactory.getLogger(AbstractOAuthAuthorizationResponseAction.class);
 
     /** oidc response context. */
-    @Nonnull
+    @Nullable
     private OIDCAuthenticationResponseContext oidcResponseContext;
 
     /** OIDC Metadata context. */
-    @Nonnull
+    @Nullable
     private OIDCMetadataContext oidcMetadataContext;
 
     /**
@@ -53,7 +54,7 @@ public abstract class AbstractOAuthAuthorizationResponseAction extends AbstractO
      * 
      * @return ctx.
      */
-    @Nonnull
+    @Nullable
     public OIDCAuthenticationResponseContext getOidcResponseContext() {
         return oidcResponseContext;
     }
@@ -63,7 +64,7 @@ public abstract class AbstractOAuthAuthorizationResponseAction extends AbstractO
      * 
      * @return The OIDC Metadata context.
      */
-    public OIDCMetadataContext getMetadataContext() {
+    @Nullable public OIDCMetadataContext getMetadataContext() {
         return oidcMetadataContext;
     }
 
@@ -88,7 +89,8 @@ public abstract class AbstractOAuthAuthorizationResponseAction extends AbstractO
             return false;
         }
         
-        oidcMetadataContext = profileRequestContext.getInboundMessageContext().getSubcontext(OIDCMetadataContext.class);
+        oidcMetadataContext =
+                profileRequestContext.ensureInboundMessageContext().getSubcontext(OIDCMetadataContext.class);
         
         return true;
     }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractProcessTokenAction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractProcessTokenAction.java
index e56f8692..48ffba49 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractProcessTokenAction.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/AbstractProcessTokenAction.java
@@ -32,7 +32,6 @@ import org.opensaml.security.credential.CredentialResolver;
 import org.opensaml.security.credential.UsageType;
 import org.opensaml.security.criteria.UsageCriterion;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jose.JOSEObjectType;
 import com.nimbusds.jwt.JWTClaimsSet;
@@ -52,9 +51,12 @@ import net.shibboleth.oidc.jwt.claims.JWTValidationException;
 import net.shibboleth.oidc.profile.config.navigate.IssuedClaimsValidatorLookupFunction;
 import net.shibboleth.oidc.profile.core.OidcEventIds;
 import net.shibboleth.oidc.security.impl.JWTSignatureValidationUtil;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.collection.CollectionSupport;
+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;
 import net.shibboleth.shared.security.DataSealer;
@@ -90,7 +92,7 @@ public abstract class AbstractProcessTokenAction<T> extends AbstractOIDCRequestA
     @Nullable private ClaimsValidator claimsValidator;
     
     /** Source of signing keys. */
-    @Nullable private CredentialResolver credentialResolver;
+    @NonnullAfterInit private CredentialResolver credentialResolver;
 
     /** List of deserializer bi-functions for refresh tokens to be used in addition to unsealing opaque value. */
     @Nonnull private List<BiFunction<ProfileRequestContext,String,RefreshTokenClaimsSet>> refreshTokenDeserializers;
@@ -147,6 +149,16 @@ public abstract class AbstractProcessTokenAction<T> extends AbstractOIDCRequestA
                 Constraint.isNotNull(deserializers, "List of refresh token deserializers cannot be null");
     }
 
+    /** {@inheritDoc} */
+    @Override
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        
+        if (credentialResolver == null) {
+            throw new ComponentInitializationException("Credential resolver cannot be null");
+        }
+    }
+    
     /** {@inheritDoc} */
     @Override
     protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
@@ -196,6 +208,7 @@ public abstract class AbstractProcessTokenAction<T> extends AbstractOIDCRequestA
         }
 
         log.debug("{} Validating parsed/decoded claims set: {}", getLogPrefix(), tokenClaimsSet.toString());
+        assert claimsValidator != null;
         try {
             claimsValidator.validate(tokenClaimsSet, profileRequestContext);
         } catch (final JWTValidationException e) {
@@ -204,7 +217,7 @@ public abstract class AbstractProcessTokenAction<T> extends AbstractOIDCRequestA
         }
         
         // Populate outbound tree.
-        profileRequestContext.getOutboundMessageContext().getSubcontext(
+        profileRequestContext.ensureOutboundMessageContext().ensureSubcontext(
                 OAuth2TokenMgmtResponseContext.class).setTokenClaimsSet(tokenClaimsSet);
     }
 // Checkstyle: CyclomaticComplexity ON
@@ -230,6 +243,7 @@ public abstract class AbstractProcessTokenAction<T> extends AbstractOIDCRequestA
                         return null;
                     }
 
+                    assert signedJWT != null;
                     final JWTClaimsSet jwtClaimsSet = signedJWT.getJWTClaimsSet();
                     log.debug("{} Checking JWT signature", getLogPrefix());
                     final Collection<Credential> credList = new ArrayList<>();
@@ -242,6 +256,7 @@ public abstract class AbstractProcessTokenAction<T> extends AbstractOIDCRequestA
                         return null;
                     }
 
+                    assert signedJWT != null;
                     final String errorEventId = JWTSignatureValidationUtil.validateSignatureEx(credList, signedJWT,
                             OidcEventIds.INVALID_GRANT);
                     if (errorEventId != null) {
@@ -260,7 +275,10 @@ public abstract class AbstractProcessTokenAction<T> extends AbstractOIDCRequestA
 
         // Fall back to opaque.
         try {
-            return AccessTokenClaimsSet.parse(token.getValue(), dataSealer).getClaimsSet();
+            final String tokenValue = token.getValue();
+            assert tokenValue != null;
+            assert dataSealer != null;
+            return AccessTokenClaimsSet.parse(tokenValue, dataSealer).getClaimsSet();
         } catch (final DataSealerException | ParseException e) {
             
         }
@@ -279,6 +297,7 @@ public abstract class AbstractProcessTokenAction<T> extends AbstractOIDCRequestA
             @Nonnull @NotEmpty final Token token) {
         final String refreshToken = token.getValue();
         try {
+            assert refreshToken != null;
             assert dataSealer != null;
             return RefreshTokenClaimsSet.parse(refreshToken, dataSealer).getClaimsSet();
         } catch (ParseException | DataSealerException e) {
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildAccessToken.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildAccessToken.java
index bb304a64..abfec090 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildAccessToken.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildAccessToken.java
@@ -31,7 +31,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.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.PlainJWT;
@@ -41,6 +40,7 @@ import com.nimbusds.openid.connect.sdk.AuthenticationRequest;
 import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
 
 import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
 import net.shibboleth.idp.authn.context.SubjectContext;
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.AccessTokenContext;
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseConsentContext;
@@ -64,6 +64,7 @@ import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 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.DataSealer;
 import net.shibboleth.shared.security.DataSealerException;
@@ -170,20 +171,29 @@ public class BuildAccessToken extends AbstractOIDCResponseAction {
                 new InboundMessageContextLookup());
         
         idGeneratorLookupStrategy = FunctionSupport.constant(new SecureRandomIdentifierGenerationStrategy());
-        
-        tokenClaimsContextLookupStrategy =
+
+        final Function<ProfileRequestContext,OIDCAuthenticationResponseTokenClaimsContext> tccls =
                 new ChildContextLookup<>(OIDCAuthenticationResponseTokenClaimsContext.class).compose(
                         new OIDCAuthenticationResponseContextLookupFunction());
-        consentContextLookupStrategy =
+        assert tccls != null;
+        tokenClaimsContextLookupStrategy = tccls;
+
+        final Function<ProfileRequestContext, OIDCAuthenticationResponseConsentContext> ccls =
                 new ChildContextLookup<>(OIDCAuthenticationResponseConsentContext.class).compose(
                         new OIDCAuthenticationResponseContextLookupFunction());
+        assert ccls != null;
+        consentContextLookupStrategy = ccls;
 
         consentEnabledPredicate = new AttributeConsentFlowEnabledPredicate();
         
         // PRC -> inbound message context -> OIDC response context -> ATC
-        accessTokenContextCreationStrategy = new ChildContextLookup<>(AccessTokenContext.class, true).compose(
-                new ChildContextLookup<>(OIDCAuthenticationResponseContext.class).compose(
-                        new OutboundMessageContextLookup()));
+        final Function<ProfileRequestContext,AccessTokenContext> atccs =
+                new ChildContextLookup<>(AccessTokenContext.class, true).compose(
+                        new ChildContextLookup<>(OIDCAuthenticationResponseContext.class).compose(
+                                new OutboundMessageContextLookup()));
+        assert atccs != null;
+        accessTokenContextCreationStrategy = atccs; 
+
         tokenClaimsSetManipulationStrategyLookupStrategy =
                 new AccessTokenClaimsSetManipulationStrategyLookupFunction();
         xmlSafeIdentifier = true;
@@ -366,7 +376,7 @@ public class BuildAccessToken extends AbstractOIDCResponseAction {
         if (tokenClaimsSet != null && !(tokenClaimsSet instanceof RefreshTokenClaimsSet)
                 && !(tokenClaimsSet instanceof AuthorizeCodeClaimsSet)) {
             log.error("{} Authorization grant is of unknown type: {}", getLogPrefix(),
-                    tokenClaimsSet.getClass().getName());
+                    tokenClaimsSet != null ? tokenClaimsSet.getClass().getName() : null);
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
             return false;
         }
@@ -393,9 +403,9 @@ public class BuildAccessToken extends AbstractOIDCResponseAction {
             }
             
             if (profileRequestContext.getInboundMessageContext() != null
-                    && profileRequestContext.getInboundMessageContext().getMessage() instanceof AuthenticationRequest) {
-                authenticationRequest =
-                        (AuthenticationRequest) profileRequestContext.getInboundMessageContext().getMessage();
+                    && profileRequestContext.ensureInboundMessageContext().getMessage() 
+                        instanceof AuthenticationRequest authnRequest) {
+                authenticationRequest = authnRequest;
             }
         }
         
@@ -412,6 +422,7 @@ public class BuildAccessToken extends AbstractOIDCResponseAction {
             ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_PROFILE_CONFIG);
             return false;
         }
+        assert accessTokenCtx != null;
         accessTokenCtx.setLifetime(lifetime);
 
         manipulationStrategy = tokenClaimsSetManipulationStrategyLookupStrategy.apply(profileRequestContext);
@@ -444,7 +455,8 @@ public class BuildAccessToken extends AbstractOIDCResponseAction {
 
         final Scope scope = responseCtx.getScope() != null ? responseCtx.getScope() : new Scope();
         log.debug("{} Building access token with scope: {}", getLogPrefix(), scope);
-        
+
+        assert scope != null;
         final boolean oidc = scope.contains("openid");
         
         if (oidc) {
@@ -453,42 +465,42 @@ public class BuildAccessToken extends AbstractOIDCResponseAction {
         log.debug("{} Building access token with audience: {}", getLogPrefix(), responseCtx.getAudience());
 
         final Instant now = Instant.now();
+        assert accessTokenCtx != null;
         final Instant dateExp = now.plus(accessTokenCtx.getLifetime());
+        assert dateExp != null;
         
         final AccessTokenClaimsSet.Builder builder;
-        
+
         if (tokenClaimsSet != null) {
+            final TokenClaimsSet nonNullClaimsSet = tokenClaimsSet;
             // We may not use original claims as input for scope / delivery claims as they may have been reduced.
             builder = new AccessTokenClaimsSet.Builder(
-                    tokenClaimsSet,
+                    nonNullClaimsSet,
                     scope,
                     oidc ? claims : null,
                     oidc ? claimsUI : null,
-                    Instant.now(),
+                    now,
                     dateExp);
             // Add additional bits.
             builder.setAudience(responseCtx.getAudience());
+            assert idGenerator != null;
             builder.setJWTID(idGenerator, xmlSafeIdentifier);
             builder.setSessionIdentifier(responseCtx.getSessionId());
             // Set root token identifier to contain jit from the claims set used for building the new token
-            if (StringSupport.trimOrNull(tokenClaimsSet.getRootTokenIdentifier()) == null) {
-                builder.setRootTokenIdentifier(tokenClaimsSet.getID());
+            if (StringSupport.trimOrNull(nonNullClaimsSet.getRootTokenIdentifier()) == null) {
+                builder.setRootTokenIdentifier(nonNullClaimsSet.getID());
             }
         } else {
             final OIDCAuthenticationResponseConsentContext consentCtx =
                     consentContextLookupStrategy.apply(profileRequestContext);
             final JSONArray consented = consentCtx != null ? consentCtx.getConsentedAttributes() : null;
-            
+
             builder = (Builder) new AccessTokenClaimsSet.Builder()
-                    .setJWTID(idGenerator, xmlSafeIdentifier)
                     .setClientID(clientID)
                     .setIssuer(issuer)
-                    .setPrincipal(subjectCtx.getPrincipalName())
-                    .setSubject(responseCtx.getSubject())
                     .setIssuedAt(now)
                     .setExpiresAt(dateExp)
                     .setACR(responseCtx.getAcr())
-                    .setAuthenticationTime(responseCtx.getAuthTime())
                     .setScope(scope)
                     .setAudience(responseCtx.getAudience())
                     .setDlClaims(claims)
@@ -497,31 +509,61 @@ public class BuildAccessToken extends AbstractOIDCResponseAction {
                     .setConsentEnabled(consentEnabledPredicate.test(profileRequestContext))
                     .setSessionIdentifier(responseCtx.getSessionId());
 
+            assert subjectCtx != null;
+            final String principal = subjectCtx.getPrincipalName();
+            if (principal != null) {
+                builder.setPrincipal(principal);
+            }
+
+            assert responseCtx != null;
+            final String subject = responseCtx.getSubject();
+            if (subject != null) {
+                builder.setSubject(subject);
+            }
+
+            assert responseCtx != null;
+            final Instant authTime = responseCtx.getAuthTime();
+            if (authTime != null) {
+                builder.setAuthenticationTime(authTime);
+            }
+
+            assert idGenerator != null;
+            builder.setJWTID(idGenerator, xmlSafeIdentifier);
+
             if (authenticationRequest != null) {
-                builder
-                    .setNonce(authenticationRequest.getNonce())
-                    .setClaimsRequest(authenticationRequest.getOIDCClaims());
+                final AuthenticationRequest nonNullAuthnRequest = authenticationRequest;
+                builder.setNonce(nonNullAuthnRequest.getNonce());
+                builder.setClaimsRequest(nonNullAuthnRequest.getOIDCClaims());
             }
         }
-        
-        if (jwtTokenType && responseCtx.getAccessTokenClaimSet() != null) {
-            builder.setCustomClaims(responseCtx.getAccessTokenClaimSet().toJSONObject());
+
+        final ClaimsSet responseCtxClaimsSet = responseCtx.getAccessTokenClaimSet();
+        if (jwtTokenType && responseCtxClaimsSet != null) {
+            final JSONObject json = responseCtxClaimsSet.toJSONObject();
+            if (json != null) {
+                builder.setCustomClaims(json);
+            }
         }
         
         final AccessTokenClaimsSet claimsSet = builder.build();
 
         if (manipulationStrategy != null) {
+            final JWTClaimsSet acClaimsSet = claimsSet.getClaimsSet();
+            assert acClaimsSet != null;
             log.debug("{} Manipulation strategy has been set, applying it to the claims set {}", getLogPrefix(),
                     claimsSet.serialize());
+            assert manipulationStrategy != null;
             final Map<String, Object> result = manipulationStrategy.apply(profileRequestContext,
-                    claimsSet.getClaimsSet().toJSONObject());
+                    acClaimsSet.toJSONObject());
             if (result == null) {
                 log.debug("{} Manipulation strategy returned null, leaving token claims set untouched.",
                         getLogPrefix());
             } else {
                 log.debug("{} Applying the manipulated claims into the token claims set", getLogPrefix());
                 try {
-                    claimsSet.setClaimsSet(JWTClaimsSet.parse(result));
+                    final JWTClaimsSet parsedSet = JWTClaimsSet.parse(result);
+                    assert parsedSet != null;
+                    claimsSet.setClaimsSet(parsedSet);
                 } catch (final ParseException e) {
                     log.error("{} The resulted claims set could not be transformed into ", getLogPrefix(), e);
                     ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_PROFILE_CONFIG);
@@ -534,10 +576,16 @@ public class BuildAccessToken extends AbstractOIDCResponseAction {
 
         try {
             if (jwtTokenType) {
-                accessTokenCtx.setJWT(new PlainJWT(sealClaims(claimsSet.getClaimsSet())));
+                final JWTClaimsSet acClaimsSet = claimsSet.getClaimsSet();
+                assert acClaimsSet != null;
+                assert accessTokenCtx != null;
+                accessTokenCtx.setJWT(new PlainJWT(sealClaims(acClaimsSet)));
                 log.debug("{} Claims stored to JWT access token: {}", getLogPrefix(), claimsSet.serialize());
             } else { 
-                accessTokenCtx.setOpaque(claimsSet.serialize(dataSealer));
+                assert dataSealer != null;
+                final String sealedToken = claimsSet.serialize(dataSealer);
+                assert accessTokenCtx != null;
+                accessTokenCtx.setOpaque(sealedToken);
                 log.debug("{} Claims converted to opaque access token: {}", getLogPrefix(), claimsSet.serialize());
             }
         } catch (final DataSealerException | ParseException e) {
@@ -605,11 +653,17 @@ public class BuildAccessToken extends AbstractOIDCResponseAction {
         }
         
         // Wrap the sealed claims and re-embed back in original claims set.
-        final String sealed = dataSealer.wrap(JWTClaimsSet.parse(toSeal).toString());
+        final JWTClaimsSet claimsSetToSeal = JWTClaimsSet.parse(toSeal);
+        assert claimsSetToSeal != null;
+        final String stringToSeal = claimsSetToSeal.toString();
+        assert stringToSeal != null;
+        final String sealed = dataSealer.wrap(stringToSeal);
         map.put(TokenClaimsSet.KEY_SEALED_FOR_OP, sealed);
         
         // Re-parse the claims.
-        return JWTClaimsSet.parse(map);
+        final JWTClaimsSet result = JWTClaimsSet.parse(map);
+        assert result != null;
+        return result;
     }
     
 }
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildRevokeTokenErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildRevokeTokenErrorResponseFromEvent.java
index 09e3cf14..7f747795 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildRevokeTokenErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildRevokeTokenErrorResponseFromEvent.java
@@ -14,6 +14,8 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl;
 
+import javax.annotation.Nonnull;
+
 import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
 
@@ -30,7 +32,7 @@ public class BuildRevokeTokenErrorResponseFromEvent
         extends AbstractBuildErrorResponseFromEvent<OAuth2RevocationErrorResponse> {
 
     @Override
-    protected OAuth2RevocationErrorResponse buildErrorResponse(final ErrorObject error,
+    protected OAuth2RevocationErrorResponse buildErrorResponse(@Nonnull final ErrorObject error,
             final ProfileRequestContext profileRequestContext) {
         return new OAuth2RevocationErrorResponse(error);
     }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/FormOutboundIntrospectionResponseMessage.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/FormOutboundIntrospectionResponseMessage.java
index 45ffba40..9aff26de 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/FormOutboundIntrospectionResponseMessage.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/FormOutboundIntrospectionResponseMessage.java
@@ -21,7 +21,6 @@ import javax.annotation.Nonnull;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.oauth2.sdk.Scope;
@@ -35,6 +34,7 @@ import com.nimbusds.oauth2.sdk.token.AccessTokenType;
 import net.shibboleth.idp.plugin.oidc.op.oauth2.messaging.context.OAuth2TokenMgmtResponseContext;
 import net.shibboleth.idp.plugin.oidc.op.token.support.TokenClaimsSet;
 import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Action that forms outbound token introspection success message. Formed message is set to
@@ -49,17 +49,18 @@ public class FormOutboundIntrospectionResponseMessage extends AbstractProfileAct
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
         
         final OAuth2TokenMgmtResponseContext ctx =
-                profileRequestContext.getOutboundMessageContext().getSubcontext(
+                profileRequestContext.ensureOutboundMessageContext().getSubcontext(
                         OAuth2TokenMgmtResponseContext.class);
         
         if (ctx == null || ctx.getTokenClaimsSet() == null) {
             log.debug("{} Introspection of token failed, token was not valid", getLogPrefix());
-            profileRequestContext.getOutboundMessageContext().setMessage(
+            profileRequestContext.ensureOutboundMessageContext().setMessage(
                     new TokenIntrospectionSuccessResponse.Builder(false).build());
             return;
         }
 
         final JWTClaimsSet tokenClaimsSet = ctx.getTokenClaimsSet();
+        assert tokenClaimsSet != null;
 
         try {
             String clientID = tokenClaimsSet.getStringClaim(TokenClaimsSet.KEY_CLIENTID);
@@ -94,11 +95,11 @@ public class FormOutboundIntrospectionResponseMessage extends AbstractProfileAct
 
             }
             
-            profileRequestContext.getOutboundMessageContext().setMessage(builder.build());
+            profileRequestContext.ensureOutboundMessageContext().setMessage(builder.build());
             
         } catch (final ParseException e) {
             log.error("{} Failure extracting claims for response", getLogPrefix(), e);
-            profileRequestContext.getOutboundMessageContext().setMessage(
+            profileRequestContext.ensureOutboundMessageContext().setMessage(
                     new TokenIntrospectionSuccessResponse.Builder(false).build());
         }
     }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/FormOutboundRevokeTokenResponseMessage.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/FormOutboundRevokeTokenResponseMessage.java
index f35f317d..152b2d6e 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/FormOutboundRevokeTokenResponseMessage.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/FormOutboundRevokeTokenResponseMessage.java
@@ -30,7 +30,7 @@ public class FormOutboundRevokeTokenResponseMessage extends AbstractProfileActio
     /** {@inheritDoc} */
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
-        profileRequestContext.getOutboundMessageContext().setMessage(new OAuth2RevocationSuccessResponse());
+        profileRequestContext.ensureOutboundMessageContext().setMessage(new OAuth2RevocationSuccessResponse());
     }
 
 }
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/RevokeToken.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/RevokeToken.java
index e6d7f1bf..2d4086a6 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/RevokeToken.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/RevokeToken.java
@@ -25,7 +25,6 @@ import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.storage.RevocationCache;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jwt.JWTClaimsSet;
 
@@ -42,6 +41,7 @@ import net.shibboleth.oidc.profile.oauth2.config.OAuth2TokenRevocationConfigurat
 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 net.shibboleth.shared.primitive.StringSupport;
 
 /**
@@ -169,8 +169,8 @@ public class RevokeToken extends AbstractProfileAction {
             return false;            
         }
 
-        final OAuth2TokenMgmtResponseContext ctx = profileRequestContext.getOutboundMessageContext().getSubcontext(
-                OAuth2TokenMgmtResponseContext.class);
+        final OAuth2TokenMgmtResponseContext ctx = profileRequestContext.ensureOutboundMessageContext()
+                .getSubcontext(OAuth2TokenMgmtResponseContext.class);
         if (ctx == null || ctx.getTokenClaimsSet() == null) {
             log.debug("{} No token validated for revocation, assumed to be invalid", getLogPrefix());
             return false;
@@ -209,6 +209,8 @@ public class RevokeToken extends AbstractProfileAction {
             } else {
                 idToRevoke = rootJti;
             }
+            assert idToRevoke != null;
+            assert revocationLifetime != null;
             if (revocationCache.revoke(RevocationCacheContexts.AUTHORIZATION_CODE, idToRevoke, revocationLifetime)) {
                 log.debug("{} Revoked all tokens based on ID '{}'", getLogPrefix(), idToRevoke);
             } else {
@@ -216,6 +218,7 @@ public class RevokeToken extends AbstractProfileAction {
                 ActionSupport.buildEvent(profileRequestContext, OidcEventIds.REVOCATION_FAILED);
             }
         } else if (OAuth2TokenRevocationMethod.TOKEN.equals(revocationMethod)) {
+            assert revocationLifetime != null;
             if (revocationCache.revoke(RevocationCacheContexts.SINGLE_ACCESS_OR_REFRESH_TOKENS, jti,
                     revocationLifetime)) {
                 log.debug("{} Revoked the single token with ID '{}'", getLogPrefix(), jti);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetAccessTokenToResponseContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetAccessTokenToResponseContext.java
index 3cf5f664..43961b52 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetAccessTokenToResponseContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetAccessTokenToResponseContext.java
@@ -14,6 +14,7 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl;
 
+import java.time.Duration;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -23,12 +24,14 @@ import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import com.nimbusds.jwt.JWT;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.AccessTokenContext;
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
 import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractOIDCResponseAction;
 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;
@@ -52,9 +55,12 @@ public class SetAccessTokenToResponseContext extends AbstractOIDCResponseAction
     /** Constructor. */
     public SetAccessTokenToResponseContext() {
         // PRC -> outbound message context -> OIDC response context -> ATC
-        accessTokenContextLookupStrategy = new ChildContextLookup<>(AccessTokenContext.class).compose(
-                new ChildContextLookup<>(OIDCAuthenticationResponseContext.class).compose(
-                        new OutboundMessageContextLookup()));
+        final Function<ProfileRequestContext,AccessTokenContext> atcls = 
+                new ChildContextLookup<>(AccessTokenContext.class).compose(
+                        new ChildContextLookup<>(OIDCAuthenticationResponseContext.class).compose(
+                                new OutboundMessageContextLookup()));
+        assert atcls != null;
+        accessTokenContextLookupStrategy = atcls;
     }
 
     /**
@@ -84,12 +90,19 @@ public class SetAccessTokenToResponseContext extends AbstractOIDCResponseAction
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
             return false;
         }
-        
-        if (tokenCtx.getJWT() == null && tokenCtx.getOpaque() == null) {
+
+        final AccessTokenContext nonNullTokenCtx = tokenCtx;
+        assert nonNullTokenCtx != null;
+        if (nonNullTokenCtx.getJWT() == null && nonNullTokenCtx.getOpaque() == null) {
             log.debug("{} Access token is missing", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
             return false;
         }
+        if (nonNullTokenCtx.getLifetime() == null) {
+            log.debug("{} Access token lifetime is missing", getLogPrefix());
+            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
+            return false;
+        }
         
         return true;
     }
@@ -97,15 +110,21 @@ public class SetAccessTokenToResponseContext extends AbstractOIDCResponseAction
     /** {@inheritDoc} */
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
-        
+
+        final AccessTokenContext nonNullTokenCtx = tokenCtx;
+        assert nonNullTokenCtx != null;
+
         final String token;
-        if (tokenCtx.getJWT() != null) {
-            token = tokenCtx.getJWT().serialize();
+        final JWT jwt = nonNullTokenCtx.getJWT();
+        if (jwt != null) {
+            token = jwt.serialize();
         } else {
-            token = tokenCtx.getOpaque();
+            token = nonNullTokenCtx.getOpaque();
         }
-        
-        getOidcResponseContext().setAccessToken(token, tokenCtx.getLifetime(), getOidcResponseContext().getScope());
+
+        final Duration lifetime = nonNullTokenCtx.getLifetime();
+        assert lifetime != null;
+        getOidcResponseContext().setAccessToken(token, lifetime, getOidcResponseContext().getScope());
     }
 
 }
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetAuthorizationCodeToResponseContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetAuthorizationCodeToResponseContext.java
index 8559122d..5262bec6 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetAuthorizationCodeToResponseContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetAuthorizationCodeToResponseContext.java
@@ -14,6 +14,7 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl;
 
+import java.net.URI;
 import java.text.ParseException;
 import java.time.Duration;
 import java.time.Instant;
@@ -27,10 +28,11 @@ import javax.annotation.Nullable;
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.oauth2.sdk.AuthorizationRequest;
 import com.nimbusds.oauth2.sdk.Scope;
+import com.nimbusds.oauth2.sdk.id.ClientID;
 import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
 import net.minidev.json.JSONArray;
 import net.shibboleth.idp.authn.context.SubjectContext;
@@ -51,6 +53,7 @@ import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 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.security.DataSealer;
 import net.shibboleth.shared.security.DataSealerException;
 import net.shibboleth.shared.security.IdentifierGenerationStrategy;
@@ -129,12 +132,19 @@ public class SetAuthorizationCodeToResponseContext extends AbstractOAuthAuthoriz
     public SetAuthorizationCodeToResponseContext() {
         codeChallengeLookupStrategy = new DefaultRequestCodeChallengeLookupFunction();
         codeChallengeMethodLookupStrategy = new DefaultRequestCodeChallengeMethodLookupFunction();
-        tokenClaimsContextLookupStrategy =
+
+        final Function<ProfileRequestContext, OIDCAuthenticationResponseTokenClaimsContext> tccls =
                 new ChildContextLookup<>(OIDCAuthenticationResponseTokenClaimsContext.class).compose(
                         new OIDCAuthenticationResponseContextLookupFunction());
-        consentContextLookupStrategy =
+        assert tccls != null;
+        tokenClaimsContextLookupStrategy = tccls;
+
+        final Function<ProfileRequestContext, OIDCAuthenticationResponseConsentContext> ccls =
                 new ChildContextLookup<>(OIDCAuthenticationResponseConsentContext.class).compose(
                         new OIDCAuthenticationResponseContextLookupFunction());
+        assert ccls != null;
+        consentContextLookupStrategy = ccls;
+
         authzCodeLifetimeLookupStrategy = new AuthzCodeLifetimeLookupFunction();
         issuerLookupStrategy = new IssuerLookupFunction();
         consentEnabledPredicate = new AttributeConsentFlowEnabledPredicate();
@@ -334,6 +344,9 @@ public class SetAuthorizationCodeToResponseContext extends AbstractOAuthAuthoriz
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
         final OIDCAuthenticationResponseContext responseCtx = getOidcResponseContext();
+        assert responseCtx != null;
+        final AuthorizationRequest authorizationRequest = getAuthorizationRequest();
+        assert authorizationRequest != null;
         
         final OIDCAuthenticationResponseConsentContext consentCtx =
                 consentContextLookupStrategy.apply(profileRequestContext);
@@ -348,18 +361,36 @@ public class SetAuthorizationCodeToResponseContext extends AbstractOAuthAuthoriz
             claimsID = tokenClaimsCtx.getIdtokenClaims();
             claimsUI = tokenClaimsCtx.getUserinfoClaims();
         }
-        final Instant dateExp = Instant.now().plus(authzCodeLifetime);
+        final Instant now = Instant.now();
+        final Instant dateExp = now.plus(authzCodeLifetime);
+        assert dateExp != null;
         final Scope scope = responseCtx.getScope();
+        final ClientID clientId = authorizationRequest.getClientID();
+        assert clientId != null;
+        final String issuer = issuerLookupStrategy.apply(profileRequestContext);
+        assert subjectCtx != null;
+        final String principal = subjectCtx.getPrincipalName();
+        final String subject = responseCtx.getSubject();
+        final Instant authTime = responseCtx.getAuthTime();
+        final URI redirectUri = responseCtx.getRedirectURI();
+        if (issuer == null || principal == null | subject == null || authTime == null || redirectUri == null) {
+            log.warn("{} Mandatory claims set variable is missing", getLogPrefix());
+            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+            return;
+        }
+        assert principal != null;
+        assert subject != null;
+        assert idGenerator != null;
         final AuthorizeCodeClaimsSet claimsSet = new AuthorizeCodeClaimsSet.Builder()
                 .setJWTID(idGenerator, xmlSafeIdentifier)
-                .setClientID(getAuthorizationRequest().getClientID())
-                .setIssuer(issuerLookupStrategy.apply(profileRequestContext))
-                .setPrincipal(subjectCtx.getPrincipalName())
-                .setSubject(responseCtx.getSubject())
-                .setIssuedAt(Instant.now())
+                .setClientID(clientId)
+                .setIssuer(issuer)
+                .setPrincipal(principal)
+                .setSubject(subject)
+                .setIssuedAt(now)
                 .setExpiresAt(dateExp)
-                .setAuthenticationTime(responseCtx.getAuthTime())
-                .setRedirectURI(responseCtx.getRedirectURI())
+                .setAuthenticationTime(authTime)
+                .setRedirectURI(redirectUri)
                 .setScope(scope != null ? scope : new Scope())
                 .setAudience(responseCtx.getAudience())
                 .setACR(responseCtx.getAcr())
@@ -375,17 +406,22 @@ public class SetAuthorizationCodeToResponseContext extends AbstractOAuthAuthoriz
                 .build();
 
         if (manipulationStrategy != null) {
+            final JWTClaimsSet jwtClaimsSet = claimsSet.getClaimsSet();
+            assert jwtClaimsSet != null;
             log.debug("{} Manipulation strategy has been set, applying it to the claims set {}", getLogPrefix(),
                     claimsSet.serialize());
+            assert manipulationStrategy != null;
             final Map<String, Object> result = manipulationStrategy.apply(profileRequestContext,
-                    claimsSet.getClaimsSet().toJSONObject());
+                    jwtClaimsSet.toJSONObject());
             if (result == null) {
                 log.debug("{} Manipulation strategy returned null, leaving token claims set untouched.",
                         getLogPrefix());
             } else {
                 log.debug("{} Applying the manipulated claims into the token claims set", getLogPrefix());
                 try {
-                    claimsSet.setClaimsSet(JWTClaimsSet.parse(result));
+                    final JWTClaimsSet parsedClaimsSet = JWTClaimsSet.parse(result);
+                    assert parsedClaimsSet != null;
+                    claimsSet.setClaimsSet(parsedClaimsSet);
                 } catch (final ParseException e) {
                     log.error("{} The resulted claims set could not be transformed into ", getLogPrefix(), e);
                     ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_PROFILE_CONFIG);
@@ -399,7 +435,9 @@ public class SetAuthorizationCodeToResponseContext extends AbstractOAuthAuthoriz
         // We set token claims set to response context for possible access token generation.
         responseCtx.setAuthorizationGrantClaimsSet(claimsSet);
         try {
-            responseCtx.setAuthorizationCode(claimsSet.serialize(dataSealer));
+            assert dataSealer != null;
+            final String sealedCode = claimsSet.serialize(dataSealer);
+            responseCtx.setAuthorizationCode(sealedCode);
             log.debug("{} Setting authz code {} as {} to response context ", getLogPrefix(), claimsSet.serialize(),
                     responseCtx.getAuthorizationCode());
         } catch (final DataSealerException e) {
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetRequestObjectToResponseContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetRequestObjectToResponseContext.java
index 17a2a457..61952caf 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetRequestObjectToResponseContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/SetRequestObjectToResponseContext.java
@@ -36,15 +36,19 @@ 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 com.nimbusds.jwt.JWT;
 import com.nimbusds.jwt.JWTParser;
+import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
+import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
 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 that stored request object to {@link OIDCAuthenticationResponseContext}. The request
@@ -103,6 +107,7 @@ public class SetRequestObjectToResponseContext extends AbstractOAuthAuthorizatio
     @Nonnull
     private HttpClientContext buildHttpContext(@Nonnull final ClassicHttpRequest request) {
         final HttpClientContext clientContext = HttpClientContext.create();
+        assert clientContext != null;
         HttpClientSecuritySupport.marshalSecurityParameters(clientContext, httpClientSecurityParameters, false);
         HttpClientSecuritySupport.addDefaultTLSTrustEngineCriteria(clientContext, request);
         return clientContext;
@@ -122,11 +127,11 @@ public class SetRequestObjectToResponseContext extends AbstractOAuthAuthorizatio
         if (!super.doPreExecute(profileRequestContext)) {
             return false;
         }
-        
+
         if (!getAuthorizationRequest().specifiesRequestObject()) {
             if (requestObjectEnforcedPredicate.test(profileRequestContext)) {
                 log.warn("{} No request_uri or request by value, even though it's enforced for {}", getLogPrefix(),
-                        getMetadataContext().getClientInformation().getID().getValue());
+                        getAuthorizationRequest().getClientID().getValue());
                 ActionSupport.buildEvent(profileRequestContext, OidcEventIds.MISSING_MANDATORY_REQUEST_OBJECT);
             } else {
                 log.debug("{} No request_uri or request by value, nothing to do", getLogPrefix());
@@ -147,21 +152,28 @@ public class SetRequestObjectToResponseContext extends AbstractOAuthAuthorizatio
     /** {@inheritDoc} */
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
-        if (getAuthorizationRequest().getRequestObject() != null) {
-            getOidcResponseContext().setRequestObject(getAuthorizationRequest().getRequestObject());
+        final OIDCAuthenticationResponseContext oidcResponseContext = getOidcResponseContext();
+        assert oidcResponseContext != null;
+        final JWT requestObject = getAuthorizationRequest().getRequestObject();
+        if (requestObject != null) {
+            oidcResponseContext.setRequestObject(requestObject);
             log.debug("{} Request object {} by value stored to oidc response context", getLogPrefix(),
-                    getOidcResponseContext().getRequestObject().serialize());
+                    requestObject.serialize());
             return;
         }
         
         // Request URI must be found in metadata.
         boolean authorized = false;
-        if (getMetadataContext() != null && getMetadataContext().getClientInformation() != null) {
-            final OIDCClientMetadata metadata = getMetadataContext().getClientInformation().getOIDCMetadata();
-            if (metadata != null) {
-                final Set<URI> allowedURIs = metadata.getRequestObjectURIs();
-                if (allowedURIs != null) {
-                    authorized = allowedURIs.contains(getAuthorizationRequest().getRequestURI());
+        final OIDCMetadataContext metadataContext = getMetadataContext();
+        if (metadataContext != null) {
+            final OIDCClientInformation clientInformation = metadataContext.getClientInformation();
+            if (clientInformation != null) {
+                final OIDCClientMetadata metadata = clientInformation.getOIDCMetadata();
+                if (metadata != null) {
+                    final Set<URI> allowedURIs = metadata.getRequestObjectURIs();
+                    if (allowedURIs != null) {
+                        authorized = allowedURIs.contains(getAuthorizationRequest().getRequestURI());
+                    }
                 }
             }
         }
@@ -176,13 +188,15 @@ public class SetRequestObjectToResponseContext extends AbstractOAuthAuthorizatio
         final HttpGet httpRequest = new HttpGet(getAuthorizationRequest().getRequestURI());
         final HttpClientContext httpContext = buildHttpContext(httpRequest);
         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);
             if (response.getCode() == HttpStatus.SC_OK) {
-                final String requestObject = EntityUtils.toString(response.getEntity());
+                final String requestObjectValue = EntityUtils.toString(response.getEntity());
                 try {
-                    getOidcResponseContext().setRequestObject(JWTParser.parse(requestObject));
+                    oidcResponseContext.setRequestObject(JWTParser.parse(requestObjectValue));
                     log.debug("{} Request object {} by reference stored to oidc response context", getLogPrefix(),
-                            getOidcResponseContext().getRequestObject().serialize());
+                            JWTParser.parse(requestObjectValue).serialize());
                     return;
                 } catch (final ParseException e) {
                     log.error("{} Unable to parse request object from request_uri, {}", getLogPrefix(), e.getMessage());
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateAudience.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateAudience.java
index d672b5b5..b2854d38 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateAudience.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateAudience.java
@@ -30,18 +30,18 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.ProxiedRequesterContext;
 import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
-import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseTokenClaimsContext;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.ClientInfoAudienceLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultOIDCMetadataContextLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.TokenRequestAudienceLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractOIDCAuthenticationResponseAction;
 import net.shibboleth.idp.plugin.oidc.op.profile.logic.IssueIDTokenCondition;
+import net.shibboleth.idp.plugin.oidc.op.token.support.TokenClaimsSet;
 import net.shibboleth.oidc.profile.core.OidcEventIds;
 import net.shibboleth.profile.context.navigate.IssuerLookupFunction;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Action that validates requested resource/audience values against a computed set of "allowed"
@@ -79,19 +79,20 @@ public class ValidateAudience extends AbstractOIDCAuthenticationResponseAction {
     /** Whether the request includes the OP as an audience. */
     @Nonnull private Predicate<ProfileRequestContext> selfAudienceCondition;
     
-    /** Strategy used to locate the {@link OIDCAuthenticationResponseTokenClaimsContext}. */
-    @Nonnull
-    private Function<ProfileRequestContext,OIDCAuthenticationResponseTokenClaimsContext>
-    tokenClaimsContextLookupStrategy;
-    
     /** Constructor. */
     public ValidateAudience() {
         requestedAudienceLookupStrategy = new TokenRequestAudienceLookupFunction();
         relyingPartyIdLookupStrategy = new IssuerLookupFunction();
-        allowedAudienceLookupStrategy = new ClientInfoAudienceLookupFunction().compose(
+        final Function<ProfileRequestContext,List<String>> aals = new ClientInfoAudienceLookupFunction().compose(
                 new DefaultOIDCMetadataContextLookupFunction());
-        proxiedRequesterContextCreationStrategy = new ChildContextLookup<>(ProxiedRequesterContext.class, true).compose(
-                new OutboundMessageContextLookup());
+        assert aals != null;
+        allowedAudienceLookupStrategy = aals;
+        final Function<ProfileRequestContext,ProxiedRequesterContext> prccs = 
+                new ChildContextLookup<>(ProxiedRequesterContext.class, true).compose(
+                        new OutboundMessageContextLookup());
+        assert prccs != null;
+        proxiedRequesterContextCreationStrategy = prccs;
+
         // openid scope -> we're issuing an ID token -> the OP will be an audience for the access token
         selfAudienceCondition = new IssueIDTokenCondition();
     }
@@ -172,8 +173,10 @@ public class ValidateAudience extends AbstractOIDCAuthenticationResponseAction {
         
         // These come from a previous authorization grant (authz code or refresh token).
         List<String> previouslyGrantedAudience = null;
-        if (getOidcResponseContext().getAuthorizationGrantClaimsSet() != null) {
-            previouslyGrantedAudience = getOidcResponseContext().getAuthorizationGrantClaimsSet().getAudience();
+        final OIDCAuthenticationResponseContext oidcResponseContext = getOidcResponseContext();
+        final TokenClaimsSet grantClaimsSet = oidcResponseContext.getAuthorizationGrantClaimsSet();
+        if (grantClaimsSet != null) {
+            previouslyGrantedAudience = grantClaimsSet.getAudience();
         }
 
         // These come from a request object or parameter. Absent by definition on the UserInfo endpoint.
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateAuthorizationRequestType.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateAuthorizationRequestType.java
index f2226bde..71aa3df8 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateAuthorizationRequestType.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateAuthorizationRequestType.java
@@ -22,12 +22,12 @@ 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.AuthorizationRequest;
 
 import net.shibboleth.idp.plugin.oidc.op.profile.logic.DefaultAuthorizationRequestTypeValidationStrategy;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * An action that validates the incoming OAuth2 authorization request via configurable strategy.
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateClientIDAgainstPolicy.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateClientIDAgainstPolicy.java
index 25ee34e3..fbf6f0fa 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateClientIDAgainstPolicy.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateClientIDAgainstPolicy.java
@@ -26,7 +26,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.id.ClientID;
 
@@ -40,6 +39,7 @@ import net.shibboleth.oidc.profile.config.navigate.UnregisteredClientPolicyLooku
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Validates a client ID against unregistered client policy via configurable policy enforcer. The validation is done
@@ -119,7 +119,7 @@ public class ValidateClientIDAgainstPolicy extends AbstractProfileAction {
         }
 
         final OIDCMetadataContext oidcMetadataContext =
-                profileRequestContext.getInboundMessageContext().getSubcontext(OIDCMetadataContext.class);
+                profileRequestContext.ensureInboundMessageContext().getSubcontext(OIDCMetadataContext.class);
         if (oidcMetadataContext != null && oidcMetadataContext.getClientInformation() != null) {
             log.debug("{} OIDC metadata context is populated: client ID has already been validated against metadata",
                     getLogPrefix());
@@ -145,14 +145,20 @@ public class ValidateClientIDAgainstPolicy extends AbstractProfileAction {
     /** {@inheritDoc} */
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
-
+        assert clientId != null;
+        final String clientIdValue = clientId.getValue();
+        assert clientIdValue != null;
+        assert policies != null;
         final Pair<Object, Boolean> enforcerResult =
-                unregisteredClientPolicyEnforcer.apply(clientId.getValue(), policies.get("client_id"));
-        if (enforcerResult.getSecond() && clientId.getValue().equals(enforcerResult.getFirst())) {
-            log.debug("{} The client ID {} is compliant with the policy", getLogPrefix(), clientId.getValue());
-            return;
+                unregisteredClientPolicyEnforcer.apply(clientIdValue, policies.get("client_id"));
+        if (enforcerResult != null) {
+            final Boolean result = enforcerResult.getSecond();
+            if (result != null && result.booleanValue() && clientIdValue.equals(enforcerResult.getFirst())) {
+                log.debug("{} The client ID {} is compliant with the policy", getLogPrefix(), clientIdValue);
+                return;
+            }
         }
-        log.warn("{} The client ID {} is not compliant with the policy", getLogPrefix(), clientId);
+        log.warn("{} The client ID {} is not compliant with the policy", getLogPrefix(), clientIdValue);
         ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
     }
 
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateCodeChallenge.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateCodeChallenge.java
index 2242c5ea..c7582a47 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateCodeChallenge.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateCodeChallenge.java
@@ -23,7 +23,6 @@ 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.profile.context.navigate.DefaultRequestCodeChallengeLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestCodeChallengeMethodLookupFunction;
@@ -31,6 +30,8 @@ import net.shibboleth.oidc.profile.config.logic.AllowPKCEPlainPredicate;
 import net.shibboleth.oidc.profile.config.logic.ForcePKCEPredicate;
 import net.shibboleth.oidc.profile.core.OidcEventIds;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
 
 /**
  * Validates the presence of PKCE code challenge parameter from the incoming authentication request.
@@ -130,7 +131,7 @@ public class ValidateCodeChallenge  extends AbstractOAuthAuthorizationResponseAc
 
         codeChallenge = codeChallengeLookupStrategy.apply(profileRequestContext);
 
-        if ((codeChallenge == null || codeChallenge.isEmpty()) && !forcePKCE) {
+        if (StringSupport.trimOrNull(codeChallenge) == null && !forcePKCE) {
             log.debug("{} No PKCE code challenge in request, nothing to do", getLogPrefix());
             return false;
         }
@@ -142,13 +143,13 @@ public class ValidateCodeChallenge  extends AbstractOAuthAuthorizationResponseAc
     /** {@inheritDoc} */
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
-        if (codeChallenge == null || codeChallenge.isEmpty()) {
+        if (StringSupport.trimOrNull(codeChallenge) == null) {
             log.warn("{} No PKCE code challenge presented in authentication request" +
                             " even though required by the profile configuration", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, OidcEventIds.MISSING_PKCE_CODE_CHALLENGE);
             return;
         }
-        if (codeChallengeMethod == null || codeChallengeMethod.isEmpty() || "plain".equals(codeChallengeMethod)) {
+        if (StringSupport.trimOrNull(codeChallengeMethod) == null || "plain".equals(codeChallengeMethod)) {
             if (!plainPKCE) {
                 log.warn("{} Plain PKCE code challenge method not allowed", getLogPrefix());
                 ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_PKCE_TRANSFORMATION_METHOD);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRedirectURI.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRedirectURI.java
index 69b47553..929eff93 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRedirectURI.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRedirectURI.java
@@ -25,8 +25,8 @@ 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 net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestRedirectURILookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultValidRedirectUrisLookupFunction;
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
@@ -39,6 +39,7 @@ import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Action that validates redirect uri is expected. Validated redirect uri is stored to response context.
@@ -159,7 +160,10 @@ public class ValidateRedirectURI extends AbstractOAuthAuthorizationResponseActio
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
         final URI requestRedirectURI = redirectURILookupStrategy.apply(profileRequestContext);
-        
+
+        final OIDCAuthenticationResponseContext oidcResponseContext = getOidcResponseContext();
+        assert oidcResponseContext != null;
+
         if (requestRedirectURI != null && getMetadataContext() == null) {
             final Map<String, UnregisteredClientPolicy> policies =
                     unregisteredClientPolicyLookupStrategy.apply(profileRequestContext);
@@ -167,11 +171,15 @@ public class ValidateRedirectURI extends AbstractOAuthAuthorizationResponseActio
                 final Pair<Object, Boolean> result =
                         unregisteredClientPolicyEnforcer.apply(requestRedirectURI.toString(),
                                 policies.get("redirect_uri"));
-                if (result.getSecond() && requestRedirectURI.toString().equals(result.getFirst())) {
-                    log.debug("{} Redirection URI {} accepted by the policy for unregistered clients", getLogPrefix(),
-                            requestRedirectURI);
-                    getOidcResponseContext().setRedirectURI(requestRedirectURI);
-                    return;
+                if (result != null) {
+                    final Boolean enforcerResult = result.getSecond();
+                    if (enforcerResult != null && enforcerResult.booleanValue() 
+                            && requestRedirectURI.toString().equals(result.getFirst())) {
+                        log.debug("{} Redirection URI {} accepted by the policy for unregistered clients", getLogPrefix(),
+                                requestRedirectURI);
+                        oidcResponseContext.setRedirectURI(requestRedirectURI);
+                        return;
+                    }
                 }
             }
             log.warn("{} Redirection URI {} is not accepted by the policy for unregistered clients", getLogPrefix(),
@@ -194,7 +202,7 @@ public class ValidateRedirectURI extends AbstractOAuthAuthorizationResponseActio
         }
 
         if (redirectionURIs.contains(requestRedirectURI)) {
-            getOidcResponseContext().setRedirectURI(requestRedirectURI);
+            oidcResponseContext.setRedirectURI(requestRedirectURI);
             log.debug("{} Redirection URI validated {}", getLogPrefix(), requestRedirectURI);
             return;
         }
@@ -235,7 +243,9 @@ public class ValidateRedirectURI extends AbstractOAuthAuthorizationResponseActio
             if (singleRegisteredUri.equals(singleValidUri)) {
                 log.debug("{} No requested redirect_uri found, but allowing it due to single trusted value {}",
                         getLogPrefix(), singleRegisteredUri);
-                getOidcResponseContext().setRedirectURI(singleRegisteredUri);
+                final OIDCAuthenticationResponseContext oidcResponseContext = getOidcResponseContext();
+                assert oidcResponseContext != null;
+                oidcResponseContext.setRedirectURI(singleRegisteredUri);
                 return;
             } else {
                 log.warn("{} Registered URI '{}' did not match with the valid one '{}'", getLogPrefix(),
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRequestObject.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRequestObject.java
index 30a442ba..cd6a4c49 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRequestObject.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateRequestObject.java
@@ -15,17 +15,13 @@
 package net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl;
 
 import java.text.ParseException;
-import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jwt.JWT;
@@ -34,14 +30,17 @@ import com.nimbusds.jwt.PlainJWT;
 import com.nimbusds.jwt.SignedJWT;
 import com.nimbusds.oauth2.sdk.ResponseType;
 import com.nimbusds.oauth2.sdk.id.ClientID;
+import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 
+import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
 import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
 import net.shibboleth.oidc.jwt.claims.JWTValidationException;
+import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
 import net.shibboleth.oidc.profile.core.OidcEventIds;
-import net.shibboleth.oidc.security.jose.context.SecurityParametersContext;
 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 request object in response context.
@@ -51,11 +50,6 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
     /** Class logger. */
     @Nonnull private Logger log = LoggerFactory.getLogger(ValidateRequestObject.class);
 
-    /**
-     * Strategy used to locate the {@link SecurityParametersContext} to use for signing.
-     */
-    @Nonnull private Function<ProfileRequestContext, SecurityParametersContext> securityParametersLookupStrategy;
-
     /** Request Object. */
     @Nullable private JWT requestObject;
 
@@ -67,21 +61,6 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
 
     /** Constructor. */
     public ValidateRequestObject() {
-        securityParametersLookupStrategy = new ChildContextLookup<>(SecurityParametersContext.class).compose(
-                new InboundMessageContextLookup());
-    }
-
-    /**
-     * Set the strategy used to locate the {@link SecurityParametersContext} to use.
-     * 
-     * @param strategy lookup strategy
-     */
-    public void setSecurityParametersLookupStrategy(
-            @Nonnull final Function<ProfileRequestContext, SecurityParametersContext> strategy) {
-        ifInitializedThrowUnmodifiabledComponentException();
-
-        securityParametersLookupStrategy =
-                Constraint.isNotNull(strategy, "SecurityParameterContext lookup strategy cannot be null");
     }
 
     /**
@@ -125,7 +104,9 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
             return false;
         }
         
-        requestObject = getOidcResponseContext().getRequestObject();
+        final OIDCAuthenticationResponseContext oidcResponseContext = getOidcResponseContext();
+        assert oidcResponseContext != null;
+        requestObject = oidcResponseContext.getRequestObject();
         if (requestObject == null) {
             log.debug("{} No request object, nothing to do", getLogPrefix());
             return false;
@@ -146,19 +127,26 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
                 ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
                 return;
             }
-            final JWSAlgorithm requestObjectAlg =
-                    getMetadataContext().getClientInformation().getOIDCMetadata().getRequestObjectJWSAlg();
-            if (requestObjectAlg != null && !"none".equals(requestObjectAlg.getName())) {
-                log.error("{} Request object is not signed, registered alg is {}", getLogPrefix(),
-                        requestObjectAlg.getName());
-                ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
-                return;
+            final OIDCMetadataContext metadataContext = getMetadataContext();
+            if (metadataContext != null) {
+                final OIDCClientInformation clientInformation = metadataContext.getClientInformation();
+                if (clientInformation != null && clientInformation.getOIDCMetadata() != null) {
+                    final JWSAlgorithm requestObjectAlg =
+                            clientInformation.getOIDCMetadata().getRequestObjectJWSAlg();
+                    if (requestObjectAlg != null && !"none".equals(requestObjectAlg.getName())) {
+                        log.error("{} Request object is not signed, registered alg is {}", getLogPrefix(),
+                                requestObjectAlg.getName());
+                        ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
+                        return;
+                    }
+                }
             }
         }
 
         final JWTClaimsSet claimsSet;
         // Validate still client_id and response_type values
         try {
+            assert requestObject != null;
             claimsSet = requestObject.getJWTClaimsSet();
             if (claimsSet.getClaims().containsKey("client_id")
                     && !getAuthorizationRequest().getClientID()
@@ -169,7 +157,7 @@ public class ValidateRequestObject extends AbstractOAuthAuthorizationResponseAct
             }
             if (claimsSet.getClaims().containsKey("response_type")
                     && !getAuthorizationRequest().getResponseType().equals(new ResponseType(
-                            ((String) requestObject.getJWTClaimsSet().getClaim("response_type")).split(" ")))) {
+                            ((String) claimsSet.getClaim("response_type")).split(" ")))) {
                 log.error("{} response_type in request object not matching response_type request parameter",
                         getLogPrefix());
                 ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_OBJECT);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateResponseType.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateResponseType.java
index a44bbebe..b2f5aa10 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateResponseType.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateResponseType.java
@@ -24,13 +24,14 @@ 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.nimbusds.oauth2.sdk.ResponseType;
+import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestResponseTypeLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultValidResponseTypesLookupFunction;
+import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
 import net.shibboleth.oidc.metadata.policy.UnregisteredClientPolicy;
 import net.shibboleth.oidc.metadata.policy.impl.DefaultMetadataPolicyEnforcer;
@@ -38,6 +39,7 @@ import net.shibboleth.oidc.profile.config.navigate.UnregisteredClientPolicyLooku
 import net.shibboleth.oidc.profile.core.OidcEventIds;
 import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * An action that validates the requested response_type is (1) registered to the requesting RP (or accepted in the
@@ -124,13 +126,17 @@ public class ValidateResponseType extends AbstractOAuthAuthorizationResponseActi
 
         final ResponseType requestedType = requestedResponseTypeLookupStrategy.apply(profileRequestContext);
 
-        if (getMetadataContext() != null) {
-            final Set<ResponseType> registeredTypes =
-                    getMetadataContext().getClientInformation().getMetadata().getResponseTypes();
-            if (registeredTypes == null || registeredTypes.isEmpty() || !registeredTypes.contains(requestedType)) {
-                log.warn("{} The response type {} is not registered for this RP", getLogPrefix(), requestedType);
-                ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_RESPONSE_TYPE);
-                return;
+        final OIDCMetadataContext metadataContext = getMetadataContext();
+        if (metadataContext != null) {
+            final OIDCClientInformation clientInformation = metadataContext.getClientInformation();
+            if (clientInformation != null && clientInformation.getOIDCMetadata() != null) {
+                final Set<ResponseType> registeredTypes =
+                        clientInformation.getMetadata().getResponseTypes();
+                if (registeredTypes == null || registeredTypes.isEmpty() || !registeredTypes.contains(requestedType)) {
+                    log.warn("{} The response type {} is not registered for this RP", getLogPrefix(), requestedType);
+                    ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_RESPONSE_TYPE);
+                    return;
+                }
             }
         } else {
             final Map<String, UnregisteredClientPolicy> policies =
@@ -143,10 +149,13 @@ public class ValidateResponseType extends AbstractOAuthAuthorizationResponseActi
             final Pair<Object, Boolean> enforcerResult =
                     unregisteredClientPolicyEnforcer.apply(requestedType == null ? "" : requestedType.toString(),
                             policies.get("response_type"));
-            if (!enforcerResult.getSecond()) {
-                log.warn("{} The response type {} is not compliant with the policy", getLogPrefix(), requestedType);
-                ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_RESPONSE_TYPE);
-                return;
+            if (enforcerResult != null) {
+                final Boolean validationResult = enforcerResult.getSecond();
+                if (validationResult == null || !validationResult.booleanValue()) {
+                    log.warn("{} The response type {} is not compliant with the policy", getLogPrefix(), requestedType);
+                    ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_RESPONSE_TYPE);
+                    return;
+                }
             }
         }
 
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateScope.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateScope.java
index b29b78c9..105a3c04 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateScope.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/ValidateScope.java
@@ -20,25 +20,28 @@ import java.util.function.Function;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.opensaml.messaging.context.BaseContext;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.ResponseType;
 import com.nimbusds.oauth2.sdk.Scope;
 import com.nimbusds.openid.connect.sdk.OIDCScopeValue;
 
+import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseTokenClaimsContext;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.ClientInfoScopeLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultOIDCMetadataContextLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestResponseTypeLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestedScopeLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.OIDCAuthenticationResponseContextLookupFunction;
+import net.shibboleth.idp.plugin.oidc.op.token.support.TokenClaimsSet;
 import net.shibboleth.oidc.profile.core.OidcEventIds;
 import net.shibboleth.profile.context.navigate.RelyingPartyIdLookupFunction;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * Action that validates requested and previously granted scopes are also registered in client metadata
@@ -85,12 +88,16 @@ public class ValidateScope extends AbstractOAuthAuthorizationResponseAction {
     public ValidateScope() {
         requestedScopeLookupStrategy = new DefaultRequestedScopeLookupFunction();
         relyingPartyIdLookupStrategy = new RelyingPartyIdLookupFunction();
-        allowedScopeLookupStrategy = new ClientInfoScopeLookupFunction().compose(
+        final Function<ProfileRequestContext,Scope>  asls = new ClientInfoScopeLookupFunction().compose(
                 new DefaultOIDCMetadataContextLookupFunction());
+        assert asls != null;
+        allowedScopeLookupStrategy = asls;
         mandatoryScopeLookupStrategy = prc -> null;
-        tokenClaimsContextLookupStrategy =
+        final Function<ProfileRequestContext,OIDCAuthenticationResponseTokenClaimsContext> tccls =
                 new ChildContextLookup<>(OIDCAuthenticationResponseTokenClaimsContext.class).compose(
                         new OIDCAuthenticationResponseContextLookupFunction());
+        assert tccls != null;
+        tokenClaimsContextLookupStrategy = tccls;
     }
 
     /**
@@ -164,10 +171,13 @@ public class ValidateScope extends AbstractOAuthAuthorizationResponseAction {
         
         final String clientId = relyingPartyIdLookupStrategy.apply(profileRequestContext);
 
+        final OIDCAuthenticationResponseContext oidcResponseContext = getOidcResponseContext();
+        assert oidcResponseContext != null;
         // These come from a previous authorization grant (authz code or access/refresh token).
         Scope previouslyGrantedScopes = null;
-        if (getOidcResponseContext().getAuthorizationGrantClaimsSet() != null) {
-            previouslyGrantedScopes = getOidcResponseContext().getAuthorizationGrantClaimsSet().getScope();
+        final TokenClaimsSet authzGrantClaimsSet = oidcResponseContext.getAuthorizationGrantClaimsSet();
+        if (authzGrantClaimsSet != null) {
+            previouslyGrantedScopes = authzGrantClaimsSet.getScope();
         }
 
         // These come from a request object or parameter. Absent by definition on the UserInfo endpoint.
@@ -243,16 +253,19 @@ public class ValidateScope extends AbstractOAuthAuthorizationResponseAction {
         }
         
         if (!requestedScopes.isEmpty()) {
-            getOidcResponseContext().setScope(requestedScopes);
+            oidcResponseContext.setScope(requestedScopes);
         }
         
         if (reducedRequestedScopes) {
             final OIDCAuthenticationResponseTokenClaimsContext tokenClaimsCtx =
                     tokenClaimsContextLookupStrategy.apply(profileRequestContext);
             if (tokenClaimsCtx != null) {
-                log.debug("{} Removing grant-encoded attributes due to reduction of requested scopes",
-                        getLogPrefix());
-                tokenClaimsCtx.getParent().removeSubcontext(tokenClaimsCtx);
+                final BaseContext parentContext = tokenClaimsCtx.getParent();
+                if (parentContext != null) {
+                    log.debug("{} Removing grant-encoded attributes due to reduction of requested scopes",
+                            getLogPrefix());
+                    parentContext.removeSubcontext(tokenClaimsCtx);
+                }
             }
         }
     }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java
index f1fcefd4..3b7d43fa 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java
@@ -24,7 +24,6 @@ import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.CurrentOrPreviousEventLookup;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.nimbusds.oauth2.sdk.ErrorObject;
 import com.nimbusds.oauth2.sdk.ErrorResponse;
@@ -32,6 +31,7 @@ import com.nimbusds.oauth2.sdk.http.HTTPResponse;
 
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
  * This action is extended by error response actions. Action reads an event from the configured {@link EventContext}
@@ -120,7 +120,8 @@ public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorRespons
      * @param profileRequestContext profile request context.
      * @return ErrorResponse
      */
-    protected abstract T buildErrorResponse(ErrorObject error, ProfileRequestContext profileRequestContext);
+    protected abstract T buildErrorResponse(@Nonnull final ErrorObject error,
+            @Nonnull final ProfileRequestContext profileRequestContext);
     
     /** {@inheritDoc} */
     @Override

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


More information about the commits mailing list