[java-plugin-shibd-oidc] branch main updated: Add test for signed and encrypted ID_Token

Codeberg noreply at shibboleth.net
Wed Nov 19 17:16:11 UTC 2025


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

codeberg pushed a commit to branch main
in repository java-plugin-shibd-oidc.

View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd-oidc/commit/5a7bfd51fb393e25024c720820ce48a42a9446ec

The following commit(s) were added to refs/heads/main by this push:
     new 5a7bfd5  Add test for signed and encrypted ID_Token
5a7bfd5 is described below

commit 5a7bfd51fb393e25024c720820ce48a42a9446ec
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed Nov 19 17:16:01 2025 +0000

    Add test for signed and encrypted ID_Token
    
     - Added a new encryption credential for the OP which is of course not
    used for the new test, that would be to encrypt requests to the OP
    (which there are no tests for yet).
---
 .../sp/oidc/flows/OIDCTokenConsumerFlowTest.java   | 82 +++++++++++++++++++---
 .../module/credentials/op/op-encryption-rsa.jwk    | 14 ++++
 .../net/shibboleth/sp/oidc-test-beans.xml          |  3 +
 3 files changed, 90 insertions(+), 9 deletions(-)

diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
index a088c9e..7b46b36 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
@@ -55,7 +55,9 @@ import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.nimbusds.jose.EncryptionMethod;
 import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWEAlgorithm;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jwt.JWT;
 import com.nimbusds.jwt.JWTClaimsSet;
@@ -108,6 +110,9 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
     /** Dummy signing key of the dummy OP we are testing against. */
     @Autowired @Qualifier("dummy.op.signing.Credential") protected JWKCredential opSigningCredential;
     
+    /** Dummy encryption key of the RP/SP. */
+    @Autowired @Qualifier("dummy.sp.encryption.Credential") protected JWKCredential rpEncryptionCredential;
+    
     /** The mocked HttpClient to use when responding to Token and UserInfo requests.*/
     private HttpClient httpClient;
 
@@ -139,9 +144,40 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
      */
     @SuppressWarnings({ "unchecked", "rawtypes" })
     @Test
