[java-idp-oidc] branch main updated: Add JWT unit tests.

Scott Cantor cantor.2 at osu.edu
Thu Feb 3 13:58:26 UTC 2022


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

scantor 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=3301a9715b7479ea6ee8c2d60bbd639b28ee0b72

The following commit(s) were added to refs/heads/main by this push:
     new 3301a971 Add JWT unit tests.
3301a971 is described below

commit 3301a9715b7479ea6ee8c2d60bbd639b28ee0b72
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Feb 3 08:58:19 2022 -0500

    Add JWT unit tests.
---
 .../FormOutboundIntrospectionResponseMessage.java  |  5 +-
 .../FormOutboundRevokeTokenResponseMessage.java    |  6 +-
 .../oidc/op/profile/flow/RevocationFlowTest.java   | 95 ++++++++++++++++++++++
 3 files changed, 99 insertions(+), 7 deletions(-)

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 d2beb1bc..3149edf2 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
@@ -28,7 +28,6 @@ import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.oauth2.sdk.Scope;
-import com.nimbusds.oauth2.sdk.TokenIntrospectionRequest;
 import com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse;
 import com.nimbusds.oauth2.sdk.id.Audience;
 import com.nimbusds.oauth2.sdk.id.ClientID;
@@ -37,14 +36,14 @@ import com.nimbusds.oauth2.sdk.id.Subject;
 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.profile.impl.AbstractOIDCRequestAction;
 import net.shibboleth.idp.plugin.oidc.op.token.support.TokenClaimsSet;
+import net.shibboleth.idp.profile.AbstractProfileAction;
 
 /**
  * Action that forms outbound token introspection success message. Formed message is set to
  * {@link ProfileRequestContext#getOutboundMessageContext()}.
  */
