Interface TaskAuthorizationProvider

All Known Implementing Classes:
TestTaskAuthorizationProvider_v0_3

public interface TaskAuthorizationProvider
SPI for per-user task authorization.

Implementers provide a CDI bean (@ApplicationScoped) implementing this interface to control which users can read, write, or create tasks. When no implementation is provided, all operations are permitted.

Providing an implementation

Create an @ApplicationScoped CDI bean that implements this interface. The SDK automatically discovers it and wires it into the request pipeline — no additional configuration is required.


 @ApplicationScoped
 public class MyTaskAuthorizationProvider implements TaskAuthorizationProvider {

     @Override
     public boolean checkRead(ServerCallContext context, String taskId, TaskOperation op) {
         User user = context.getUser();
         // look up ownership in your backing store
         return isOwner(user, taskId);
     }

     @Override
     public boolean checkWrite(ServerCallContext context, String taskId, TaskOperation op) {
         return checkRead(context, taskId, op); // same rule
     }

     @Override
     public boolean checkCreate(ServerCallContext context, TaskOperation op) {
         return context.getUser().isAuthenticated();
     }

     @Override
     public boolean isTaskRecorded(String taskId) {
         return ownershipStore.contains(taskId);
     }

     @Override
     public void recordOwnership(ServerCallContext context, String taskId, TaskOperation op) {
         ownershipStore.put(taskId, context.getUser().getUsername());
     }
 }
 

Behavior

When a provider is present, the SDK enforces authorization as follows:

Denied operations throw TaskNotFoundError — the caller cannot distinguish "does not exist" from "not authorized", preventing information leakage.

Thread safety

Implementations must be thread-safe. Methods will be called concurrently from multiple requests.

Ownership recording

recordOwnership(org.a2aproject.sdk.server.ServerCallContext, java.lang.String, org.a2aproject.sdk.server.auth.TaskOperation) is only triggered by onMessageSend and onMessageSendStream — the methods that can create tasks. Other methods (onGetTask, onCancelTask, etc.) do not trigger recording. checkRead(org.a2aproject.sdk.server.ServerCallContext, java.lang.String, org.a2aproject.sdk.server.auth.TaskOperation)/checkWrite(org.a2aproject.sdk.server.ServerCallContext, java.lang.String, org.a2aproject.sdk.server.auth.TaskOperation) may be called for tasks the provider has no ownership data for (e.g., legacy tasks created before the provider was enabled). For production deployments, a fail-closed policy is recommended: deny access when no ownership data exists. An owner == null → allow policy is only appropriate for testing or single-user deployments. If enabling the provider on an existing deployment, consider a migration step to backfill ownership for pre-existing tasks.

Common pitfalls

See Also:
  • Method Details

    • checkRead

      boolean checkRead(ServerCallContext context, String taskId, TaskOperation operation) throws A2AError
      Check whether the current user is allowed to read the given task.
      Parameters:
      context - the server call context containing the authenticated user
      taskId - the task being accessed
      operation - which RequestHandler method triggered the check
      Returns:
      true to allow, false to deny
      Throws:
      A2AError - if the authorization check itself fails
    • checkWrite

      boolean checkWrite(ServerCallContext context, String taskId, TaskOperation operation) throws A2AError
      Check whether the current user is allowed to write to the given task.
      Parameters:
      context - the server call context containing the authenticated user
      taskId - the task being accessed
      operation - which RequestHandler method triggered the check
      Returns:
      true to allow, false to deny
      Throws:
      A2AError - if the authorization check itself fails
    • checkCreate

      boolean checkCreate(ServerCallContext context, TaskOperation operation) throws A2AError
      Check whether the current user is allowed to create a new task.
      Parameters:
      context - the server call context containing the authenticated user
      operation - which RequestHandler method triggered the check
      Returns:
      true to allow, false to deny
      Throws:
      A2AError - if the authorization check itself fails
    • isTaskRecorded

      boolean isTaskRecorded(String taskId) throws A2AError
      Check whether the given task is already known to this provider. Used to avoid redundant recordOwnership(org.a2aproject.sdk.server.ServerCallContext, java.lang.String, org.a2aproject.sdk.server.auth.TaskOperation) calls.
      Parameters:
      taskId - the task to check
      Returns:
      true if ownership has already been recorded for this task
      Throws:
      A2AError - if the check itself fails
    • recordOwnership

      void recordOwnership(ServerCallContext context, String taskId, TaskOperation operation) throws A2AError
      Record that the current user owns the given task. Called after task creation via onMessageSend or onMessageSendStream.

      Must be idempotent. Concurrent requests for the same unrecorded task may both call this method before either completes.

      Parameters:
      context - the server call context containing the authenticated user
      taskId - the newly created task
      operation - which RequestHandler method triggered the recording
      Throws:
      A2AError - if recording fails