[java-idp-oidc] 01/03: JOIDC-222 - Support for OpenID Federation

Henri Mikkonen henri.mikkonen at iki.fi
Fri May 9 13:10:18 UTC 2025


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

hjmikkon pushed a commit to branch dev/JOIDC-222
in repository java-idp-oidc.

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

commit a721e204227e28a41f3de50744a70caa1ee3cced
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri May 9 15:33:08 2025 +0300

    JOIDC-222 - Support for OpenID Federation
    
    https://shibboleth.atlassian.net/browse/JOIDC-222
    
    - Improve logic for initiating automatic registration in authorize and PAR -flows
      - Solely start trust chain resolution if:
        - request object is not a plain one
        - client_id in the request object matches with the one in the request query
        - PAR request must be authenticated via request object or private_key_jwt
      - Customizable via idp.oidfed.par.customAutomaticRegistrationCondition and idp.oidfed.authorize.customAutomaticRegistrationCondition
    - Improve federation-specific request object validation to authorize and PAR -flows
      - included claim validator for the mandatory client_id -claim
---
 .../pushed-authorization-beans.xml                 | 42 +++++++++-
 .../idp/flows/oidc/authorize/authorize-beans.xml   | 34 ++++++--
 .../AuthorizeFlowAutomaticRegistrationTest.java    | 93 +++++++++++++++++++++
 ...shedAuthorizeFlowAutomaticRegistrationTest.java | 94 +++++++++++++++++++++-
 4 files changed, 254 insertions(+), 9 deletions(-)

diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-beans.xml
index 8b499cd4..e0315e28 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oauth2/pushed-authorization/pushed-authorization-beans.xml
@@ -318,6 +318,14 @@
             p:requiredClaims="exp" />
         <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ProhibitedClaimsValidator"
             p:prohibitedClaims="sub" />
+        <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ExactMatchClaimsValidator"
+            p:claimName="client_id">
+            <property name="valueToMatchLookupStrategy">
+                <bean parent="shibboleth.BiFunctions.Expression"
+                    c:expression="#custom.apply(#input1.getInboundMessageContext()) == null ? null : #custom.apply(#input1.getInboundMessageContext()).toString()"
+                    p:customObject-ref="shibboleth.ClientIDLookupStrategy" />
+            </property>
+        </bean>
     </util:list>
 
     <bean id="DefaultParUseOnlyRequestObjectCondition" parent="shibboleth.BiConditions.Expression"
@@ -431,6 +439,38 @@
         </property>
     </bean>
 
