[java-idp-oidc] 02/02: JOIDC-171 - Support unregistered client policies in userinfo/token/introspection/revocation

Henri Mikkonen henri.mikkonen at iki.fi
Tue Sep 5 10:25:09 UTC 2023


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=fed0d6b98eabbcdd6f8bfaf398c3592948bac31f

commit fed0d6b98eabbcdd6f8bfaf398c3592948bac31f
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Tue Sep 5 13:24:17 2023 +0300

    JOIDC-171 - Support unregistered client policies in userinfo/token/introspection/revocation
    
    https://shibboleth.atlassian.net/browse/JOIDC-171
    
    Added client ID validation against policy to the introspection and revocation endpoints. The
    validation is done if metadata was not resolved to the requesting RP.
---
 .../oauth2/introspection/introspection-beans.xml   |  5 +++++
 .../oauth2/introspection/introspection-flow.xml    |  1 +
 .../flows/oauth2/revocation/revocation-beans.xml   |  5 +++++
 .../flows/oauth2/revocation/revocation-flow.xml    |  1 +
 .../op/profile/flow/IntrospectionFlowTest.java     | 24 ++++++++++++++++------
 .../oidc/op/profile/flow/RevocationFlowTest.java   |  9 ++++----
 .../shibboleth/idp/module/conf/relying-party.xml   |  4 ++--
 7 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-beans.xml
index 05a118a0..9e2fa45c 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-beans.xml
@@ -28,6 +28,11 @@
         class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.InitializeOutboundTokenMgmtResponseMessageContext"
         scope="prototype" />
 
+    <bean id="ValidateClientIDAgainstPolicy"
+        class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.ValidateClientIDAgainstPolicy"
+        p:clientIDLookupStrategy-ref="shibboleth.ClientIDLookupStrategy"
+        scope="prototype" />
+
     <bean id="ProcessTokenForIntrospection"
         class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.ProcessTokenForIntrospection" scope="prototype"
         p:dataSealer-ref="#{'%{idp.oidc.tokenSealer:shibboleth.oidc.TokenSealer}'.trim()}"
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-flow.xml
index 1bde90be..572bc538 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/introspection/introspection-flow.xml
@@ -35,6 +35,7 @@
     <!-- Authentication subflow happens here. -->
 
     <action-state id="ResumeAfterAuthentication">
+        <evaluate expression="ValidateClientIDAgainstPolicy" />
         <evaluate expression="ProcessTokenForIntrospection" />
         <evaluate expression="'proceed'" />
         
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-beans.xml
index f61bc55f..3e8909eb 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-beans.xml
@@ -28,6 +28,11 @@
         class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.InitializeOutboundTokenMgmtResponseMessageContext"
         scope="prototype" />
 
+    <bean id="ValidateClientIDAgainstPolicy"
+        class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.ValidateClientIDAgainstPolicy"
+        p:clientIDLookupStrategy-ref="shibboleth.ClientIDLookupStrategy"
+        scope="prototype" />
+
     <bean id="ProcessTokenForRevocation"
         class="net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl.ProcessTokenForRevocation" scope="prototype"
         p:dataSealer-ref="#{'%{idp.oidc.tokenSealer:shibboleth.oidc.TokenSealer}'.trim()}"
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-flow.xml
index bd3acae3..55864840 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/revocation/revocation-flow.xml
@@ -35,6 +35,7 @@
     <!-- Authentication subflow happens here. -->
 
     <action-state id="ResumeAfterAuthentication">
+        <evaluate expression="ValidateClientIDAgainstPolicy" />
         <evaluate expression="ProcessTokenForRevocation" />
         <evaluate expression="RevokeToken" />
         <evaluate expression="'proceed'" />
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java
index 37140ec9..76874fee 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java
@@ -127,14 +127,26 @@ public class IntrospectionFlowTest extends AbstractOidcClientAuthenticationFlowT
                 "token_type",
                 "access_token"));
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        final TokenIntrospectionSuccessResponse resp =
-                parseSuccessResponse(result, TokenIntrospectionSuccessResponse.class);
-        Assert.assertFalse(resp.isActive());
+        assertErrorCode(result, OAuth2Error.ACCESS_DENIED_CODE);
     }
 
     @Test