-    public void testSuccess_PlainUserInfo() throws Exception {
+    public void testSuccess_SignedIDToken_PlainUserInfo() throws Exception {
+        
+        mockOIDCEndpoints(constructSuccessfulTokenResponseSigned(Instant.now().plusSeconds(3600), Instant.now()), 
+                constructJSONUserInfoResponse());
+
+        final AuthenticationSuccessResponse response = 
+                buildOIDCAuthorizationCodeResponse(TestConstants.RESPONSE_URL, ResponseMode.QUERY, TestConstants.STATE_STRING);        
+        final DDF input = buildRemotedQueryStringResponse(response);
+        
+        // Add cookies
+        input.addmember("http.headers.Cookie")
+            .unsafe_string(TestConstants.COOKIE_HEADER.getBytes("UTF-8"));
+        
+        setApplicationRequest("test-oidc-application-with-ro", input);
+
+        final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, TestConstants.FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        final DDF output = assertOutputMessageSuccess(result);
+        assert output != null;
+        System.out.println("testSuccess output: " + output.toString());
+        validateOutputMessage(result, CollectionSupport.singleton("mail"), TestConstants.RESOURCE_URL);
+    }
+    
+    /**
+     * Test successful flow.
+     * 
+     * @throws IOException 
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Test
+    public void testSuccess_SignedEncryptedIDToken_PlainUserInfo() throws Exception {
         
-        mockOIDCEndpoints(constructSuccessfulTokenResponse(Instant.now().plusSeconds(3600), Instant.now()), 
+        mockOIDCEndpoints(constructSuccessfulTokenResponseSignedAndEncrypted(Instant.now().plusSeconds(3600), Instant.now()), 
                 constructJSONUserInfoResponse());
 
         final AuthenticationSuccessResponse response = 
@@ -169,10 +205,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
      * @throws IOException 
      */
     @Test
-    public void testSuccess_JWTUserInfo() throws Exception {
+    public void testSuccess_SignedIDToken_JWTUserInfo() throws Exception {
         
-        mockOIDCEndpoints(constructSuccessfulTokenResponse(Instant.now().plusSeconds(3600), Instant.now()), 
-                constructJWTUserInfoResponse());     
+        mockOIDCEndpoints(constructSuccessfulTokenResponseSigned(Instant.now().plusSeconds(3600), Instant.now()), 
+                constructJWTUserInfoResponseSigned());     
 
         final AuthenticationSuccessResponse response = 
                 buildOIDCAuthorizationCodeResponse(TestConstants.RESPONSE_URL, ResponseMode.QUERY, TestConstants.STATE_STRING);        
@@ -216,7 +252,7 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
     }
     
     /**
-     * Construct a successful OIDC token response.
+     * Construct a successful OIDC token response with signed id_token.
      * 
      * @param expiry expiry time
      * @param issuedAt issue time
@@ -224,7 +260,7 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
      * @throws ParseException 
      * @throws JOSEException 
      */
-    private OIDCTokenResponse constructSuccessfulTokenResponse(
+    private OIDCTokenResponse constructSuccessfulTokenResponseSigned(
             @Nonnull final Instant expiry, @Nonnull final Instant issuedAt) throws JOSEException, ParseException {
 
          final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
@@ -242,6 +278,34 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
          return new OIDCTokenResponse((new OIDCTokens(signedIdToken, accessToken, refreshToken)));
     }
     
+    /**
+     * Construct a successful OIDC token response with a signed and encrypted id_token.
+     * 
+     * @param expiry expiry time
+     * @param issuedAt issue time
+     * @return the tokens
+     * @throws ParseException 
+     * @throws JOSEException 
+     */
+    private OIDCTokenResponse constructSuccessfulTokenResponseSignedAndEncrypted(
+            @Nonnull final Instant expiry, @Nonnull final Instant issuedAt) throws JOSEException, ParseException {
+
+         final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
+                 .subject("fake-user")
+                 .issuer("https://op.example.org")
+                 .audience("mock-client-id")
+                 .expirationTime(Date.from(expiry))
+                     .issueTime(Date.from(issuedAt))
+                     .build();
+         final JWT encryptedIdToken = 
+                 TestTokenHelper.createJWT(claimsSet, JWSAlgorithm.RS256, JWEAlgorithm.RSA_OAEP_256, 
+                         EncryptionMethod.A128CBC_HS256, opSigningCredential, rpEncryptionCredential);
+         
+         final AccessToken accessToken = new BearerAccessToken("fake-access-token-value", 3600, null);
+         final RefreshToken refreshToken = new RefreshToken("fake-refresh-token-value");
+         return new OIDCTokenResponse((new OIDCTokens(encryptedIdToken, accessToken, refreshToken)));
+    }
+    
     /**
      * Construct a successful OIDC user info response in JSON format. application/json.
      * 
@@ -255,13 +319,13 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
     }
     
     /**
-     * Construct a successful OIDC user info response in JWT format.
+     * Construct a successful OIDC user info response in JWT format, signed.
      * 
      * @return the user info response
      * @throws ParseException 
      * @throws JOSEException 
      */
-    private UserInfoSuccessResponse constructJWTUserInfoResponse() throws JOSEException, ParseException {
+    private UserInfoSuccessResponse constructJWTUserInfoResponseSigned() throws JOSEException, ParseException {
         final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                 .subject("fake-user")
                 .issuer("https://op.example.org")
diff --git a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/credentials/op/op-encryption-rsa.jwk b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/credentials/op/op-encryption-rsa.jwk
new file mode 100644
index 0000000..ebf77b6
--- /dev/null
+++ b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/credentials/op/op-encryption-rsa.jwk
@@ -0,0 +1,14 @@
+{
+  "kty": "RSA",
+  "use": "enc",
+  "alg": "RSA-OAEP-256",
+  "kid": "op-encryption-key",
+  "d": "wbLiGv3ndXOvjH8hEfmcNtIZOgXF4Y_n3NvBJQpxg7P_azzeNXccHNYdkj1iv2B7aiFOh2Q2gcMvFzEa7H-s-DhYBmBN2UeRy3FrkfpGtNl8jnyomyUJr3DrpcPIPo1zQ19Z5CPiHHoCdtWnmWwCuO69gwTU9fbIicAa4R2F6bjGOqR2zm91TJCwlkME2vPXW_Pp3ptdvH7X-_YcFxr6dXB1lCA8oBPW6CBBQENkfHzC82A7AzO14OZkr-gWOfxgFllCjNstv1erWVXAQWliM8feqotHUn2qmtMI-X7F78ts2LAt9J0hPLD9uPQQLApdPyg7CKLQFZyZCWcQB4LCcQ",
+  "n": "1lxRd9jc3GkVoeTpO1-HB-UYPj6yynBU2jvauRpusR93dp7hUVg-wB4h0tj1zSR60LGWCn2PvDCySQFgCy537t6uMEd3cF2yyhTz9mlF-YipE2OT2782ZqdBnYo8kJTIlZ3yFAON8nYYl5PRYNSZXKvV9GzDXvasZesqoPNbEiPlsTUqLDoxGdxhXIqAY6_AVU1eHamIBEKNlzbvIRFpF5yK2iCx5FwupphVJxZagEoIFH9vaU4KcvX5eGThL39SfwrCXI3OC5vYMBN_umtJm8BTyvroYSloqPhYxxLSHXLYVk5hcRx-0Zd5-bwp0g6RoUlD4itzocJkPglPSE7chQ",
+  "e": "AQAB",
+  "p": "3OofCyEiAigD_VYGa-FzJIuXmY-GkWYJ9A2WU77EUKRJiLf8uVUhSE3ehYCw7KG0jLZKiwle8Zcrl5nkX0hnlVL8xwueJfNdz6jGKRpo339sXmqVncnLKj67Avzg-fgccki91E0TkaNCZzbRPuH67xCGghuGBxdHRBfHIv_SZPc",
+  "q": "-Ge6zH-p5k2epkp0rV-8vtsbvrMm-TZduPGtpP4nL5WrdVgDSW4mRoWVX0DXOJPlj6ILZkmz4vDv1CfdxLDNuPnMwSN4Lb8q-9l7z5mEnu5XTW52Zt9ZI1oMNgF-bj3riOCjE4s3iUfGlM1Rwy8t9t89hE0USy8TS9YYSXFVd2M",
+  "dp": "gIeuvBjw4nRJrfGJFuc6yL52259H2fyWOepV1i-dpJWROvxhC6teC-VSXDY9uc9zbpL41-AB32nmsPOWjWFg8t4vt9cokkgAArvdXzjAX5iRgnVcy0sG63NH9zsN4iHa2xs7ZvPZONjV35tjLsTn7IOe3sAIwMNocVOsRs60qI0",
+  "dq": "55dmK_S2RTaGvEjcgSuqAFKtilzi8CQEu0Hvf81IYW_sHAoDfnmIi-VNPzJntaMFuqT8ddAvO10gbC8C7rdcBaI3iLX1_MinXYkFiqZ5Y-eYU2OyVfTT2UbB7bP02Pk32DR_NeBs1buqY98M5Kne87RsWSW3zuTD28due0KDyTs",
+  "qi": "Y8OhHB2nLmxwviyLqC1Qr3m-EtUQ7dKUB1nr9VejDTPe7A9m92Nw0pPbHNcY-eDwwXWoHs4WCXNaSw0JM-E1vOUjXy5QZ2ob6fQsPXFmJluroirOJPTct0-QgppuoZudo5a90lvfuWKF3TqZFkSdkI3frXX5xeioEdXV9L4GuVY"
+}
\ No newline at end of file
diff --git a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/sp/oidc-test-beans.xml b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/sp/oidc-test-beans.xml
index 4a969c3..32ee7bf 100644
--- a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/sp/oidc-test-beans.xml
+++ b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/sp/oidc-test-beans.xml
@@ -30,6 +30,9 @@
 
     <bean id="dummy.op.signing.Credential" parent="shibboleth.oidc.JWKCredential"
         p:resource="%{idp.home}/credentials/op/op-signing-rsa.jwk" p:throwIfNull="false" />
+        
+     <bean id="dummy.sp.encryption.Credential" parent="shibboleth.oidc.JWKCredential"
+        p:resource="%{idp.home}/credentials/sp/sp-encryption-rsa.jwk" p:throwIfNull="false" />
 
     <!-- Mockito mock for HttpClient -->
     <bean id="Mock.HttpClient"

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


More information about the commits mailing list