-    <alias alias="AutomaticRegistrationCondition" name="%{idp.oidfed.par.automaticRegistrationCondition:shibboleth.Conditions.FALSE}" />
+    <alias alias="AutomaticRegistrationCondition" name="%{idp.oidfed.par.customAutomaticRegistrationCondition:DefaultAutomaticRegistrationCondition}" />
+
+    <bean id="DefaultAutomaticRegistrationCondition" parent="shibboleth.Conditions.AND">
+        <constructor-arg>
+            <list>
+                <ref bean="%{idp.oidfed.par.automaticRegistrationCondition:shibboleth.Conditions.FALSE}"/>
+                <bean parent="shibboleth.Conditions.Expression"
+                    c:expression="#input.ensureInboundMessageContext().getMessage() instanceof T(com.nimbusds.oauth2.sdk.PushedAuthorizationRequest)" />
+                <bean parent="shibboleth.Conditions.Expression"
+                    c:expression="!(#input.ensureInboundMessageContext().getMessage().getAuthorizationRequest().getRequestObject() instanceof T(com.nimbusds.jwt.PlainJWT))" />
+                <bean parent="shibboleth.Conditions.OR">
+                    <constructor-arg>
+                        <bean parent="shibboleth.Conditions.Expression"
+                            c:expression="#input.ensureInboundMessageContext().getMessage().getAuthorizationRequest().specifiesRequestObject()" />
+                    </constructor-arg>
+                    <constructor-arg>
+                        <bean parent="shibboleth.Conditions.Expression"
+                            c:expression="#input.ensureInboundMessageContext().getMessage().getClientAuthentication() != null and #input.ensureInboundMessageContext().getMessage().getClientAuthentication().getMethod().equals(T(com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod).PRIVATE_KEY_JWT)" />
+                    </constructor-arg>
+                </bean>
+                <bean parent="shibboleth.Conditions.OR">
+                    <constructor-arg>
+                        <list>
+                            <bean parent="shibboleth.Conditions.Expression"
+                                c:expression="!(#input.ensureInboundMessageContext().getMessage().getAuthorizationRequest().getRequestObject() instanceof T(com.nimbusds.jwt.SignedJWT))" />
+                            <bean parent="shibboleth.Conditions.Expression"
+                                c:expression="#input.ensureInboundMessageContext().getMessage().getAuthorizationRequest().getClientID().getValue().equals(#input.ensureInboundMessageContext().getMessage().getAuthorizationRequest().getRequestObject().getJWTClaimsSet().getClaim('client_id'))" />
+                        </list>
+                    </constructor-arg>
+                </bean>
+            </list>
+        </constructor-arg>
+    </bean>
 
 </beans>
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml
index 5acb6b53..7d1b81d6 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml
@@ -468,6 +468,14 @@
             p:requiredClaims="exp" />
         <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ProhibitedClaimsValidator"
             p:prohibitedClaims="sub" />
+        <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ExactMatchClaimsValidator"
+            p:claimName="client_id">
+            <property name="valueToMatchLookupStrategy">
+                <bean parent="shibboleth.BiFunctions.Expression"
+                    c:expression="#custom.apply(#input1.getInboundMessageContext()) == null ? null : #custom.apply(#input1.getInboundMessageContext()).toString()"
+                    p:customObject-ref="shibboleth.ClientIDLookupStrategy" />
+            </property>
+        </bean>
     </util:list>
 
     <bean id="DefaultRequestRedirectURILookupFunction"
@@ -1199,13 +1207,27 @@
         </constructor-arg>
     </bean>
 
-    <bean id="AutomaticRegistrationCondition" parent="shibboleth.Conditions.AND">
-        <constructor-arg>
-            <ref bean="%{idp.oidfed.authorize.automaticRegistrationCondition:shibboleth.Conditions.FALSE}"/>
-        </constructor-arg>
+    <alias alias="AutomaticRegistrationCondition" name="%{idp.oidfed.authorize.customAutomaticRegistrationCondition:DefaultAutomaticRegistrationCondition}" />
+
+    <bean id="DefaultAutomaticRegistrationCondition" parent="shibboleth.Conditions.AND">
         <constructor-arg>
-            <bean parent="shibboleth.Conditions.Expression"
-                c:expression="#input.ensureInboundMessageContext().getMessage() instanceof T(com.nimbusds.oauth2.sdk.AuthorizationRequest) and #input.ensureInboundMessageContext().getMessage().specifiesRequestObject()" />
+            <list>
+                <ref bean="%{idp.oidfed.authorize.automaticRegistrationCondition:shibboleth.Conditions.FALSE}"/>
+                <bean parent="shibboleth.Conditions.Expression"
+                    c:expression="#input.ensureInboundMessageContext().getMessage() instanceof T(com.nimbusds.oauth2.sdk.AuthorizationRequest) and #input.ensureInboundMessageContext().getMessage().specifiesRequestObject()" />
+                <bean parent="shibboleth.Conditions.Expression"
+                    c:expression="!(#input.ensureInboundMessageContext().getMessage().getRequestObject() instanceof T(com.nimbusds.jwt.PlainJWT))" />
+                <bean parent="shibboleth.Conditions.OR">
+                    <constructor-arg>
+                        <list>
+                            <bean parent="shibboleth.Conditions.Expression"
+                                c:expression="!(#input.ensureInboundMessageContext().getMessage().getRequestObject() instanceof T(com.nimbusds.jwt.SignedJWT))" />
+                            <bean parent="shibboleth.Conditions.Expression"
+                                c:expression="#input.ensureInboundMessageContext().getMessage().getClientID().getValue().equals(#input.ensureInboundMessageContext().getMessage().getRequestObject().getJWTClaimsSet().getClaim('client_id'))" />
+                        </list>
+                    </constructor-arg>
+                </bean>
+            </list>
         </constructor-arg>
     </bean>
 
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
index 592d071c..8bb080d9 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
@@ -85,6 +85,7 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
         final FlowExecutionResult result =
                 launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
                         "iss", clientId,
