[java-idp-oidc] branch main updated: JOIDC-149 - Configurability of ID Token issuance via Refresh Tokens

Henri Mikkonen henri.mikkonen at iki.fi
Fri Apr 21 09:38:27 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=5cf4bc27495f20f3bf0ba2f19b920f95d2dd582a

The following commit(s) were added to refs/heads/main by this push:
     new 5cf4bc27 JOIDC-149 - Configurability of ID Token issuance via Refresh Tokens
5cf4bc27 is described below

commit 5cf4bc27495f20f3bf0ba2f19b920f95d2dd582a
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Apr 21 12:37:34 2023 +0300

    JOIDC-149 - Configurability of ID Token issuance via Refresh Tokens
    
    https://shibboleth.atlassian.net/browse/JOIDC-149
    
    The token flow now exploits the 'issueIdTokenViaRefreshToken' profile configuration
    parameter. That flag is required to be 'true' whenever grant type is refresh_token
    in order to get id_token issued.
    
    The new property 'idp.oauth2.issueIdTokenViaRefreshToken' can be globally used for
    setting the flag. The default value is 'true'.
---
 .../idp/flows/oidc/token/token-beans.xml           | 38 +++++++++++++++++++---
 .../idp/service/relying-party/postconfig.xml       | 11 ++++++-
 .../plugin/oidc/op/profile/flow/TokenFlowTest.java | 18 ++++++++++
 .../src/test/resources/conf/relying-party.xml      |  8 +++++
 4 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-beans.xml
index 1b5ab3bd..dc0b9443 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/token/token-beans.xml
@@ -53,6 +53,11 @@
         class="net.shibboleth.idp.plugin.oidc.op.messaging.context.logic.RequestedGrantTypesCondition"
         p:grantTypes="#{T(com.nimbusds.oauth2.sdk.GrantType).AUTHORIZATION_CODE}" />
 
+    <!-- Condition signaling that request was for refresh_token grant. -->        
+    <bean id="RefreshTokenGrantCondition"
+        class="net.shibboleth.idp.plugin.oidc.op.messaging.context.logic.RequestedGrantTypesCondition"
+        p:grantTypes="#{T(com.nimbusds.oauth2.sdk.GrantType).REFRESH_TOKEN}" />
+
     <!-- Traditional third-party grant handling. -->
 
     <bean id="ValidateGrant" class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateGrant" scope="prototype"
@@ -155,9 +160,32 @@
     <bean id="TokenRequestScopeLookupStrategy"
         class="net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.TokenRequestScopeLookupFunction" />
 
-    <bean id="IssueIDTokenCondition"
+    <bean id="BuildOIDCTokensCondition"
         class="net.shibboleth.idp.plugin.oidc.op.profile.logic.IssueIDTokenCondition" />
 
+    <bean id="IssueIDTokenCondition" parent="shibboleth.Conditions.AND">
+        <constructor-arg>
+            <list>
+                <ref bean="BuildOIDCTokensCondition" />
+                <bean parent="shibboleth.Conditions.OR">
+                    <constructor-arg>
+                        <list>
+                            <ref bean="AuthorizationCodeGrantCondition" />
+                            <bean parent="shibboleth.Conditions.AND">
+                                <constructor-arg>
+                                    <list>
+                                        <ref bean="RefreshTokenGrantCondition" />
+                                        <bean class="net.shibboleth.oidc.profile.config.logic.IssueIdTokenViaRefreshTokenPredicate" />
+                                    </list>
+                                </constructor-arg>
+                            </bean>
+                        </list>
+                    </constructor-arg>
+                </bean>
+            </list>
+        </constructor-arg>
+    </bean>
+
     <!--
     Do a metadata lookup for the primary audience of the token for encryption purposes.
     Contexts are stored under the outbound MessageContext, including the new RelyingPartyContext.
@@ -385,13 +413,13 @@
                         <list>
                             <bean parent="shibboleth.Conditions.NOT">
                                 <constructor-arg>
-                                    <ref bean="IssueIDTokenCondition" />
+                                    <ref bean="BuildOIDCTokensCondition" />
                                 </constructor-arg>
                             </bean>
                             <bean parent="shibboleth.Conditions.AND">
                                 <constructor-arg>
                                     <list>
-                                        <ref bean="IssueIDTokenCondition" />
+                                        <ref bean="BuildOIDCTokensCondition" />
                                         <bean class="net.shibboleth.idp.plugin.oidc.op.profile.logic.OfflineAccessScopeCondition" />
                                     </list>
                                 </constructor-arg>
@@ -625,7 +653,7 @@
             </bean>
         </property>
         <property name="activationCondition">
-            <bean parent="shibboleth.Conditions.NOT" c:_0-ref="IssueIDTokenCondition" />
+            <bean parent="shibboleth.Conditions.NOT" c:_0-ref="BuildOIDCTokensCondition" />
         </property>
     </bean>
 
@@ -699,7 +727,7 @@
             </bean>
         </constructor-arg>
         <property name="activationCondition">