-public class FormOutboundIntrospectionResponseMessage extends AbstractOIDCRequestAction<TokenIntrospectionRequest> {
+public class FormOutboundIntrospectionResponseMessage extends AbstractProfileAction {
 
     /** Class logger. */
     @Nonnull private Logger log = LoggerFactory.getLogger(FormOutboundIntrospectionResponseMessage.class);
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 a34e4f24..ffcf9343 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
@@ -21,16 +21,14 @@ import javax.annotation.Nonnull;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 
-import com.nimbusds.oauth2.sdk.TokenRevocationRequest;
-
 import net.shibboleth.idp.plugin.oidc.op.oauth2.messaging.impl.OAuth2RevocationSuccessResponse;
-import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractOIDCRequestAction;
+import net.shibboleth.idp.profile.AbstractProfileAction;
 
 /**
  * Action that forms outbound token revocation success message. Formed message is set to
  * {@link ProfileRequestContext#getOutboundMessageContext()}.
  */
-public class FormOutboundRevokeTokenResponseMessage extends AbstractOIDCRequestAction<TokenRevocationRequest> {
+public class FormOutboundRevokeTokenResponseMessage extends AbstractProfileAction {
 
     /** {@inheritDoc} */
     @Override
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java
index c6f5d53e..a8326f85 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java
@@ -20,8 +20,10 @@ package net.shibboleth.idp.plugin.oidc.op.profile.flow;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.security.NoSuchAlgorithmException;
+import java.time.Instant;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.opensaml.storage.StorageService;
@@ -31,18 +33,24 @@ import org.springframework.webflow.executor.FlowExecutionResult;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.nimbusds.jose.JOSEException;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jwt.SignedJWT;
 import com.nimbusds.oauth2.sdk.OAuth2Error;
 import com.nimbusds.oauth2.sdk.ParseException;
 import com.nimbusds.oauth2.sdk.Scope;
 import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
+import com.nimbusds.oauth2.sdk.id.ClientID;
 
 import net.shibboleth.idp.plugin.oidc.op.oauth2.messaging.impl.OAuth2RevocationSuccessResponse;
+import net.shibboleth.idp.plugin.oidc.op.token.support.AccessTokenClaimsSet;
+import net.shibboleth.oidc.security.credential.JWKCredential;
 import net.shibboleth.utilities.java.support.collection.Pair;
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
 import net.shibboleth.utilities.java.support.security.DataSealerException;
 
+// Checkstyle: ThrowsCount OFF
+
 /**
  * Unit tests for the OAuth2 revocation flow.
  */
@@ -58,6 +66,10 @@ public class RevocationFlowTest extends AbstractOidcClientAuthenticationFlowTest
 
     Scope scope = Scope.parse("openid profile email");
     
+    @Autowired
+    @Qualifier("testbed.DefaultRSSigningCredential")
+    private JWKCredential signingKey = null;
+    
     @Autowired
     @Qualifier("shibboleth.StorageService")
     StorageService storageService;
@@ -144,7 +156,90 @@ public class RevocationFlowTest extends AbstractOidcClientAuthenticationFlowTest
         return new Pair<>("invalid_client", "Client authentication failed");
     }
 
+    @Test
+    public void testSuccessJWTNoAudience() throws JOSEException, IOException {
+        storeMetadata(storageService, clientId, clientSecret, scope);
+        setBasicAuth(clientId, clientSecret);
+        setHttpFormRequest("POST", Map.of(
+                "token",
+                buildJWTToken(clientId, "sub", scope, null, signingKey.getPrivateKey(), "RS256").toJSONObject()
+                    .getAsString("access_token"),
+                "token_type",
+                "access_token"));
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        parseSuccessResponse(result, OAuth2RevocationSuccessResponse.class);
+    }
 
+    @Test
+    public void testSuccessJWTAudience() throws JOSEException, IOException {
+        storeMetadata(storageService, clientId, clientSecret, scope);
+        setBasicAuth(clientId, clientSecret);
+        setHttpFormRequest("POST", Map.of(
+                "token",
+                buildJWTToken("https://sp2.example.org", "sub", scope,
+                        List.of("https://sp.example.org", clientId),
+                        signingKey.getPrivateKey(), "RS256").toJSONObject()
+                    .getAsString("access_token"),
+                "token_type",
+                "access_token"));
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        parseSuccessResponse(result, OAuth2RevocationSuccessResponse.class);
+    }
+
+    @Test
+    public void testSuccessJWTExpired() throws JOSEException, IOException {
+        storeMetadata(storageService, clientId, clientSecret, scope);
+        setBasicAuth(clientId, clientSecret);
+        final AccessTokenClaimsSet claims = new AccessTokenClaimsSet.Builder()
+                .setJWTID(idGenerator)
+                .setClientID(new ClientID(clientId))
+                .setIssuer("https://op.example.org")
+                .setSubject(clientId)
+                .setIssuedAt(Instant.now().minusSeconds(300))
+                .setNotBefore(Instant.now().minusSeconds(300))
+                .setExpiresAt(Instant.now().minusSeconds(200))
+                .setAuthenticationTime(Instant.now())
+                .setScope(scope)
+                .build();
+        setHttpFormRequest("POST", Map.of(
+                "token",
+                buildJWTToken(claims, signingKey.getPrivateKey(), "RS256").toJSONObject().getAsString("access_token"),
+                "token_type",
+                "access_token"));
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        parseSuccessResponse(result, OAuth2RevocationSuccessResponse.class);
+    }
+    
+    @Test
+    public void testSuccessJWTNotAuthorized() throws JOSEException, IOException {
+        storeMetadata(storageService, clientId, clientSecret, scope);
+        setBasicAuth(clientId, clientSecret);
+        setHttpFormRequest("POST", Map.of(
+                "token",
+                buildJWTToken("https://sp3.example.org", "sub", scope,
+                        List.of("https://sp.example.org", "https://sp2.example.org"),
+                        signingKey.getPrivateKey(), "RS256").toJSONObject()
+                    .getAsString("access_token"),
+                "token_type",
+                "access_token"));
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        parseSuccessResponse(result, OAuth2RevocationSuccessResponse.class);
+    }
+    
+    @Test
+    public void testSuccessJWTWrongKey() throws JOSEException, IOException {
+        storeMetadata(storageService, clientId, clientSecret, scope);
+        setBasicAuth(clientId, clientSecret);
+        setHttpFormRequest("POST", Map.of(
+                "token",
+                buildJWTToken(clientId, "sub", scope, null, rsaPrivateKey, "RS256").toJSONObject()
+                    .getAsString("access_token"),
+                "token_type",
+                "access_token"));
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        parseSuccessResponse(result, OAuth2RevocationSuccessResponse.class);
+    }
+    
     @Test
     public void testFailedAuthentication() throws IOException, NoSuchAlgorithmException, URISyntaxException,
             DataSealerException, ComponentInitializationException {

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


More information about the commits mailing list