+                        "client_id", clientId,
                         "aud", issuer,
                         "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
                         "jti", UUID.randomUUID(),
@@ -100,6 +101,24 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
         Assert.assertEquals(unwrapTrustChainFromAuthorizeCode(successResponse), List.of(clientId, anchorId));
     }
 
+    @Test
+    public void testWithValidTrustChain_signedRequestObject_nonMatchingClientId()
+            throws IOException, UnsupportedOperationException, URISyntaxException {
+        final String clientId = uniqueClientId();
+        configureMockHttpClient(clientId);
+        final FlowExecutionResult result =
+                launchAuthenticationRequest(clientId + "2", "openid profile", signedRequestObject(Map.of(
+                        "iss", clientId,
+                        "client_id", clientId,
+                        "aud", issuer,
+                        "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                        "jti", UUID.randomUUID(),
+                        "response_type", "code",
+                        "scope", "openid profile",
+                        "redirect_uri", redirectUri)));
+        Assert.assertEquals(result.getOutcome().getId(), "ErrorView");
+    }
+
     @Test
     public void testWithValidTrustChain_signedRequestObject_missingJti()
             throws IOException, UnsupportedOperationException, URISyntaxException {
@@ -108,6 +127,7 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
         final FlowExecutionResult result =
                 launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
                         "iss", clientId,
+                        "client_id", clientId,
                         "aud", issuer,
                         "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
                         "response_type", "code",
@@ -124,6 +144,7 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
         final FlowExecutionResult result =
                 launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
                         "iss", clientId,
+                        "client_id", clientId,
                         "aud", issuer,
                         "jti", UUID.randomUUID(),
                         "response_type", "code",
@@ -132,6 +153,76 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
         assertErrorCode(result, "invalid_request_object");
     }
 
