[java-idp-oidc] branch main updated: JOIDC-73 - Add validation of request_uri

Scott Cantor cantor.2 at osu.edu
Fri Jan 28 18:29:30 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=300cb7ad16ccd543291c3de0fd4962b1f9f7d412

The following commit(s) were added to refs/heads/main by this push:
     new 300cb7ad JOIDC-73 - Add validation of request_uri
300cb7ad is described below

commit 300cb7ad16ccd543291c3de0fd4962b1f9f7d412
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri Jan 28 13:29:27 2022 -0500

    JOIDC-73 - Add validation of request_uri
    
    https://shibboleth.atlassian.net/browse/JOIDC-73
---
 .../impl/SetRequestObjectToResponseContext.java    |  32 +++++-
 .../oidc/op/static/openid-configuration.json       |   2 +-
 .../SetRequestObjectToResponseContextTest.java     | 126 +++++++++++++++++++++
 3 files changed, 156 insertions(+), 4 deletions(-)

diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/SetRequestObjectToResponseContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/SetRequestObjectToResponseContext.java
index 9c0bf1c0..2364de01 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/SetRequestObjectToResponseContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/SetRequestObjectToResponseContext.java
@@ -18,7 +18,10 @@
 package net.shibboleth.idp.plugin.oidc.op.profile.impl;
 
 import java.io.IOException;
+import java.net.URI;
 import java.text.ParseException;
+import java.util.Set;
+
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.apache.http.HttpResponse;
@@ -35,6 +38,7 @@ import org.opensaml.security.httpclient.HttpClientSecuritySupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import com.nimbusds.jwt.JWTParser;
+import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseContext;
 import net.shibboleth.idp.plugin.oidc.op.profile.OidcEventIds;
@@ -44,14 +48,13 @@ import net.shibboleth.utilities.java.support.logic.Constraint;
 
 /**
  * Action that stored request object to {@link OIDCAuthenticationResponseContext}. The request
- * object may be given by value with request parameter or by reference with
- * request_uri parameter.
+ * object may be given by value with request parameter or by reference with request_uri parameter.
  */
 public class SetRequestObjectToResponseContext extends AbstractOIDCAuthenticationResponseAction {
 
     /** Class logger. */
     @Nonnull private Logger log = LoggerFactory.getLogger(SetRequestObjectToResponseContext.class);
-
+    
     /** HTTP Client used to post the data. */
     @NonnullAfterInit private HttpClient httpClient;
 
@@ -106,16 +109,19 @@ public class SetRequestObjectToResponseContext extends AbstractOIDCAuthenticatio
         if (!super.doPreExecute(profileRequestContext)) {
             return false;
         }
+        
         if (!getAuthenticationRequest().specifiesRequestObject()) {
             log.debug("{} No request_uri or request by value, nothing to do", getLogPrefix());
             return false;
         }
+        
         if (getAuthenticationRequest().getRequestObject() != null
                 && getAuthenticationRequest().getRequestURI() != null) {
             log.error("{} request_uri and request object cannot be both set", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, OidcEventIds.REQUEST_OBJECT_AND_URI);
             return false;
         }
+        
         return true;
     }
 
@@ -128,6 +134,26 @@ public class SetRequestObjectToResponseContext extends AbstractOIDCAuthenticatio
                     getOidcResponseContext().getRequestObject().serialize());
             return;
         }
