[java-idp-oidc] 02/02: JOIDC-270 - Add 'exp' claim to Backchannel LogoutToken
Codeberg
noreply at shibboleth.net
Wed Jun 17 07:21:55 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-idp-oidc.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-oidc/commit/528c096ee3032b50fa0cece2b312d1a22157cfd9
commit 528c096ee3032b50fa0cece2b312d1a22157cfd9
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Jun 5 15:55:49 2026 +0300
JOIDC-270 - Add 'exp' claim to Backchannel LogoutToken
https://shibboleth.atlassian.net/browse/JOIDC-270
Include 'exp' to the logout token claims set
- Default offset is 30 seconds
- Configurable via 'idp.oidc.logout.logoutTokenExpiryOffset'
---
.../impl/PrepareBackChannelLogoutRequest.java | 25 +++++++++++++++++++---
.../oidc/oidc-logout-propagation-beans.xml | 3 ++-
.../idp/plugin/oidc/op/conf/oidc.properties | 3 +++
.../impl/PrepareBackChannelLogoutRequestTest.java | 5 +++++
4 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequest.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequest.java
index ed53c166..ee5e9d58 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequest.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequest.java
@@ -44,7 +44,8 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.text.ParseException;
-import java.util.Calendar;
+import java.time.Duration;
+import java.time.Instant;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -75,12 +76,18 @@ public class PrepareBackChannelLogoutRequest extends AbstractOIDCBackChannelLogo
/** The xmlSafe-flag passed to the identifier generator. */
private boolean xmlSafeIdentifier;
+ /** The offset to add to the 'exp' claim time for logout token claims set. Default is 30 seconds.*/
+ @Nonnull private Duration logoutTokenExpiryOffset;
+
/**
* Constructor.
*/
public PrepareBackChannelLogoutRequest() {
idGeneratorLookupStrategy = FunctionSupport.constant(new SecureRandomIdentifierGenerationStrategy());
xmlSafeIdentifier = true;
+ final Duration thirtySecs = Duration.ofSeconds(30);
+ assert thirtySecs != null;
+ logoutTokenExpiryOffset = thirtySecs;
}
/**
@@ -115,6 +122,16 @@ public class PrepareBackChannelLogoutRequest extends AbstractOIDCBackChannelLogo
objectMapper = Constraint.isNotNull(mapper, "Object mapper cannot be null");
}
+ /**
+ * Set the logout token expiry time offset.
+ *
+ * @param expiry the logout token 'exp' claim offset
+ */
+ public void setLogoutTokenExpiryOffset(@Nonnull final Duration expiry) {
+ checkSetterPreconditions();
+ logoutTokenExpiryOffset = Constraint.isNotNull(expiry, "logoutTokenExpiryOffset can not be null");
+ }
+
/** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
@@ -150,12 +167,14 @@ public class PrepareBackChannelLogoutRequest extends AbstractOIDCBackChannelLogo
final Issuer iss = new Issuer(rpSession.getIssuer());
final Subject sub = new Subject(rpSession.getSubject());
final List<Audience> aud = Collections.singletonList(new Audience(rpSession.getId()));
- final Date iat = Calendar.getInstance().getTime();
+ final Instant now = Instant.now();
+ final Date iat = Date.from(now);
+ final Date exp = Date.from(now.plus(logoutTokenExpiryOffset));
assert idGenerator != null;
final JWTID jti = new JWTID(idGenerator.generateIdentifier(xmlSafeIdentifier));
final SessionID sid = new SessionID(rpSession.getSessionIdentifier());
- final LogoutTokenClaimsSet logoutTokenClaimsSet = new LogoutTokenClaimsSet(iss, sub, aud, iat, jti, sid);
+ final LogoutTokenClaimsSet logoutTokenClaimsSet = new LogoutTokenClaimsSet(iss, sub, aud, iat, exp, jti, sid);
final OIDCBackChannelLogoutPropagationContext bcLogoutContext = getOidcBackChannelLogoutContext();
assert bcLogoutContext != null;
bcLogoutContext.setLogoutTokenClaimsSet(logoutTokenClaimsSet);
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/logoutprop/oidc/oidc-logout-propagation-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/logoutprop/oidc/oidc-logout-propagation-beans.xml
index f5843c90..d90c5b71 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/logoutprop/oidc/oidc-logout-propagation-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/logoutprop/oidc/oidc-logout-propagation-beans.xml
@@ -83,7 +83,8 @@
scope="prototype"
p:xmlSafeIdentifier="%{idp.oidc.xmlSafeIdentifiers:true}"
p:identifierGeneratorLookupStrategy-ref="shibboleth.oidc.DefaultIdentifierGenerationStrategy"
- p:objectMapper-ref="#{'%{idp.oidc.logging.objectMapper:shibboleth.oidc.JSONObjectMapper}'.trim()}" />
+ p:objectMapper-ref="#{'%{idp.oidc.logging.objectMapper:shibboleth.oidc.JSONObjectMapper}'.trim()}"
+ p:logoutTokenExpiryOffset="%{idp.oidc.logout.logoutTokenExpiryOffset:PT30S}"/>
<bean id="DefaultLogoutTokenTypeLookupStrategy" parent="shibboleth.Functions.Constant"
c:target="logout+jwt"/>
diff --git a/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/conf/oidc.properties b/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/conf/oidc.properties
index 798dae56..197b4f12 100644
--- a/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/conf/oidc.properties
+++ b/idp-oidc-extension-impl/src/main/resources/net/shibboleth/idp/plugin/oidc/op/conf/oidc.properties
@@ -143,6 +143,9 @@ idp.oidc.subject.salt = this_too_should_be_ch4ng3d
# Bean (BiPredicate<String,SPSession>) used for matching logout hint to the SP session
#idp.oidc.logout.logoutHintMatchingStrategy =
+# The offset to add to the 'exp' claim time for logout token claims set
+#idp.oidc.logout.logoutTokenExpiryOffset = PT30S
+
# Settings for issue-registration-access-token flow
#idp.oidc.admin.registration.logging = IssueRegistrationAccessToken
#idp.oidc.admin.registration.nonBrowserSupported = true
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequestTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequestTest.java
index 72c4a0da..dd024c2b 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequestTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/logout/profile/impl/PrepareBackChannelLogoutRequestTest.java
@@ -79,6 +79,11 @@ public class PrepareBackChannelLogoutRequestTest
Assert.assertEquals(claimsSet.getSubject().getValue(), "mockSubject");
Assert.assertEquals(claimsSet.getSessionID().getValue(), "mockSessionIdentifier");
Assert.assertEquals(claimsSet.getJWTID().getValue(), "mockId");
+ final long iat = claimsSet.getIssueTime().toInstant().getEpochSecond();
+ final long exp = claimsSet.getExpirationTime().toInstant().getEpochSecond();
+ Assert.assertNotNull(iat);
+ Assert.assertNotNull(exp);
+ Assert.assertEquals(exp - iat, 30);
}
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list