+    @Test
+    public void testWithValidTrustChain_signedRequestObject_invalidIss()
+            throws IOException, UnsupportedOperationException, URISyntaxException {
+        final String clientId = uniqueClientId();
+        configureMockHttpClient(clientId);
+        final FlowExecutionResult result =
+                launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
+                        "iss", clientId + "2",
+                        "client_id", clientId,
+                        "aud", issuer,
+                        "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                        "jti", UUID.randomUUID(),
+                        "response_type", "code",
+                        "scope", "openid profile",
+                        "redirect_uri", redirectUri)));
+        assertErrorCode(result, "invalid_request_object");
+    }
+
+    @Test
+    public void testWithValidTrustChain_signedRequestObject_missingIss()
+            throws IOException, UnsupportedOperationException, URISyntaxException {
+        final String clientId = uniqueClientId();
+        configureMockHttpClient(clientId);
+        final FlowExecutionResult result =
+                launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
+                        "client_id", clientId,
+                        "aud", issuer,
+                        "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                        "jti", UUID.randomUUID(),
+                        "response_type", "code",
+                        "scope", "openid profile",
+                        "redirect_uri", redirectUri)));
+        assertErrorCode(result, "invalid_request_object");
+    }
+
+    @Test
+    public void testWithValidTrustChain_signedRequestObject_invalidClientId()
+            throws IOException, UnsupportedOperationException, URISyntaxException {
+        final String clientId = uniqueClientId();
+        configureMockHttpClient(clientId);
+        final FlowExecutionResult result =
+                launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
+                        "iss", clientId,
+                        "client_id", clientId + "2",
+                        "aud", issuer,
+                        "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                        "jti", UUID.randomUUID(),
+                        "response_type", "code",
+                        "scope", "openid profile",
+                        "redirect_uri", redirectUri)));
+        Assert.assertEquals(result.getOutcome().getId(), "ErrorView");
+    }
+
+    @Test
+    public void testWithValidTrustChain_signedRequestObject_missingClientId()
+            throws IOException, UnsupportedOperationException, URISyntaxException {
+        final String clientId = uniqueClientId();
+        configureMockHttpClient(clientId);
+        final FlowExecutionResult result =
+                launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
+                        "iss", clientId,
+                        "aud", issuer,
+                        "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                        "jti", UUID.randomUUID(),
+                        "response_type", "code",
+                        "scope", "openid profile",
+                        "redirect_uri", redirectUri)));
+        Assert.assertEquals(result.getOutcome().getId(), "ErrorView");
+    }
+
     @Test
     public void testWithValidTrustChain_signedRequestObject_containsForbiddenSub()
             throws IOException, UnsupportedOperationException, URISyntaxException {
@@ -140,6 +231,7 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
         final FlowExecutionResult result =
                 launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
                         "iss", clientId,
+                        "client_id", clientId,
                         "sub", "mockValue",
                         "aud", issuer,
                         "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
@@ -158,6 +250,7 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
         final FlowExecutionResult result =
                 launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
                         "iss", clientId,
+                        "client_id", clientId,
                         "aud", List.of(issuer, "https://another.example.org"),
                         "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
                         "jti", UUID.randomUUID(),
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/PushedAuthorizeFlowAutomaticRegistrationTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/PushedAuthorizeFlowAutomaticRegistrationTest.java
index ddf5dd40..6747f192 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/PushedAuthorizeFlowAutomaticRegistrationTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/PushedAuthorizeFlowAutomaticRegistrationTest.java
@@ -81,7 +81,7 @@ public class PushedAuthorizeFlowAutomaticRegistrationTest extends AbstractFedera
         setHttpFormRequest("POST", createRequestParameters(clientId));
         final FlowExecutionResult result =
                 flowExecutor.launchExecution(PushedAuthorizeFlowTest.FLOW_ID, null, externalContext);
-        assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
+        assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
     }
 
     @Test
@@ -132,6 +132,96 @@ public class PushedAuthorizeFlowAutomaticRegistrationTest extends AbstractFedera
         assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
     }
 
