diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/auth/AuthenticatedUser.java b/server-common/src/main/java/org/a2aproject/sdk/server/auth/AuthenticatedUser.java index 255b2020a..03a81d53f 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/auth/AuthenticatedUser.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/auth/AuthenticatedUser.java @@ -1,10 +1,23 @@ package org.a2aproject.sdk.server.auth; +import org.jspecify.annotations.Nullable; import org.a2aproject.sdk.util.Assert; -public record AuthenticatedUser(String username) implements User { +import java.util.Map; + +public record AuthenticatedUser( + String username, + Map attributes +) implements User { + + public AuthenticatedUser(String username) { + this(username, Map.of()); + } + public AuthenticatedUser { Assert.checkNotNullParam("username", username); + Assert.checkNotNullParam("attributes", attributes); + attributes = Map.copyOf(attributes); } @Override @@ -16,4 +29,9 @@ public boolean isAuthenticated() { public String getUsername() { return username; } + + @Override + public @Nullable Object getAttribute(String key) { + return attributes.get(key); + } } diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/AuthorizationRequestHandlerDecorator.java b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/AuthorizationRequestHandlerDecorator.java index b570410f2..366b55d50 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/AuthorizationRequestHandlerDecorator.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/requesthandlers/AuthorizationRequestHandlerDecorator.java @@ -1,8 +1,5 @@ package org.a2aproject.sdk.server.requesthandlers; -import java.util.concurrent.Flow; -import java.util.concurrent.atomic.AtomicBoolean; - import jakarta.annotation.PostConstruct; import jakarta.annotation.Priority; import jakarta.decorator.Decorator; @@ -10,10 +7,10 @@ import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; - import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; import org.a2aproject.sdk.server.ServerCallContext; import org.a2aproject.sdk.server.auth.TaskAuthorizationProvider; +import org.a2aproject.sdk.server.auth.TaskOperation; import org.a2aproject.sdk.spec.A2AError; import org.a2aproject.sdk.spec.CancelTaskParams; import org.a2aproject.sdk.spec.DeleteTaskPushNotificationConfigParams; @@ -32,9 +29,11 @@ import org.a2aproject.sdk.spec.TaskPushNotificationConfig; import org.a2aproject.sdk.spec.TaskQueryParams; import org.a2aproject.sdk.spec.TaskStatusUpdateEvent; -import org.a2aproject.sdk.server.auth.TaskOperation; import org.jspecify.annotations.Nullable; +import java.util.concurrent.Flow; +import java.util.concurrent.atomic.AtomicBoolean; + @Decorator @Priority(50) public class AuthorizationRequestHandlerDecorator implements RequestHandler { @@ -53,7 +52,17 @@ public class AuthorizationRequestHandlerDecorator implements RequestHandler { public AuthorizationRequestHandlerDecorator() { } - AuthorizationRequestHandlerDecorator(RequestHandler delegate, + /** + * Creates an authorization decorator programmatically. + * + *

This constructor is intended for integrations with + * non-CDI runtimes such as Spring Framework.

+ * + * @param delegate request handler being protected + * @param authorizationProvider task authorization provider; + * {@code null} disables authorization + */ + public AuthorizationRequestHandlerDecorator(RequestHandler delegate, @Nullable TaskAuthorizationProvider authorizationProvider) { this.delegate = delegate; this.authorizationProvider = authorizationProvider; diff --git a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryTaskStore.java b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryTaskStore.java index ddfbde45b..925c950cb 100644 --- a/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryTaskStore.java +++ b/server-common/src/main/java/org/a2aproject/sdk/server/tasks/InMemoryTaskStore.java @@ -1,15 +1,9 @@ package org.a2aproject.sdk.server.tasks; -import java.util.Comparator; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; - import org.a2aproject.sdk.jsonrpc.common.wrappers.ListTasksResult; import org.a2aproject.sdk.server.ServerCallContext; import org.a2aproject.sdk.server.auth.TaskAuthorizationProvider; @@ -17,10 +11,15 @@ import org.a2aproject.sdk.spec.Artifact; import org.a2aproject.sdk.spec.ListTasksParams; import org.a2aproject.sdk.spec.Message; -import org.a2aproject.sdk.util.PageToken; import org.a2aproject.sdk.spec.Task; +import org.a2aproject.sdk.util.PageToken; import org.jspecify.annotations.Nullable; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + /** * In-memory implementation of {@link TaskStore} and {@link TaskStateProvider}. *

@@ -105,7 +104,18 @@ public InMemoryTaskStore(@Any Instance authorizationP : null; } - InMemoryTaskStore(@Nullable TaskAuthorizationProvider authorizationProvider) { + /** + * Creates an in-memory task store with optional + * task-level authorization. + * + *

This constructor supports programmatic wiring + * in non-CDI runtimes such as Spring Framework.

+ * + * @param authorizationProvider provider used to filter + * tasks during list operations; + * {@code null} permits all tasks + */ + public InMemoryTaskStore(@Nullable TaskAuthorizationProvider authorizationProvider) { this.authorizationProvider = authorizationProvider; }