[java-plugin-shibd-oidc] branch main updated: Add redirect_uri to state and fix token request

Codeberg noreply at shibboleth.net
Tue Feb 17 18:33:50 UTC 2026


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/fd294d953e59dcea15fa426b5d32da35ea73e16e

The following commit(s) were added to refs/heads/main by this push:
     new fd294d9  Add redirect_uri to state and fix token request
fd294d9 is described below

commit fd294d953e59dcea15fa426b5d32da35ea73e16e
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Tue Feb 17 18:33:39 2026 +0000

    Add redirect_uri to state and fix token request
---
 .../profile/AuthenticationRequestStateData.java    | 36 ++++++++++-
 .../idp/flows/sp/consumer/oidc/oidc-beans.xml      |  7 ++-
 .../sp/oidc/flows/OIDCTokenConsumerFlowTest.java   |  1 +
 .../shibboleth/sp/oidc/flows/TestConstants.java    | 15 ++++-
 .../impl/RedirectUriFromStateLookupStrategy.java   | 71 ++++++++++++++++++++++
 5 files changed, 126 insertions(+), 4 deletions(-)

diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestStateData.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestStateData.java
index bc1235f..fea1898 100644
--- a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestStateData.java
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestStateData.java
@@ -15,6 +15,7 @@
 package net.shibboleth.sp.oidc.profile;
 
 
+import java.net.URI;
 import java.time.Duration;
 import java.time.Instant;
 import java.util.List;