-    public void testSuccessUnverified() throws IOException, NoSuchAlgorithmException, URISyntaxException,
-            DataSealerException, ComponentInitializationException {
+    public void testFailureUnverified_nonCompliantPolicy() throws IOException, NoSuchAlgorithmException,
+            URISyntaxException, DataSealerException, ComponentInitializationException {
+        setBasicAuth(clientId, clientSecret);
+        setHttpFormRequest("POST", Map.of(
+                "token",
+                buildToken(clientId, "sub", Scope.parse("openid")).toJSONObject().getAsString("access_token"),
+                "token_type",
+                "access_token"));
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertErrorCode(result, OAuth2Error.ACCESS_DENIED_CODE);
+    }
+
+    @Test
+    public void testSuccessUnverified_compliantPolicy() throws IOException, NoSuchAlgorithmException,
+            URISyntaxException, DataSealerException, ComponentInitializationException {
+        final String clientId = "policyAcceptedClient1";
         setBasicAuth(clientId, clientSecret);
         setHttpFormRequest("POST", Map.of(
                 "token",
@@ -149,7 +161,7 @@ public class IntrospectionFlowTest extends AbstractOidcClientAuthenticationFlowT
         Assert.assertEquals(resp.getScope(), Scope.parse("openid"));
         Assert.assertNull(resp.getAudience());
     }
-    
+
     @Test
     public void testSuccess() throws IOException, NoSuchAlgorithmException, URISyntaxException, DataSealerException,
             ComponentInitializationException {
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 e7711640..2f70d031 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
@@ -87,13 +87,13 @@ public class RevocationFlowTest extends AbstractOidcClientAuthenticationFlowTest
     }
 
     @Test
-    public void testUntrustedClient() throws IOException, NoSuchAlgorithmException, URISyntaxException,
-        DataSealerException, ComponentInitializationException {
-        setBasicAuth(clientId, clientSecret + "bad");
+    public void testUntrustedClient_nonCompliantClientID() throws IOException, NoSuchAlgorithmException,
+        URISyntaxException, DataSealerException, ComponentInitializationException {
+        setBasicAuth(clientId, clientSecret);
         setHttpFormRequest("POST", Collections.singletonMap("token", super.buildToken(clientId, "sub", 
                 Scope.parse("openid")).toJSONObject().getAsString("access_token")));
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
+        assertErrorCode(result, OAuth2Error.ACCESS_DENIED_CODE);
     }
     
     @Test
@@ -110,6 +110,7 @@ public class RevocationFlowTest extends AbstractOidcClientAuthenticationFlowTest
     @Test
     public void testSuccessUnverified() throws IOException, NoSuchAlgorithmException, URISyntaxException,
         DataSealerException, ComponentInitializationException {
+        final String clientId = "policyAcceptedClient1";
         setBasicAuth(clientId, clientSecret);
         setHttpFormRequest("POST", Collections.singletonMap("token", super.buildToken(clientId, "sub", 
                 Scope.parse("openid")).toJSONObject().getAsString("access_token")));
diff --git a/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml b/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml
index 55a74f2a..7243f177 100644
--- a/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml
+++ b/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml
@@ -43,8 +43,8 @@
                 <bean parent="OAUTH2.Token" p:unregisteredClientPolicyLookupStrategy-ref="shibboleth.oidc.DefaultUnregisteredPolicyLookupStrategy"/>
                 <bean parent="OAUTH2.TokenAudience" p:encryptionOptional="true" /> 
                 <bean parent="OIDC.UserInfo" p:unregisteredClientPolicyLookupStrategy-ref="shibboleth.oidc.DefaultUnregisteredPolicyLookupStrategy"/>
-                <ref bean="OAUTH2.Introspection" />
-                <ref bean="OAUTH2.Revocation" />
+                <bean parent="OAUTH2.Introspection" p:unregisteredClientPolicyLookupStrategy-ref="shibboleth.oidc.DefaultUnregisteredPolicyLookupStrategy"/>
+                <bean parent="OAUTH2.Revocation" p:unregisteredClientPolicyLookupStrategy-ref="shibboleth.oidc.DefaultUnregisteredPolicyLookupStrategy"/>
             </list>
         </property>
     </bean>

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


More information about the commits mailing list