[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