@@ -72,6 +73,12 @@ public class AuthenticationRequestStateData {
     /** List of authentication context class references requested in the authentication request.*/
     @Nonnull @Unmodifiable @NotLive private List<String> acrs;
     
+    /**
+     * The redirect_uri value of the authentication request, included here to be
+     * able to include it in any further Token endpoint requests.
+     */
+    @Nullable private URI redirectUri;
+    
     /** Constructor.*/
     public AuthenticationRequestStateData() {
         acrs = CollectionSupport.emptyList();
@@ -258,6 +265,29 @@ public class AuthenticationRequestStateData {
         return CollectionSupport.copyToList(acrs);
     }
     
+    /**
+     * Get the redirect_uri value of the authentication request.
+     * 
+     * @return Returns the redirectUri.
+     */
+    @JsonProperty("redirect_uri")
+    @Nullable public URI getRedirectUri() {
+        return redirectUri;
+    }
+    
+    /**
+     * Set the redirect_uri value of the authentication request, included here to be able to include it in any further 
+     * Token endpoint requests.
+     * 
+     * @param uri The redirectUri to set.
+     * 
+     * @return the updated object
+     */
+    public AuthenticationRequestStateData setRedirectUri(@Nullable final URI uri) {
+        redirectUri = uri;
+        return this;
+    }
+    
     /**
      * Create an instance of this class from the given authentication request and authentication authority.
      * 
@@ -277,7 +307,8 @@ public class AuthenticationRequestStateData {
                 .setMaxAge(request.getMaxAge())
                 .setAuthnRequestTime(request.getAuthnRequestTime())
                 .setClientId(request.getClientID().getValue())
-                .setAcrs(request.getAcrs().stream().filter(Objects::nonNull).map(ACR::getValue).toList());
+                .setAcrs(request.getAcrs().stream().filter(Objects::nonNull).map(ACR::getValue).toList())
+                .setRedirectUri(request.getRedirectURI());
 
         state.setAuthTimeRequired(isAuthTimeRequired(request));
         return state;
@@ -322,7 +353,8 @@ public class AuthenticationRequestStateData {
 
         return "AuthenticationRequestStateData [nonce="+nonceSuffix+", authenticatingAuthority=" + authenticatingAuthority
                 + ", pkceCodeVerifier="+pkceCodeVerifierSuffix+", maxAge=" + maxAge + ", authTimeRequired="
-                + authTimeRequired + ", authnRequestTime=" + authnRequestTime + ", acrs=" + acrs + "]";
+                + authTimeRequired + ", authnRequestTime=" + authnRequestTime + ", acrs=" + acrs + ", "
+                        + "redirect_uri="+redirectUri+"]";
     }
     
     /**
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml
index 53c4cd3..3f3fce0 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml
@@ -164,7 +164,12 @@
     <bean id="DefaultAuthCodeTokenResponseEncoder" scope="prototype"
         class="net.shibboleth.oidc.profile.encoding.impl.AuthCodeTokenRequestEncoder" 
         p:providerMetadataLookupStrategy-ref="shibboleth.ChildLookup.OIDCProviderMetadataContextFromInboundMessageContext"
-        p:oAuth2ClientAuthenticationContextLookupStrategy-ref="shibboleth.ChildLookupOrCreate.OAuth2ClientAuthenticationContextFromInboundMessageContext"/>
+        p:oAuth2ClientAuthenticationContextLookupStrategy-ref="shibboleth.ChildLookupOrCreate.OAuth2ClientAuthenticationContextFromInboundMessageContext">
+        <property name="redirectUriLookupStrategy">
+             <bean class="net.shibboleth.sp.oidc.profile.impl.RedirectUriFromStateLookupStrategy" scope="prototype" 
+             c:authenticationRequestLookupStrategy-ref="shibboleth.ChildLookup.AuthenticationRequestStateDataFromInbound"/>   
+        </property>   
+    </bean>
     
     <bean id="ValidateOAuthAccessTokenResponse" scope="prototype"
         class="net.shibboleth.sp.oidc.profile.impl.ValidateOAuthAccessTokenResponse"/>
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 ba696b1..59dda68 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
@@ -829,6 +829,7 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
             }
         }
         Assert.assertTrue(mutableIds.isEmpty());
+        //TODO ADD BACK
         
 //        try {
 //            final DDF s = output.getmember(ConsumerConstants.SESSION_OPAQUE);
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/TestConstants.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/TestConstants.java
index 5617dd2..693b694 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/TestConstants.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/TestConstants.java
@@ -16,6 +16,8 @@ package net.shibboleth.sp.oidc.flows;
 
 import static org.testng.Assert.fail;
 
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
@@ -138,12 +140,23 @@ public final class TestConstants {
         
     }
     
+    /**
+     * Build the authentication request state JSON for the given parameters. This is used for the state value, and 
+     * contains important information about the authentication request.
+     * 
+     * @param maxAge the maximum age of the authentication request, used for validation of the authentication response
+     * @param authTimeRequired a flag whether the authentication time is required, used for validation of the authentication response
+     * @param acrs the ACRs to request, used for validation of the authentication response. May be null if no ACRs are requested.
+     * @return the authentication request state JSON for the given parameters
+     * @throws URISyntaxException on error.
+     */
     public static String buildAuthenticationState(final Duration maxAge, final boolean authTimeRequired, 
-            @Nullable final List<String> acrs) {
+            @Nullable final List<String> acrs) throws URISyntaxException {
         final AuthenticationRequestStateData state = new AuthenticationRequestStateData()
                 .setClientId(APPLICATION_ID)
                 .setNonce(ID_TOKEN_NONCE)
                 .setAuthenticationAuthority(ISSUER)
+                .setRedirectUri(new URI(RESPONSE_URL))
                 .setMaxAge(maxAge)
                 .setAuthTimeRequired(authTimeRequired)
                 .setAuthnRequestTime(Instant.now());
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/RedirectUriFromStateLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/RedirectUriFromStateLookupStrategy.java
new file mode 100644
index 0000000..a344abc
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/RedirectUriFromStateLookupStrategy.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed 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.sp.oidc.profile.impl;
+
+import java.net.URI;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.sp.oidc.context.AuthnRequestStateDataContext;
+import net.shibboleth.sp.oidc.profile.AuthenticationRequestStateData;
+
+
+/**
+ * A lookup strategy that retrieves the redirect_uri from the {@link AuthenticationRequestStateData} stored in the
+ * {@link AuthnRequestStateDataContext} associated with a {@link ProfileRequestContext}.
+ */
+ at ThreadSafe
+public class RedirectUriFromStateLookupStrategy implements Function<ProfileRequestContext, URI> {
+    
+    /** 
+     * Strategy used to locate the {@link AuthnRequestStateDataContext}.
+     */
+    @Nonnull private final Function<ProfileRequestContext, AuthnRequestStateDataContext> authenticationRequestLookupStrategy;
+
+    /**
+     * Constructor.
+     *
+     * @param strategy strategy to find the authentication request state context
+     */
+    public RedirectUriFromStateLookupStrategy(@ParameterName(name = "authenticationRequestLookupStrategy")
+            @Nonnull final Function<ProfileRequestContext, AuthnRequestStateDataContext> strategy) {
+        authenticationRequestLookupStrategy = Constraint.isNotNull(strategy,
+                "authenticationRequestLookupStrategy can not be null");
+    }
+    
+
+    @Override
+    @Nullable public URI apply(final ProfileRequestContext prc) {
+        
+        final AuthnRequestStateDataContext authnRequestCtx = authenticationRequestLookupStrategy.apply(prc);
+        
+        if (authnRequestCtx == null) {
+            return null;
+        }
+        final AuthenticationRequestStateData authnRequest = authnRequestCtx.getAuthnState();
+        if (authnRequest == null) {
+            return null;
+        }
+        return authnRequest.getRedirectUri();
+    }
+
+}

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


More information about the commits mailing list