-            <bean parent="shibboleth.Conditions.NOT" c:_0-ref="IssueIDTokenCondition" />
+            <bean parent="shibboleth.Conditions.NOT" c:_0-ref="BuildOIDCTokensCondition" />
         </property>
     </bean>
 
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
index 67638435..117433d0 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
@@ -43,7 +43,8 @@
     <bean id="OAUTH2.Token" parent="AbstractOIDCSSOProfile" lazy-init="true"
         class="net.shibboleth.oidc.profile.oauth2.config.impl.DefaultOAuth2TokenConfiguration"
         p:grantTypes="%{idp.oauth2.grantTypes:authorization_code,refresh_token}"
-        p:enforceRefreshTokenRotation="%{idp.oauth2.enforceRefreshTokenRotation:false}" />
+        p:enforceRefreshTokenRotation="%{idp.oauth2.enforceRefreshTokenRotation:false}"
+        p:issueIdTokenViaRefreshToken="%{idp.oauth2.issueIdTokenViaRefreshToken:true}" />
     
     <bean id="OAUTH2.TokenAudience" parent="AbstractOIDCProfile" lazy-init="true"
         class="net.shibboleth.oidc.profile.oauth2.config.impl.DefaultOAuth2TokenAudienceConfiguration"
@@ -403,6 +404,14 @@
                 <constructor-arg value="%{idp.oauth2.enforceRefreshTokenRotation:false}" />
             </bean>
         </property>
+        <property name="IssueIdTokenViaRefreshTokenPredicate">
+            <bean class="net.shibboleth.utilities.java.support.logic.PredicateSupport" factory-method="fromFunction">
+                <constructor-arg>
+                    <bean parent="shibboleth.MDDrivenBoolProperty" p:propertyName="issueIdTokenViaRefreshToken" />
+                </constructor-arg>
+                <constructor-arg value="%{idp.oauth2.issueIdTokenViaRefreshToken:true}" />
+            </bean>
+        </property>
     </bean>
     
     <bean id="OAUTH2.TokenAudience.MDDriven" parent="AbstractMDDrivenOIDCProfile" lazy-init="true"
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java
index b1a656bb..d150cd21 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java
@@ -92,6 +92,7 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
     String clientIdCustomTokens = "mockClientIdCustomTokens";
     String clientIdRefreshTokenRotation = "mockClientIdRefreshTokenRotation";
     String clientIdJwtAccessToken = "mockClientIdJwtAccessToken";
+    String clientIdNoIdTokenViaRefreshToken = "mockClientIdNoIdTokenViaRefreshToken";
     String codeVerifier = "9234567812345678123456781234567812345678123456781234567812345678";
 
     Scope scope = Scope.parse("openid profile email offline_access");
@@ -116,6 +117,7 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
         removeMetadata(storageService, clientIdCustomTokens);
         removeMetadata(storageService, clientIdRefreshTokenRotation);
         removeMetadata(storageService, clientIdJwtAccessToken);
+        removeMetadata(storageService, clientIdNoIdTokenViaRefreshToken);
     }
 
     @Test
@@ -830,6 +832,22 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
         Assert.assertFalse(revocationCache.isRevoked(RevocationCacheContexts.AUTHORIZATION_CODE, rootId));
     }
 
+    @Test
+    public void testValidRefreshTokenGrant_idTokenIssuanceDisabled() throws Exception {
+        final String clientId = clientIdNoIdTokenViaRefreshToken;
+        final String id = idGenerator.generateIdentifier();
+        final String rootId = idGenerator.generateIdentifier();
+        initializeGrantAndRequest(clientId, createRequestParameters(redirectUri, "refresh_token",
+                buildRefreshToken(clientId, id, rootId, null), clientId));
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        Assert.assertFalse(OIDCTokenResponse.class.isInstance(parseResponse(result)));
+        final AccessTokenResponse response = parseSuccessResponse(result, AccessTokenResponse.class);
+        final AccessToken accessToken = response.getTokens().getAccessToken();
+        Assert.assertNotNull(accessToken);
+        Assert.assertFalse(revocationCache.isRevoked(RevocationCacheContexts.SINGLE_ACCESS_OR_REFRESH_TOKENS, id));
+        Assert.assertFalse(revocationCache.isRevoked(RevocationCacheContexts.AUTHORIZATION_CODE, rootId));
+    }
+
     @Test
     public void testValidRefreshTokenGrantWithSid() throws Exception {
         final String id = idGenerator.generateIdentifier();
diff --git a/idp-oidc-extension-impl/src/test/resources/conf/relying-party.xml b/idp-oidc-extension-impl/src/test/resources/conf/relying-party.xml
index d451d60c..399d41e9 100644
--- a/idp-oidc-extension-impl/src/test/resources/conf/relying-party.xml
+++ b/idp-oidc-extension-impl/src/test/resources/conf/relying-party.xml
@@ -153,6 +153,14 @@
                  </list>
             </property>
         </bean>
+
+        <bean parent="RelyingPartyByName" c:relyingPartyIds="mockClientIdNoIdTokenViaRefreshToken">
+            <property name="profileConfigurations">
+                 <list>
+                     <bean parent="OAUTH2.Token.MDDriven" p:issueIdTokenViaRefreshToken="false"/>
+                 </list>
+            </property>
+        </bean>
         <bean parent="RelyingPartyByName" c:relyingPartyIds="mockClientIdPKCEPlainUnforced">
             <property name="profileConfigurations">
                  <list>

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


More information about the commits mailing list