+    @Test
+    public void testWithPublicClientWithSignedRequestObject_missingIss() throws Exception {
+        final OIDCClientMetadata metadata = new OIDCClientMetadata();
+        metadata.setRedirectionURI(new URI(redirectUri));
+        metadata.setResponseTypes(Set.of(ResponseType.CODE));
+        metadata.setJWKSet(new JWKSet(rpKey.toPublicJWK()));
+        metadata.setTokenEndpointAuthMethod(ClientAuthenticationMethod.NONE);
+        final String clientId = uniqueClientId();
+        configureMockHttpClient(clientId, metadata);
+        setHttpFormRequest("POST", createRequestParameters(clientId, "openid", "code", signedRequestObject(Map.of(
+                "client_id", clientId,
+                "aud", issuer,
+                "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                "jti", UUID.randomUUID(),
+                "response_type", "code",
+                "scope", "openid",
+                "redirect_uri", redirectUri)).serialize()));
+        final FlowExecutionResult result =
+                flowExecutor.launchExecution(PushedAuthorizeFlowTest.FLOW_ID, null, externalContext);
+        assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
+    }
+
+    @Test
+    public void testWithPublicClientWithSignedRequestObject_invalidIss() throws Exception {
+        final OIDCClientMetadata metadata = new OIDCClientMetadata();
+        metadata.setRedirectionURI(new URI(redirectUri));
+        metadata.setResponseTypes(Set.of(ResponseType.CODE));
+        metadata.setJWKSet(new JWKSet(rpKey.toPublicJWK()));
+        metadata.setTokenEndpointAuthMethod(ClientAuthenticationMethod.NONE);
+        final String clientId = uniqueClientId();
+        configureMockHttpClient(clientId, metadata);
+        setHttpFormRequest("POST", createRequestParameters(clientId, "openid", "code", signedRequestObject(Map.of(
+                "client_id", clientId,
+                "iss", clientId + "2",
+                "aud", issuer,
+                "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                "jti", UUID.randomUUID(),
+                "response_type", "code",
+                "scope", "openid",
+                "redirect_uri", redirectUri)).serialize()));
+        final FlowExecutionResult result =
+                flowExecutor.launchExecution(PushedAuthorizeFlowTest.FLOW_ID, null, externalContext);
+        assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
+    }
+
+    @Test
+    public void testWithPublicClientWithSignedRequestObject_missingClientId() throws Exception {
+        final OIDCClientMetadata metadata = new OIDCClientMetadata();
+        metadata.setRedirectionURI(new URI(redirectUri));
+        metadata.setResponseTypes(Set.of(ResponseType.CODE));
+        metadata.setJWKSet(new JWKSet(rpKey.toPublicJWK()));
+        metadata.setTokenEndpointAuthMethod(ClientAuthenticationMethod.NONE);
+        final String clientId = uniqueClientId();
+        configureMockHttpClient(clientId, metadata);
+        setHttpFormRequest("POST", createRequestParameters(clientId, "openid", "code", signedRequestObject(Map.of(
+                "iss", clientId,
+                "aud", issuer,
+                "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                "jti", UUID.randomUUID(),
+                "response_type", "code",
+                "scope", "openid",
+                "redirect_uri", redirectUri)).serialize()));
+        final FlowExecutionResult result =
+                flowExecutor.launchExecution(PushedAuthorizeFlowTest.FLOW_ID, null, externalContext);
+        assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
+    }
+
+    @Test
+    public void testWithPublicClientWithSignedRequestObject_invalidClientId() throws Exception {
+        final OIDCClientMetadata metadata = new OIDCClientMetadata();
+        metadata.setRedirectionURI(new URI(redirectUri));
+        metadata.setResponseTypes(Set.of(ResponseType.CODE));
+        metadata.setJWKSet(new JWKSet(rpKey.toPublicJWK()));
+        metadata.setTokenEndpointAuthMethod(ClientAuthenticationMethod.NONE);
+        final String clientId = uniqueClientId();
+        configureMockHttpClient(clientId, metadata);
+        setHttpFormRequest("POST", createRequestParameters(clientId, "openid", "code", signedRequestObject(Map.of(
+                "client_id", clientId + "2",
+                "iss", clientId,
+                "aud", issuer,
+                "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                "jti", UUID.randomUUID(),
+                "response_type", "code",
+                "scope", "openid",
+                "redirect_uri", redirectUri)).serialize()));
+        final FlowExecutionResult result =
+                flowExecutor.launchExecution(PushedAuthorizeFlowTest.FLOW_ID, null, externalContext);
+        assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
+    }
+
     @Test
     public void testWithPublicClientWithSignedRequestObject_missingExp() throws Exception {
         final OIDCClientMetadata metadata = new OIDCClientMetadata();
@@ -221,7 +311,7 @@ public class PushedAuthorizeFlowAutomaticRegistrationTest extends AbstractFedera
                 "redirect_uri", redirectUri)).serialize()));
         final FlowExecutionResult result =
                 flowExecutor.launchExecution(PushedAuthorizeFlowTest.FLOW_ID, null, externalContext);
-        assertErrorCode(result, OAuth2Error.INVALID_REQUEST_CODE);
+        assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
     }
 
     protected void verifyAuthorizeEndpoint(final String clientId, final String requestUri) {

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


More information about the commits mailing list