+        
+        // Request URI must be found in metadata.
+        boolean authorized = false;
+        if (getMetadataContext().getClientInformation() != null) {
+            final OIDCClientMetadata metadata = getMetadataContext().getClientInformation().getOIDCMetadata();
+            if (metadata != null) {
+                final Set<URI> allowedURIs = metadata.getRequestObjectURIs();
+                if (allowedURIs != null) {
+                    authorized = allowedURIs.contains(getAuthenticationRequest().getRequestURI());
+                }
+            }
+        }
+        
+        if (!authorized) {
+            log.error("{} Unregistered request URI blocked: {}", getLogPrefix(),
+                    getAuthenticationRequest().getRequestURI());
+            ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REQUEST_URI);
+            return;
+        }
+        
         final HttpGet httpRequest = new HttpGet(getAuthenticationRequest().getRequestURI());
         final HttpClientContext httpContext = buildHttpContext(httpRequest);
         try {
diff --git a/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/static/openid-configuration.json b/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/static/openid-configuration.json
index 32010b07..a78991c2 100644
--- a/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/static/openid-configuration.json
+++ b/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/static/openid-configuration.json
@@ -89,7 +89,7 @@
    "claims_parameter_supported":true,
    "request_parameter_supported":true,
    "request_uri_parameter_supported":true,
-   "require_request_uri_registration":false,
+   "require_request_uri_registration":true,
    "display_values_supported":[
       "page"
    ],
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/SetRequestObjectToResponseContextTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/SetRequestObjectToResponseContextTest.java
new file mode 100644
index 00000000..fe4a5407
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/SetRequestObjectToResponseContextTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.oidc.op.profile.impl;
+
+import net.shibboleth.idp.plugin.oidc.op.profile.OidcEventIds;
+import net.shibboleth.idp.profile.testing.ActionTestingSupport;
+import net.shibboleth.utilities.java.support.httpclient.HttpClientBuilder;
+import net.shibboleth.utilities.java.support.httpclient.HttpClientSupport;
+import net.shibboleth.utilities.java.support.test.repository.RepositorySupport;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Set;
+
+import org.springframework.webflow.execution.Event;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.net.UrlEscapers;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.PlainJWT;
+import com.nimbusds.jwt.SignedJWT;
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.openid.connect.sdk.AuthenticationRequest;
+
+/** {@link SetRequestObjectToResponseContext} unit test. */
+public class SetRequestObjectToResponseContextTest extends BaseOIDCResponseActionTest {
+
+    /** Action. */
+    private SetRequestObjectToResponseContext action;
+
+    /** Init. */
+    @BeforeMethod
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        action = new SetRequestObjectToResponseContext();
+        final HttpClientBuilder builder = new HttpClientBuilder();
+        builder.setTLSSocketFactory(HttpClientSupport.buildNoTrustTLSSocketFactory());
+        action.setHttpClient(builder.buildClient());
+        action.initialize();
+    }
+
+    /** Test when no request object or URI is used. */
+    @Test
+    public void testNothingToDo() {
+        final Event event = action.execute(requestCtx);
+        ActionTestingSupport.assertProceedEvent(event);
+    }
+
+    /**
+     * Test on request object.
+     * 
+     * @throws ParseException
+     */
+    @Test
+    public void testRequestObject() throws ParseException {
+        final JWTClaimsSet ro = new JWTClaimsSet.Builder()
+                .claim("redirect_uri", "https://rp.example.org/redirect_uri")
+                .build();
+        final PlainJWT requestObject = new PlainJWT(ro);
+        setAuthenticationRequest(
+                AuthenticationRequest.parse("client_id=mockClientId&request=" + requestObject.serialize()));
+        
+        final Event event = action.execute(requestCtx);
+        ActionTestingSupport.assertProceedEvent(event);
+        Assert.assertNotNull(respCtx.getRequestObject());
+    }
+
+    /**
+     * Test on invalid request_uri.
+     * 
+     * @throws ParseException
+     * @throws URISyntaxException 
+     */
+    @Test
+    public void testInvalidRequestURI() throws ParseException, URISyntaxException {
+        metadataCtx.getClientInformation().getOIDCMetadata().setRequestObjectURIs(
+                Set.of(new URI("https://localhost/foobar")));
+        setAuthenticationRequest(
+                AuthenticationRequest.parse("client_id=mockClientId&request_uri=http://localhost/foo"));
+        
+        final Event event = action.execute(requestCtx);
+        ActionTestingSupport.assertEvent(event, OidcEventIds.INVALID_REQUEST_URI);
+    }
+
+    /**
+     * Test a valid request_uri.
+     * 
+     * @throws URISyntaxException
+     * @throws ParseException 
+     */
+    @Test
+    public void testRequestURI() throws URISyntaxException, ParseException {
+        
+        final String uri = RepositorySupport.buildHTTPSResourceURL("java-idp-oidc",
+                "idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/oidc/profile/impl/oidc-authreq.json");
+        
+        metadataCtx.getClientInformation().getOIDCMetadata().setRequestObjectURIs(Set.of(new URI(uri)));
+
+        setAuthenticationRequest(
+                AuthenticationRequest.parse("client_id=" + clientId +
+                        "&request_uri=" + UrlEscapers.urlFormParameterEscaper().escape(uri)));
+        final Event event = action.execute(requestCtx);
+        ActionTestingSupport.assertProceedEvent(event);
+        Assert.assertNotNull(respCtx.getRequestObject());
+        Assert.assertTrue(respCtx.getRequestObject() instanceof SignedJWT);
+    }
+    
+}
\ No newline at end of file

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


More information about the commits mailing list