[java-idp-plugin-oidc-rp] branch main updated: Cleanup Encrypted ID Token and UserInfo lookup strategies

Phil Smart philip.smart at jisc.ac.uk
Mon Mar 13 18:48:03 UTC 2023


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

philsmart pushed a commit to branch main
in repository java-idp-plugin-oidc-rp.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-oidc-rp.git;a=commit;h=051c3c6cbe3a326bd12495aa40790d83dc48f947

The following commit(s) were added to refs/heads/main by this push:
     new 051c3c6  Cleanup Encrypted ID Token and UserInfo lookup strategies
051c3c6 is described below

commit 051c3c6cbe3a326bd12495aa40790d83dc48f947
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Mon Mar 13 18:48:01 2023 +0000

    Cleanup Encrypted ID Token and UserInfo lookup strategies
    
     - Change to Java functions
     - Removes errors from the logs
     - Adds more meaningful logging
---
 ...va => AbstractTokenResponseLookupStrategy.java} | 32 ++++----
 ...stractUserInfoTokenResponseLookupStrategy.java} | 65 ++++++---------
 .../navigate/AccessTokenLookupStrategy.java        | 25 ++----
 .../navigate/DefaultIDTokenLookupStrategy.java     | 24 ++----
 ...gy.java => EncryptedIDTokenLookupStrategy.java} | 57 ++++++++------
 .../EncryptedUserInfoJWTLookupStrategy.java        | 92 ++++++++++++++++++++++
 .../navigate/IDTokenJOSEHeaderLookupStrategy.java  | 24 ++----
 .../navigate/SubFromIDTokenLookupFunction.java     | 22 ++----
 ...nfoInUserInfoResponseContextUpdateStrategy.java | 19 ++---
 .../oidc-relying-party-authn-beans.xml             | 13 +--
 10 files changed, 200 insertions(+), 173 deletions(-)

diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/DefaultIDTokenLookupStrategy.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AbstractTokenResponseLookupStrategy.java
similarity index 73%
copy from idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/DefaultIDTokenLookupStrategy.java
copy to idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AbstractTokenResponseLookupStrategy.java
index 07ed3ce..0adfde2 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/DefaultIDTokenLookupStrategy.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AbstractTokenResponseLookupStrategy.java
@@ -20,28 +20,23 @@ package net.shibboleth.idp.plugin.authn.oidc.rp.context.navigate;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.ThreadSafe;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 
-import com.nimbusds.jwt.JWT;
-
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 
-/** Function that extracts the id_token from the {@link AccessTokenResponseContext}.*/
- at ThreadSafe
-public class DefaultIDTokenLookupStrategy implements Function<ProfileRequestContext, JWT> {
+/** Base class for looking up the token response context.*/
+public abstract class AbstractTokenResponseLookupStrategy {
     
     /** Strategy used to locate the {@link AccessTokenResponseContext} to extract the id_token from.*/
     @Nonnull 
     private final Function<ProfileRequestContext, AccessTokenResponseContext> tokenResponseContextLookupStrategy;
     
     /** Constructor.*/
-    public DefaultIDTokenLookupStrategy() {
+    protected AbstractTokenResponseLookupStrategy() {
         tokenResponseContextLookupStrategy =
                 new ChildContextLookup<>(AccessTokenResponseContext.class, true).compose(
                         new InboundMessageContextLookup()); 
@@ -53,19 +48,20 @@ public class DefaultIDTokenLookupStrategy implements Function<ProfileRequestCont
     *
     * @param strategy the AccessTokenResponseContext lookup strategy to use.
     */
-   public DefaultIDTokenLookupStrategy(
+    protected AbstractTokenResponseLookupStrategy(
            @Nonnull final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
        tokenResponseContextLookupStrategy = 
                Constraint.isNotNull(strategy, "AccessTokenResponseContext lookup strategy can not be null");
-   }
-
-    @Override
-    @Nullable public JWT apply(@Nonnull final ProfileRequestContext prc) {
-        final AccessTokenResponseContext tokenContext = tokenResponseContextLookupStrategy.apply(prc);
-        if (tokenContext == null || tokenContext.getTokenResponse() == null) {
-            return null;
-        }
-        return tokenContext.getTokenResponse().getOIDCTokens().getIDToken();
+    }
+   
+    /**
+     * Get the token response context lookup strategy.
+     * 
+     * @return the lookup strategy
+     */
+    @Nonnull 
+    protected Function<ProfileRequestContext, AccessTokenResponseContext> getTokenResponseContextLookupStrategy() {
+        return tokenResponseContextLookupStrategy;
     }
 
 }
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/UserInfoInUserInfoResponseContextUpdateStrategy.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AbstractUserInfoTokenResponseLookupStrategy.java
similarity index 51%
copy from idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/UserInfoInUserInfoResponseContextUpdateStrategy.java
copy to idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AbstractUserInfoTokenResponseLookupStrategy.java
index 7381e6f..a722c91 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/UserInfoInUserInfoResponseContextUpdateStrategy.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AbstractUserInfoTokenResponseLookupStrategy.java
@@ -17,7 +17,6 @@
 
 package net.shibboleth.idp.plugin.authn.oidc.rp.context.navigate;
 
-import java.util.function.BiConsumer;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -25,64 +24,46 @@ import javax.annotation.Nonnull;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import com.nimbusds.jwt.JWT;
-import com.nimbusds.openid.connect.sdk.UserInfoResponse;
-import com.nimbusds.openid.connect.sdk.UserInfoSuccessResponse;
-
-import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext;
-import net.shibboleth.utilities.java.support.annotation.ParameterName;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 
-/** 
- * Consumer strategy to update the UserInfo JWT in the {@link UserInfoResponseContext}.
- * Note, replaces the entire {@link UserInfoResponse} object.
- */
-public class UserInfoInUserInfoResponseContextUpdateStrategy implements  BiConsumer<ProfileRequestContext, JWT> {
-    
-    /** Class logger. */
-    @Nonnull private final Logger log = LoggerFactory.getLogger(UserInfoInUserInfoResponseContextUpdateStrategy.class);
+/** Base class for looking up the UserInfo token response context.*/
+public abstract class AbstractUserInfoTokenResponseLookupStrategy {
     
-    /** Strategy used to look up the {@link AccessTokenResponseContext} to set id_token on. */
+    /** Strategy used to look up the {@link UserInfoResponseContext}. */
     @Nonnull private final Function<ProfileRequestContext, UserInfoResponseContext> 
             userInfoResponseContextLookupStrategy;
     
+    
+    /** Constructor.*/
+    protected AbstractUserInfoTokenResponseLookupStrategy() {
+        userInfoResponseContextLookupStrategy =
+                new ChildContextLookup<>(UserInfoResponseContext.class, true).compose(
+                        new InboundMessageContextLookup()); 
+    }
+    
     /**
      * 
      * Constructor.
      *
-     * @param strategy the strategy used look up the {@link AccessTokenResponseContext}.
+     * @param strategy the strategy used look up the {@link UserInfoResponseContext}.
      */
-    public UserInfoInUserInfoResponseContextUpdateStrategy(
-            @ParameterName(name="userInfoResponseContextLookupStrategy") final
-        Function<ProfileRequestContext, UserInfoResponseContext> strategy) {
+    protected AbstractUserInfoTokenResponseLookupStrategy(final
+            Function<ProfileRequestContext, UserInfoResponseContext> strategy) {
         
         userInfoResponseContextLookupStrategy = 
                 Constraint.isNotNull(strategy, "userInfoResponseContextLookupStrategy can not be null");
     }
-    
-    /** Constructor.*/
-    public UserInfoInUserInfoResponseContextUpdateStrategy() {
-        userInfoResponseContextLookupStrategy =
-                new ChildContextLookup<>(UserInfoResponseContext.class, true).compose(
-                        new InboundMessageContextLookup()); 
-    }
-
-    @Override
-    public void accept(final ProfileRequestContext profileRequestContext, final JWT token) {
-        
-        final UserInfoResponseContext context = 
-                userInfoResponseContextLookupStrategy.apply(profileRequestContext);  
-        if (context != null) {
-            // Create a new UserInfo element with the new JWT response
-            context.setUserInfo(new UserInfoSuccessResponse(token));
-        } else {
-            log.warn("Unable to set UserInfo back onto response context");
-        }
-        
+   
+    /**
+     * Get the UserInfo response context lookup strategy.
+     * 
+     * @return the lookup strategy
+     */
+    @Nonnull 
+    protected Function<ProfileRequestContext, UserInfoResponseContext> getUserInfoResponseContextLookupStrategy() {
+        return userInfoResponseContextLookupStrategy;
     }
 
 }
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AccessTokenLookupStrategy.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AccessTokenLookupStrategy.java
index 4661edf..856dbe8 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AccessTokenLookupStrategy.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AccessTokenLookupStrategy.java
@@ -23,9 +23,7 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.ThreadSafe;
 
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -33,25 +31,19 @@ import com.nimbusds.oauth2.sdk.token.AccessToken;
 
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
 import net.shibboleth.utilities.java.support.annotation.ParameterName;
-import net.shibboleth.utilities.java.support.logic.Constraint;
 
 /** Function that extracts the access_token from the {@link AccessTokenResponseContext}.*/
 @ThreadSafe
-public class AccessTokenLookupStrategy implements Function<ProfileRequestContext, AccessToken> {
+public class AccessTokenLookupStrategy extends AbstractTokenResponseLookupStrategy 
+                                        implements Function<ProfileRequestContext, AccessToken> {
     
     /** Logger. */
     @Nonnull
     private final Logger log = LoggerFactory.getLogger(AccessTokenLookupStrategy.class);
-    
-    /** Strategy used to locate the {@link AccessTokenResponseContext} to extract the id_token from.*/
-    @Nonnull 
-    private final Function<ProfileRequestContext, AccessTokenResponseContext> tokenResponseContextLookupStrategy;
-    
+   
     /** Constructor.*/
     public AccessTokenLookupStrategy() {
-        tokenResponseContextLookupStrategy =
-                new ChildContextLookup<>(AccessTokenResponseContext.class, true).compose(
-                        new InboundMessageContextLookup()); 
+        super(); 
     }
     
    /**
@@ -60,15 +52,14 @@ public class AccessTokenLookupStrategy implements Function<ProfileRequestContext
     *
     * @param strategy the AccessTokenResponseContext lookup strategy to use.
     */
-   public AccessTokenLookupStrategy(@ParameterName(name = "strategy")
-           @Nonnull final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
-       tokenResponseContextLookupStrategy = 
-               Constraint.isNotNull(strategy, "AccessTokenResponseContext lookup strategy can not be null");
+   public AccessTokenLookupStrategy(@Nonnull @ParameterName(name="accessTokenContextLookupStrategy") 
+                           final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
+       super(strategy);
    }
 
     @Override
     @Nullable public AccessToken apply(@Nonnull final ProfileRequestContext prc) {
-        final AccessTokenResponseContext tokenContext = tokenResponseContextLookupStrategy.apply(prc);
+        final AccessTokenResponseContext tokenContext = getTokenResponseContextLookupStrategy().apply(prc);
         if (tokenContext == null || tokenContext.getTokenResponse() == null ||
                 tokenContext.getTokenResponse().getTokens() == null) {
             return null;
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/DefaultIDTokenLookupStrategy.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/DefaultIDTokenLookupStrategy.java
index 07ed3ce..625dfba 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/DefaultIDTokenLookupStrategy.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/DefaultIDTokenLookupStrategy.java
@@ -23,28 +23,21 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.ThreadSafe;
 
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 
 import com.nimbusds.jwt.JWT;
 
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
-import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
 
 /** Function that extracts the id_token from the {@link AccessTokenResponseContext}.*/
 @ThreadSafe
-public class DefaultIDTokenLookupStrategy implements Function<ProfileRequestContext, JWT> {
-    
-    /** Strategy used to locate the {@link AccessTokenResponseContext} to extract the id_token from.*/
-    @Nonnull 
-    private final Function<ProfileRequestContext, AccessTokenResponseContext> tokenResponseContextLookupStrategy;
+public class DefaultIDTokenLookupStrategy extends AbstractTokenResponseLookupStrategy 
+                implements Function<ProfileRequestContext, JWT> {
     
     /** Constructor.*/
     public DefaultIDTokenLookupStrategy() {
-        tokenResponseContextLookupStrategy =
-                new ChildContextLookup<>(AccessTokenResponseContext.class, true).compose(
-                        new InboundMessageContextLookup()); 
+        super(); 
     }
     
    /**
@@ -53,15 +46,14 @@ public class DefaultIDTokenLookupStrategy implements Function<ProfileRequestCont
     *
     * @param strategy the AccessTokenResponseContext lookup strategy to use.
     */
-   public DefaultIDTokenLookupStrategy(
-           @Nonnull final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
-       tokenResponseContextLookupStrategy = 
-               Constraint.isNotNull(strategy, "AccessTokenResponseContext lookup strategy can not be null");
+   public DefaultIDTokenLookupStrategy(@Nonnull @ParameterName(name="accessTokenContextLookupStrategy") 
+                           final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
+       super(strategy);
    }
 
     @Override
     @Nullable public JWT apply(@Nonnull final ProfileRequestContext prc) {
-        final AccessTokenResponseContext tokenContext = tokenResponseContextLookupStrategy.apply(prc);
+        final AccessTokenResponseContext tokenContext = getTokenResponseContextLookupStrategy().apply(prc);
         if (tokenContext == null || tokenContext.getTokenResponse() == null) {
             return null;
         }
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AccessTokenLookupStrategy.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/EncryptedIDTokenLookupStrategy.java
similarity index 52%
copy from idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AccessTokenLookupStrategy.java
copy to idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/EncryptedIDTokenLookupStrategy.java
index 4661edf..cfa3793 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/AccessTokenLookupStrategy.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/EncryptedIDTokenLookupStrategy.java
@@ -23,35 +23,31 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.ThreadSafe;
 
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.nimbusds.oauth2.sdk.token.AccessToken;
+import com.nimbusds.jwt.EncryptedJWT;
+import com.nimbusds.jwt.JWT;
+import com.nimbusds.jwt.SignedJWT;
 
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
 import net.shibboleth.utilities.java.support.annotation.ParameterName;
-import net.shibboleth.utilities.java.support.logic.Constraint;
 
-/** Function that extracts the access_token from the {@link AccessTokenResponseContext}.*/
+/** 
+ * Function that extracts the id_token from the {@link AccessTokenResponseContext} iff it is an {@link EncryptedJWT} 
+ * type. If not {@code null} is returned.
+ */
 @ThreadSafe
-public class AccessTokenLookupStrategy implements Function<ProfileRequestContext, AccessToken> {
+public class EncryptedIDTokenLookupStrategy extends AbstractTokenResponseLookupStrategy 
+                                                    implements Function<ProfileRequestContext, JWT>{
     
     /** Logger. */
-    @Nonnull
-    private final Logger log = LoggerFactory.getLogger(AccessTokenLookupStrategy.class);
-    
-    /** Strategy used to locate the {@link AccessTokenResponseContext} to extract the id_token from.*/
-    @Nonnull 
-    private final Function<ProfileRequestContext, AccessTokenResponseContext> tokenResponseContextLookupStrategy;
+    @Nonnull private final Logger log = LoggerFactory.getLogger(EncryptedIDTokenLookupStrategy.class);
     
     /** Constructor.*/
-    public AccessTokenLookupStrategy() {
-        tokenResponseContextLookupStrategy =
-                new ChildContextLookup<>(AccessTokenResponseContext.class, true).compose(
-                        new InboundMessageContextLookup()); 
+    public EncryptedIDTokenLookupStrategy() {
+        super();
     }
     
    /**
@@ -60,20 +56,29 @@ public class AccessTokenLookupStrategy implements Function<ProfileRequestContext
     *
     * @param strategy the AccessTokenResponseContext lookup strategy to use.
     */
-   public AccessTokenLookupStrategy(@ParameterName(name = "strategy")
+    public EncryptedIDTokenLookupStrategy(@ParameterName(name="accessTokenContextLookupStrategy")
            @Nonnull final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
-       tokenResponseContextLookupStrategy = 
-               Constraint.isNotNull(strategy, "AccessTokenResponseContext lookup strategy can not be null");
-   }
-
+       super(strategy);
+    }
+    
     @Override
-    @Nullable public AccessToken apply(@Nonnull final ProfileRequestContext prc) {
-        final AccessTokenResponseContext tokenContext = tokenResponseContextLookupStrategy.apply(prc);
-        if (tokenContext == null || tokenContext.getTokenResponse() == null ||
-                tokenContext.getTokenResponse().getTokens() == null) {
+    @Nullable public JWT apply(@Nonnull final ProfileRequestContext prc) {
+        final AccessTokenResponseContext tokenContext = getTokenResponseContextLookupStrategy().apply(prc);
+        if (tokenContext == null || tokenContext.getTokenResponse() == null) {
+            return null;
+        }
+        final JWT token = tokenContext.getTokenResponse().getOIDCTokens().getIDToken();
+        if (token instanceof EncryptedJWT) {
+            log.trace("EncryptedIDToken Lookup: ID Token is encrypted using algorithm '{}'", 
+                    token.getHeader().getAlgorithm());
+            return token;
+        } else if (token instanceof SignedJWT){
+            log.trace("EncryptedIDToken Lookup: ID Token is signed and not encrypted, nothing to return");
+            return null;
+        } else {
+            log.trace("EncryptedIDToken Lookup: ID Token is neither signed nor encrypted, nothing to return");
             return null;
         }
-        return  tokenContext.getTokenResponse().getTokens().getAccessToken();
     }
 
 }
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/EncryptedUserInfoJWTLookupStrategy.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/EncryptedUserInfoJWTLookupStrategy.java
new file mode 100644
index 0000000..4f38650
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/EncryptedUserInfoJWTLookupStrategy.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.context.navigate;
+
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.jwt.EncryptedJWT;
+import com.nimbusds.jwt.JWT;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+
+/** 
+ * Function that extracts the UserInfo JWT from the {@link UserInfoResponseContext} iff it is an {@link EncryptedJWT} 
+ * type. If not {@code null} is returned.
+ */
+ at ThreadSafe
+public class EncryptedUserInfoJWTLookupStrategy extends AbstractUserInfoTokenResponseLookupStrategy 
+                                                    implements Function<ProfileRequestContext, JWT>{
+    
+    /** Logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(EncryptedUserInfoJWTLookupStrategy.class);
+    
+    /**
+     * 
+     * Constructor.
+     *
+     * @param strategy the strategy used look up the {@link AccessTokenResponseContext}.
+     */
+    public EncryptedUserInfoJWTLookupStrategy(
+            @ParameterName(name="userInfoResponseContextLookupStrategy") final
+        Function<ProfileRequestContext, UserInfoResponseContext> strategy) {
+        super(strategy);
+    }
+    
+    /** Constructor.*/
+    public EncryptedUserInfoJWTLookupStrategy() {
+        super();
+    }
+
+    @Override
+    @Nullable public JWT apply(@Nonnull final ProfileRequestContext prc) {
+        final UserInfoResponseContext userInfoContext = getUserInfoResponseContextLookupStrategy().apply(prc);
+        if (userInfoContext == null || userInfoContext.getUserInfo() == null) {
+            return null;
+        }
+        if (userInfoContext.getUserInfo().getUserInfoJWT() == null) {
+            log.trace("EncryptedUserInfoToken Lookup: UserInfo response JWT is null, nothing to return");
+            return null;
+        }
+        final JWT token = userInfoContext.getUserInfo().getUserInfoJWT();
+        if (token instanceof EncryptedJWT) {
+            log.trace("EncryptedUserInfoToken Lookup: UserInfo response JWT is encrypted using algorithm '{}'", 
+                    token.getHeader().getAlgorithm());
+            return token;
+        } else if (token instanceof SignedJWT){
+            log.trace("EncryptedUserInfoToken Lookup:  UserInfo response JWT is signed and not encrypted,"
+                    + " nothing to return");
+            return null;
+        } else {
+            log.trace("EncryptedUserInfoToken Lookup:  UserInfo response JWT is neither signed nor encrypted, "
+                    + "nothing to return");
+            return null;
+        }
+    }
+
+}
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/IDTokenJOSEHeaderLookupStrategy.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/IDTokenJOSEHeaderLookupStrategy.java
index e5e5041..a38ea34 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/IDTokenJOSEHeaderLookupStrategy.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/IDTokenJOSEHeaderLookupStrategy.java
@@ -23,29 +23,22 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.ThreadSafe;
 
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 
 import com.nimbusds.jose.Header;
 import com.nimbusds.jose.JWSHeader;
 
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
-import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
 
 /** Function that extracts the JWS JOSE header from the id_token inside the {@link AccessTokenResponseContext}.*/
 @ThreadSafe
-public class IDTokenJOSEHeaderLookupStrategy implements Function<ProfileRequestContext, JWSHeader> {
-    
-    /** Strategy used to locate the {@link AccessTokenResponseContext} to extract the id_token from.*/
-    @Nonnull 
-    private final Function<ProfileRequestContext, AccessTokenResponseContext> tokenResponseContextLookupStrategy;
+public class IDTokenJOSEHeaderLookupStrategy extends AbstractTokenResponseLookupStrategy 
+                                            implements Function<ProfileRequestContext, JWSHeader> {
     
     /** Constructor.*/
     public IDTokenJOSEHeaderLookupStrategy() {
-        tokenResponseContextLookupStrategy =
-                new ChildContextLookup<>(AccessTokenResponseContext.class, true).compose(
-                        new InboundMessageContextLookup()); 
+        super();
     }
     
    /**
@@ -54,15 +47,14 @@ public class IDTokenJOSEHeaderLookupStrategy implements Function<ProfileRequestC
     *
     * @param strategy the AccessTokenResponseContext lookup strategy to use.
     */
-   public IDTokenJOSEHeaderLookupStrategy(
-           @Nonnull final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
-       tokenResponseContextLookupStrategy = 
-               Constraint.isNotNull(strategy, "AccessTokenResponseContext lookup strategy can not be null");
+   public IDTokenJOSEHeaderLookupStrategy(@Nonnull @ParameterName(name="accessTokenContextLookupStrategy") 
+                   final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
+       super(strategy);
    }
 
     @Override
     @Nullable public JWSHeader apply(@Nonnull final ProfileRequestContext prc) {
-        final AccessTokenResponseContext tokenContext = tokenResponseContextLookupStrategy.apply(prc);
+        final AccessTokenResponseContext tokenContext = getTokenResponseContextLookupStrategy().apply(prc);
         if (tokenContext == null || tokenContext.getTokenResponse() == null || 
                 tokenContext.getTokenResponse().getOIDCTokens().getIDToken() == null) {
             return null;
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/SubFromIDTokenLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/SubFromIDTokenLookupFunction.java
index 7c7105f..78a1c79 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/SubFromIDTokenLookupFunction.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/SubFromIDTokenLookupFunction.java
@@ -25,35 +25,30 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.ThreadSafe;
 
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jwt.JWTClaimsSet;
 
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
-import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
 
 /**
  * A function that pulls the subject 'sub' out of the id_token in the {@link AccessTokenResponseContext}.
  */
 @ThreadSafe
-public class SubFromIDTokenLookupFunction implements BiFunction<ProfileRequestContext, JWTClaimsSet, String> {
+public class SubFromIDTokenLookupFunction extends AbstractTokenResponseLookupStrategy
+                                    implements BiFunction<ProfileRequestContext, JWTClaimsSet, String> {
 
     /** Class logger. */
     @Nonnull
     private final Logger log = LoggerFactory.getLogger(SubFromIDTokenLookupFunction.class);
 
-    /** Strategy used to locate the {@link AccessTokenResponseContext} to extract the id_token from. */
-    @Nonnull
-    private final Function<ProfileRequestContext, AccessTokenResponseContext> tokenResponseContextLookupStrategy;
 
     /** Constructor. */
     public SubFromIDTokenLookupFunction() {
-        tokenResponseContextLookupStrategy = new ChildContextLookup<>(AccessTokenResponseContext.class, true)
-                .compose(new InboundMessageContextLookup());
+        super();
     }
 
     /**
@@ -62,10 +57,9 @@ public class SubFromIDTokenLookupFunction implements BiFunction<ProfileRequestCo
      *
      * @param strategy the AccessTokenResponseContext lookup strategy to use.
      */
-    public SubFromIDTokenLookupFunction(
-            @Nonnull final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
-        tokenResponseContextLookupStrategy =
-                Constraint.isNotNull(strategy, "AccessTokenResponseContext lookup strategy can not be null");
+    public SubFromIDTokenLookupFunction(@Nonnull @ParameterName(name="accessTokenContextLookupStrategy") 
+                    final Function<ProfileRequestContext, AccessTokenResponseContext> strategy) {
+        super(strategy);
     }
 
     /**
@@ -77,7 +71,7 @@ public class SubFromIDTokenLookupFunction implements BiFunction<ProfileRequestCo
     @Override
     @Nullable
     public String apply(@Nonnull final ProfileRequestContext prc, @Nullable final JWTClaimsSet claimsSet) {
-        final AccessTokenResponseContext tokenContext = tokenResponseContextLookupStrategy.apply(prc);
+        final AccessTokenResponseContext tokenContext = getTokenResponseContextLookupStrategy().apply(prc);
         if (tokenContext == null || tokenContext.getTokenResponse().getOIDCTokens().getIDToken() == null) {
             return null;
         }
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/UserInfoInUserInfoResponseContextUpdateStrategy.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/UserInfoInUserInfoResponseContextUpdateStrategy.java
index 7381e6f..bd3a355 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/UserInfoInUserInfoResponseContextUpdateStrategy.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/navigate/UserInfoInUserInfoResponseContextUpdateStrategy.java
@@ -22,9 +22,7 @@ import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,20 +33,17 @@ import com.nimbusds.openid.connect.sdk.UserInfoSuccessResponse;
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext;
 import net.shibboleth.utilities.java.support.annotation.ParameterName;
-import net.shibboleth.utilities.java.support.logic.Constraint;
 
 /** 
  * Consumer strategy to update the UserInfo JWT in the {@link UserInfoResponseContext}.
  * Note, replaces the entire {@link UserInfoResponse} object.
  */
-public class UserInfoInUserInfoResponseContextUpdateStrategy implements  BiConsumer<ProfileRequestContext, JWT> {
+public class UserInfoInUserInfoResponseContextUpdateStrategy extends AbstractUserInfoTokenResponseLookupStrategy
+                    implements  BiConsumer<ProfileRequestContext, JWT> {
     
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(UserInfoInUserInfoResponseContextUpdateStrategy.class);
     
-    /** Strategy used to look up the {@link AccessTokenResponseContext} to set id_token on. */
-    @Nonnull private final Function<ProfileRequestContext, UserInfoResponseContext> 
-            userInfoResponseContextLookupStrategy;
     
     /**
      * 
@@ -59,23 +54,19 @@ public class UserInfoInUserInfoResponseContextUpdateStrategy implements  BiConsu
     public UserInfoInUserInfoResponseContextUpdateStrategy(
             @ParameterName(name="userInfoResponseContextLookupStrategy") final
         Function<ProfileRequestContext, UserInfoResponseContext> strategy) {
-        
-        userInfoResponseContextLookupStrategy = 
-                Constraint.isNotNull(strategy, "userInfoResponseContextLookupStrategy can not be null");
+        super(strategy);
     }
     
     /** Constructor.*/
     public UserInfoInUserInfoResponseContextUpdateStrategy() {
-        userInfoResponseContextLookupStrategy =
-                new ChildContextLookup<>(UserInfoResponseContext.class, true).compose(
-                        new InboundMessageContextLookup()); 
+        super();
     }
 
     @Override
     public void accept(final ProfileRequestContext profileRequestContext, final JWT token) {
         
         final UserInfoResponseContext context = 
-                userInfoResponseContextLookupStrategy.apply(profileRequestContext);  
+                getUserInfoResponseContextLookupStrategy().apply(profileRequestContext);  
         if (context != null) {
             // Create a new UserInfo element with the new JWT response
             context.setUserInfo(new UserInfoSuccessResponse(token));
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
index cd3c474..46274fb 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
@@ -438,17 +438,13 @@
     <bean id="DecryptIDTokenJWE" class="net.shibboleth.oidc.security.impl.DecryptJWE" scope="prototype"
         p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext">
         <property name="jwtTokenLookupStrategy">
-            <bean class="net.shibboleth.idp.profile.context.navigate.SpringExpressionContextLookupFunction"
-                c:_0="#{ T(org.opensaml.profile.context.ProfileRequestContext) }"
-                c:outputType="#{T(com.nimbusds.jwt.EncryptedJWT)}"
-                c:expression="#input.getInboundMessageContext().getSubcontext(T(net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext)).getTokenResponse().getOIDCTokens().getIDToken()" />
+            <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.context.navigate.EncryptedIDTokenLookupStrategy"/>
         </property>
         <property name="jwtUpdateStrategy">
             <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.context.navigate.IDTokenInAccessTokenUpdateStrategy" />
         </property>
     </bean>
 
-
     <!-- ID TOKEN Signature Validation -->
 
     <bean id="IDTokenSignatureValidation" parent="NestedWebFlowMessageHandlerAdaptor" scope="prototype"
@@ -708,16 +704,13 @@
     <bean id="DecryptUserInfoJWE" class="net.shibboleth.oidc.security.impl.DecryptJWE" scope="prototype"
         p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext">
         <property name="jwtTokenLookupStrategy">
-            <bean class="net.shibboleth.idp.profile.context.navigate.SpringExpressionContextLookupFunction"
-                c:_0="#{ T(org.opensaml.profile.context.ProfileRequestContext) }"
-                c:outputType="#{T(com.nimbusds.jwt.EncryptedJWT)}"
-                c:expression="#input.getInboundMessageContext().getSubcontext(T(net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext)).getUserInfo().getUserInfoJWT()" />
+            <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.context.navigate.EncryptedUserInfoJWTLookupStrategy"/>
         </property>
         <property name="jwtUpdateStrategy">
             <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.context.navigate.UserInfoInUserInfoResponseContextUpdateStrategy" />
         </property>
     </bean>
-
+    
     <!-- 
     Note, this is identical in setup to the id_token signature validation flow as they both use the same config and trust engine.
     the only difference is the location of the JWT to validate. Maybe they could be merged. Also, the populate steps may or may not

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


More information about the commits mailing list