[java-plugin-shibd] branch main updated: Adjust behavior of various operations.

Codeberg noreply at shibboleth.net
Wed Dec 10 02:52:37 UTC 2025


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch main
in repository java-plugin-shibd.

View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd/commit/f36bfc53a96fce018f2ecff54a7b2d2df2477897

The following commit(s) were added to refs/heads/main by this push:
     new f36bfc5  Adjust behavior of various operations.
f36bfc5 is described below

commit f36bfc53a96fce018f2ecff54a7b2d2df2477897
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Dec 9 21:52:26 2025 -0500

    Adjust behavior of various operations.
---
 .../sp/profile/impl/DoSessionCacheOperation.java   | 96 +++++++++++++---------
 1 file changed, 58 insertions(+), 38 deletions(-)

diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DoSessionCacheOperation.java b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DoSessionCacheOperation.java
index fe84111..fc64beb 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DoSessionCacheOperation.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DoSessionCacheOperation.java
@@ -17,7 +17,6 @@ package net.shibboleth.sp.profile.impl;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.time.Instant;
 
@@ -35,6 +34,9 @@ import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.annotation.constraint.Positive;
+import net.shibboleth.shared.codec.Base64Support;
+import net.shibboleth.shared.codec.DecodingException;
+import net.shibboleth.shared.codec.EncodingException;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -53,8 +55,11 @@ import net.shibboleth.sp.profile.AbstractAgentAction;
  * @event {@link EventIds#INVALID_PROFILE_CTX}
  * @event {@link EventIds#INVALID_MESSAGE}
  * @event {@link EventIds#IO_ERROR}
+ * @event {@link EventIds#UNABLE_TO_DECODE}
+ * @event {@link EventIds#UNABLE_TO_ENCODE}
  * @event {@link EventIds#MESSAGE_PROC_ERROR}
  * @event {@link #INVALID_SESSION}
+ * @event {@link #MISSING_SESSION}
  * @event {@link #EXPIRED_SESSION}
  * @event {@link #VERSION_MISMATCH}
  */
@@ -66,6 +71,9 @@ public class DoSessionCacheOperation extends AbstractAgentAction {
     /** Custom event for invalid session. */
     @Nonnull @NotEmpty public static final String INVALID_SESSION = "InvalidSession";
 
+    /** Custom event for invalid session. */
+    @Nonnull @NotEmpty public static final String MISSING_SESSION = "MissingSession";
+
     /** Custom event for expired session. */
     @Nonnull @NotEmpty public static final String EXPIRED_SESSION = "ExpiredSession";
     
@@ -236,15 +244,18 @@ public class DoSessionCacheOperation extends AbstractAgentAction {
         
         Long exp = Instant.now().plusSeconds(getStorageTimeout()).toEpochMilli();
         
-        // TODO: Encode/encrypt/etc.?
         String value;
         try (final ByteArrayOutputStream sink = new ByteArrayOutputStream()) {
             data.serialize(sink);
-            value = sink.toString(StandardCharsets.UTF_8);
+            value = Base64Support.encode(sink.toByteArray(), false);
+        } catch (final EncodingException e) {
+            log.error("{} Unable to base64-encode session data", getLogPrefix(), e);
+            ActionSupport.buildEvent(profileRequestContext, EventIds.UNABLE_TO_ENCODE);
+            return;
         }
         
-        assert value != null;
-                
+        // TODO: Encrypt?
+
         int attempts = 0;
         do {
             final String key = identifierStrategy.generateIdentifier(false);
@@ -321,12 +332,15 @@ public class DoSessionCacheOperation extends AbstractAgentAction {
         
         DDF sessionData;
         try (final ByteArrayInputStream source =
-                new ByteArrayInputStream(record.getValue().getBytes(StandardCharsets.UTF_8))) {
+                new ByteArrayInputStream(Base64Support.decode(record.getValue()))) {
             sessionData = DDF.deserialize(source);
+        } catch (final DecodingException e) {
+            log.error("{} Unable to base64-decode session data", getLogPrefix(), e);
+            ActionSupport.buildEvent(profileRequestContext, INVALID_SESSION);
+            return;
         }
-        assert sessionData != null;
         
-        // We have a deserialized session, need to enforce policies if specified.
+        // We have a deserialized session, need to enforce lifetime if specified.
         
         final Integer lifetime = input.getmember(LIFETIME).integer();
         if (lifetime != null && lifetime > 0) {
@@ -388,14 +402,17 @@ public class DoSessionCacheOperation extends AbstractAgentAction {
         final Long st = getStorageTimeout();
         final Long exp = Instant.now().plusSeconds(st).toEpochMilli();
         
-        // TODO: Encode/encrypt/etc.?
         String value;
         try (final ByteArrayOutputStream sink = new ByteArrayOutputStream()) {
             data.serialize(sink);
-            value = sink.toString(StandardCharsets.UTF_8);
+            value = Base64Support.encode(sink.toByteArray(), false);
+        } catch (final EncodingException e) {
+            log.error("{} Unable to base64-encode session data", getLogPrefix(), e);
+            ActionSupport.buildEvent(profileRequestContext, EventIds.UNABLE_TO_ENCODE);
+            return;
         }
-        
-        assert value != null;
+
+        // TODO: Encrypt?
         
         try {
             version = storageService.updateWithVersion(version, STORAGE_CONTEXT, ensureAgent().getId() + '!' + key,
@@ -433,7 +450,7 @@ public class DoSessionCacheOperation extends AbstractAgentAction {
         // "timeout" - session timeout policy to apply
         
         // Output:
-        // "ver" - current version, indicates record was found and updated 
+        // None
         
         final String key = input.getmember(KEY).string();
         if (key == null) {
@@ -441,30 +458,30 @@ public class DoSessionCacheOperation extends AbstractAgentAction {
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
             return;
         }
-        
-        // Read back record to check for timeout.
-        
-        final StorageRecord<?> record = storageService.read(STORAGE_CONTEXT, ensureAgent().getId() + '!' + key);
-        if (record == null) {
-            // Send back an empty response.
-            log.debug("{} No session found ({})", getLogPrefix(), key);
-            final DDF output = new DDF();
-            ensureAgentRequestContext().setOutput(output);
-            return;
-        }
-        
-        Long lastAccess = record.getExpiration();
-        if (lastAccess == null) {
-            log.error("{} Session record ({}) had no expiration", getLogPrefix(), key);
-            ActionSupport.buildEvent(profileRequestContext, INVALID_SESSION);
-            return;
-        }
-        
-        final Long st = getStorageTimeout();
+
         final Instant now = Instant.now();
+        final Long st = getStorageTimeout();
         
         final Integer timeout = input.getmember(TIMEOUT).integer();
         if (timeout != null && timeout > 0) {
+            // Read back record to check for timeout.
+            final StorageRecord<?> record = storageService.read(STORAGE_CONTEXT, ensureAgent().getId() + '!' + key);
+            if (record == null) {
+                // Send back an empty response.
+                log.debug("{} No session found ({})", getLogPrefix(), key);
+                final DDF output = new DDF();
+                ensureAgentRequestContext().setOutput(output);
+                return;
+            }
+        
+            Long lastAccess = record.getExpiration();
+            if (lastAccess == null) {
+                log.error("{} Session record ({}) had no expiration", getLogPrefix(), key);
+                ActionSupport.buildEvent(profileRequestContext, INVALID_SESSION);
+                return;
+            }
+        
+        
             // Recover last access time by backdating record expiration.
             lastAccess -= st;
             if (Instant.ofEpochMilli(lastAccess).plusSeconds(timeout).isBefore(now)) {
@@ -481,14 +498,13 @@ public class DoSessionCacheOperation extends AbstractAgentAction {
         if (storageService.updateExpiration(STORAGE_CONTEXT, ensureAgent().getId() + '!' + key,
                 now.plusSeconds(st).toEpochMilli())) {
             final DDF output = new DDF();
-            output.addmember(VERSION).longinteger(record.getVersion());
+            output.addmember(KEY).string(key);
             ensureAgentRequestContext().setOutput(output);
         } else {
             // Record disappeared, so send back an empty response.
             log.debug("{} Session record ({}) disappeared before update?", getLogPrefix(), key);
-            final DDF output = new DDF();
-            ensureAgentRequestContext().setOutput(output);
-        }        
+            ActionSupport.buildEvent(profileRequestContext, MISSING_SESSION);
+        }
     }
     
     /**
@@ -503,7 +519,8 @@ public class DoSessionCacheOperation extends AbstractAgentAction {
         // Input:
         // "key" - session key to delete
         
-        // Output: None
+        // Output:
+        // "key" - session key, indicates record was found and deleted
         
         final String key = input.getmember(KEY).string();
         if (key == null) {
@@ -514,8 +531,11 @@ public class DoSessionCacheOperation extends AbstractAgentAction {
         
         if (storageService.delete(STORAGE_CONTEXT, ensureAgent().getId() + '!' + key)) {
             log.debug("{} Deleted session record ({})", getLogPrefix(), key);
+            final DDF output = new DDF();
+            ensureAgentRequestContext().setOutput(output);
         } else {
             log.debug("{} No session record ({})", getLogPrefix(), key);
+            ActionSupport.buildEvent(profileRequestContext, MISSING_SESSION);
         }
     }
 

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


More information about the commits mailing list