diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/SessionThreadFactory.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/SessionThreadFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ad030d347589313db481ff251b174b21f0c4db0c
--- /dev/null
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/SessionThreadFactory.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of vospace-ui
+ * Copyright (C) 2021 Istituto Nazionale di Astrofisica
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package it.inaf.ia2.vospace.ui;
+
+import java.util.concurrent.ThreadFactory;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+/**
+ * VOSpaceClient needs to extract the access token stored into the HTTP session
+ * and forward it to the VOSpace REST service. The client can retrieve the
+ * session from the autowired HttpServletRequest, however this doesn't work if
+ * the client is called from a standard new thread (for example when the client
+ * is invoked from a CompletableFuture), because Spring Context is missing and
+ * retrieval of the autowired HttpServletRequest proxy fails with the "No
+ * thread-bound request found" exception. Many CompletableFuture methods accept
+ * an Executor as parameter, so this ThreadFactory has been created in order to
+ * store the session in these particular threads. An Executor using this
+ * ThreadaFactory must be passed to the CompletableFuture. An alternative would
+ * be passing the original HttpServletRequest to all VOSpaceClient methods. A
+ * first attempt using the current executor (Runnable::run) shown that tasks
+ * where executed sequentially, so this dedicated Executor has been set up.
+ */
+public class SessionThreadFactory implements ThreadFactory {
+
+    private final HttpServletRequest request;
+
+    public SessionThreadFactory(HttpServletRequest request) {
+        this.request = request;
+    }
+
+    @Override
+    public Thread newThread(Runnable runnable) {
+        return new SessionThread(runnable, request);
+    }
+
+    public static class SessionThread extends Thread {
+
+        private final HttpSession session;
+
+        public SessionThread(Runnable runnable, HttpServletRequest request) {
+            super(runnable);
+            this.session = request.getSession(false);
+        }
+
+        public HttpSession getHttpSession() {
+            return this.session;
+        }
+    }
+}
diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/TokenProvider.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/TokenProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..f494da5b8494904c456baf60ac3ccf638379db33
--- /dev/null
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/TokenProvider.java
@@ -0,0 +1,32 @@
+/*
+ * This file is part of vospace-ui
+ * Copyright (C) 2021 Istituto Nazionale di Astrofisica
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package it.inaf.ia2.vospace.ui;
+
+import it.inaf.ia2.aa.data.User;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TokenProvider {
+
+    @Autowired
+    private HttpServletRequest request;
+
+    public Optional<String> getToken() {
+
+        HttpSession session = request.getSession(false);
+        if (session != null) {
+            User user = (User) session.getAttribute("user_data");
+            if (user != null) {
+                return Optional.of(user.getAccessToken());
+            }
+        }
+        return Optional.empty();
+    }
+}
diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/VOSpaceUiApplication.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/VOSpaceUiApplication.java
index f251deba7529a664c3d2d05d70526b7884b644fd..2ca025d6c19e163451cef466cf2d9f20b299de9d 100644
--- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/VOSpaceUiApplication.java
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/VOSpaceUiApplication.java
@@ -12,6 +12,8 @@ import it.inaf.ia2.aa.ServletRapClient;
 import it.inaf.ia2.aa.UserManager;
 import it.inaf.ia2.gms.client.GmsClient;
 import it.inaf.ia2.rap.client.ClientCredentialsRapClient;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 import java.util.concurrent.ForkJoinPool;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -66,6 +68,16 @@ public class VOSpaceUiApplication {
         return new ForkJoinPool(parallelism, threadFactory, null, false);
     }
 
+    /**
+     * Executor to pass to CompletableFuture methods to avoid
+     * "RejectedExecutionException: Thread limit exceeded replacing blocked
+     * worker".
+     */
+    @Bean
+    public Executor requestsExecutor() {
+        return Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+    }
+
     @Bean
     public RestTemplate restTemplate() {
         return new RestTemplate();
diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/client/VOSpaceClient.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/client/VOSpaceClient.java
index 4a33a42c2a5052b28686c7cc05b4190d08bd057d..690a3cbaeec03ef3b4679d8e0f5f7b4a220b9a15 100644
--- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/client/VOSpaceClient.java
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/client/VOSpaceClient.java
@@ -6,7 +6,6 @@
 package it.inaf.ia2.vospace.ui.client;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import it.inaf.ia2.aa.data.User;
 import it.inaf.ia2.vospace.ui.VOSpaceUiApplication;
 import it.inaf.ia2.vospace.ui.data.Job;
 import it.inaf.ia2.vospace.ui.exception.BadRequestException;
@@ -35,8 +34,6 @@ import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
 import javax.xml.bind.JAXB;
 import net.ivoa.xml.uws.v1.ExecutionPhase;
 import net.ivoa.xml.uws.v1.JobSummary;
@@ -46,7 +43,6 @@ import net.ivoa.xml.vospace.v2.Protocol;
 import net.ivoa.xml.vospace.v2.Transfer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
@@ -64,9 +60,6 @@ public class VOSpaceClient {
     private final String baseUrl;
     private final ForkJoinPool jaxbExecutor;
 
-    @Autowired
-    protected HttpServletRequest servletRequest;
-
     public VOSpaceClient(@Value("${vospace-backend-url}") String backendUrl) {
         if (backendUrl.endsWith("/")) {
             // Remove final slash from configured URL
@@ -82,22 +75,18 @@ public class VOSpaceClient {
                 .build();
     }
 
-    public Node getNode(String path) {
-        return getNode(path, Optional.empty());
-    }
-
-    public Node getNode(String path, Optional<String> adminToken) {
+    public Node getNode(String path, Optional<String> token) {
 
-        HttpRequest request = getRequest("/nodes" + urlEncodePath(path), adminToken)
+        HttpRequest request = getRequest("/nodes" + urlEncodePath(path), token)
                 .header("Accept", useJson ? "application/json" : "text/xml")
                 .build();
 
         return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, Node.class));
     }
 
-    public JobSummary startTransferJob(Transfer transfer) {
+    public JobSummary startTransferJob(Transfer transfer, Optional<String> token) {
 
-        HttpRequest request = getRequest("/transfers?PHASE=RUN")
+        HttpRequest request = getRequest("/transfers?PHASE=RUN", token)
                 .header("Accept", useJson ? "application/json" : "text/xml")
                 .header("Content-Type", useJson ? "application/json" : "text/xml")
                 .POST(HttpRequest.BodyPublishers.ofString(marshal(transfer)))
@@ -106,9 +95,9 @@ public class VOSpaceClient {
         return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, JobSummary.class));
     }
 
-    public String getFileServiceEndpoint(Transfer transfer) {
+    public String getFileServiceEndpoint(Transfer transfer, Optional<String> token) {
 
-        HttpRequest request = getRequest("/synctrans")
+        HttpRequest request = getRequest("/synctrans", token)
                 .header("Accept", useJson ? "application/json" : "text/xml")
                 .header("Content-Type", useJson ? "application/json" : "text/xml")
                 .POST(HttpRequest.BodyPublishers.ofString(marshal(transfer)))
@@ -131,7 +120,7 @@ public class VOSpaceClient {
                 Matcher matcher = pattern.matcher(url);
                 if (matcher.matches()) {
                     String jobId = matcher.group(1);
-                    String errorDetail = getErrorDetail(jobId);
+                    String errorDetail = getErrorDetail(jobId, token);
                     if (!errorDetail.isBlank()) {
                         throw new BadRequestException(errorDetail);
                     }
@@ -142,15 +131,11 @@ public class VOSpaceClient {
         return protocols.get(0).getEndpoint();
     }
 
-    public Node createNode(Node node) {
-        return createNode(node, Optional.empty());
-    }
-
-    public Node createNode(Node node, Optional<String> adminToken) {
+    public Node createNode(Node node, Optional<String> token) {
 
         String path = NodeUtils.getVosPath(node);
 
-        HttpRequest request = getRequest("/nodes" + urlEncodePath(path), adminToken)
+        HttpRequest request = getRequest("/nodes" + urlEncodePath(path), token)
                 .header("Accept", useJson ? "application/json" : "text/xml")
                 .header("Content-Type", useJson ? "application/json" : "text/xml")
                 .PUT(HttpRequest.BodyPublishers.ofString(marshal(node)))
@@ -159,9 +144,9 @@ public class VOSpaceClient {
         return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, Node.class));
     }
 
-    public void deleteNode(String path) {
+    public void deleteNode(String path, Optional<String> token) {
 
-        HttpRequest request = getRequest("/nodes" + urlEncodePath(path))
+        HttpRequest request = getRequest("/nodes" + urlEncodePath(path), token)
                 .header("Accept", useJson ? "application/json" : "text/xml")
                 .header("Content-Type", useJson ? "application/json" : "text/xml")
                 .DELETE()
@@ -170,15 +155,11 @@ public class VOSpaceClient {
         call(request, BodyHandlers.ofInputStream(), 200, res -> null);
     }
 
-    public Node setNode(Node node, boolean recursive) {
-        return setNode(node, recursive, Optional.empty());
-    }
-
-    public Node setNode(Node node, boolean recursive, Optional<String> adminToken) {
+    public Node setNode(Node node, boolean recursive, Optional<String> token) {
 
         String path = NodeUtils.getVosPath(node);
 
-        HttpRequest request = getRequest("/nodes" + urlEncodePath(path) + "?recursive=" + recursive, adminToken)
+        HttpRequest request = getRequest("/nodes" + urlEncodePath(path) + "?recursive=" + recursive, token)
                 .header("Accept", useJson ? "application/json" : "text/xml")
                 .header("Content-Type", useJson ? "application/json" : "text/xml")
                 .POST(HttpRequest.BodyPublishers.ofString(marshal(node)))
@@ -187,20 +168,20 @@ public class VOSpaceClient {
         return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, Node.class));
     }
 
-    public List<Job> getAsyncRecallJobs() {
-        return getJobs("direction=pullToVoSpace", Job.JobType.ASYNC_RECALL);
+    public List<Job> getAsyncRecallJobs(Optional<String> token) {
+        return getJobs("direction=pullToVoSpace", Job.JobType.ASYNC_RECALL, token);
     }
 
-    public List<Job> getArchiveJobs() {
+    public List<Job> getArchiveJobs(Optional<String> token) {
         return getJobs("direction=pullFromVoSpace"
                 + "&VIEW=ivo://ia2.inaf.it/vospace/views%23tar"
                 + "&VIEW=ivo://ia2.inaf.it/vospace/views%23zip",
-                Job.JobType.ARCHIVE);
+                Job.JobType.ARCHIVE, token);
     }
 
-    private List<Job> getJobs(String queryString, Job.JobType type) {
+    private List<Job> getJobs(String queryString, Job.JobType type, Optional<String> token) {
 
-        HttpRequest request = getRequest("/transfers?" + queryString)
+        HttpRequest request = getRequest("/transfers?" + queryString, token)
                 .header("Accept", useJson ? "application/json" : "text/xml")
                 .header("Content-Type", useJson ? "application/json" : "text/xml")
                 .GET()
@@ -213,25 +194,25 @@ public class VOSpaceClient {
         });
     }
 
-    public String getArchiveJobHref(String jobId) {
-        List<Protocol> protocols = getTransferDetails(jobId).getProtocols();
+    public String getArchiveJobHref(String jobId, Optional<String> token) {
+        List<Protocol> protocols = getTransferDetails(jobId, token).getProtocols();
         if (!protocols.isEmpty()) {
             return protocols.get(0).getEndpoint();
         }
         return null;
     }
 
-    private Transfer getTransferDetails(String jobId) {
+    private Transfer getTransferDetails(String jobId, Optional<String> token) {
 
-        HttpRequest request = getRequest("/transfers/" + jobId + "/results/transferDetails")
+        HttpRequest request = getRequest("/transfers/" + jobId + "/results/transferDetails", token)
                 .GET().build();
 
         return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, Transfer.class));
     }
 
-    public ExecutionPhase getJobPhase(String jobId) {
+    public ExecutionPhase getJobPhase(String jobId, Optional<String> token) {
 
-        HttpRequest request = getRequest("/transfers/" + jobId + "/phase")
+        HttpRequest request = getRequest("/transfers/" + jobId + "/phase", token)
                 .GET()
                 .build();
 
@@ -244,9 +225,9 @@ public class VOSpaceClient {
         });
     }
 
-    public String getErrorDetail(String jobId) {
+    public String getErrorDetail(String jobId, Optional<String> token) {
 
-        HttpRequest request = getRequest("/transfers/" + jobId + "/error")
+        HttpRequest request = getRequest("/transfers/" + jobId + "/error", token)
                 .header("Accept", "text/plain")
                 .GET()
                 .build();
@@ -291,30 +272,14 @@ public class VOSpaceClient {
         }
     }
 
-    private HttpRequest.Builder getRequest(String path) {
-        return getRequest(path, Optional.empty());
-    }
-
-    private HttpRequest.Builder getRequest(String path, Optional<String> adminToken) {
+    private HttpRequest.Builder getRequest(String path, Optional<String> token) {
         HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(baseUrl + path));
-        String token = adminToken.orElseGet(() -> getToken());
-        if (token != null) {
-            builder.setHeader("Authorization", "Bearer " + token);
+        if (token.isPresent()) {
+            builder.setHeader("Authorization", "Bearer " + token.get());
         }
         return builder;
     }
 
-    private String getToken() {
-        HttpSession session = servletRequest.getSession(false);
-        if (session != null) {
-            User user = (User) session.getAttribute("user_data");
-            if (user != null) {
-                return user.getAccessToken();
-            }
-        }
-        return null;
-    }
-
     private <T> T unmarshal(InputStream in, Class<T> type) {
         try {
             if (useJson) {
diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/CreateLinksController.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/CreateLinksController.java
index b3dfe7fc7e1e36bfe45dbbde519cc426c8933c6b..2e1700d4cb3e5350042ee109515ace8a8f511a76 100644
--- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/CreateLinksController.java
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/CreateLinksController.java
@@ -5,6 +5,7 @@
  */
 package it.inaf.ia2.vospace.ui.controller;
 
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.data.CreateLinkRequest;
 import it.inaf.ia2.vospace.ui.exception.BadRequestException;
@@ -14,7 +15,9 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
 import net.ivoa.xml.vospace.v2.ContainerNode;
 import net.ivoa.xml.vospace.v2.LinkNode;
 import org.slf4j.Logger;
@@ -40,10 +43,18 @@ public class CreateLinksController extends BaseController {
     @Autowired
     private VOSpaceClient client;
 
+    @Autowired
+    private TokenProvider tokenProvider;
+
+    @Autowired
+    private Executor requestsExecutor;
+
     @PostMapping(value = "/createLink", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<?> createLink(@RequestBody CreateLinkRequest request) {
 
-        ContainerNode parent = getFolder(request.getFolder());
+        Optional<String> token = tokenProvider.getToken();
+
+        ContainerNode parent = getFolder(request.getFolder(), token);
 
         String uri = parent.getUri() + "/" + request.getNodeName();
 
@@ -51,7 +62,7 @@ public class CreateLinksController extends BaseController {
         link.setUri(uri);
         link.setTarget(request.getUrl());
 
-        client.createNode(link);
+        client.createNode(link, token);
 
         return ResponseEntity.noContent().build();
     }
@@ -60,7 +71,9 @@ public class CreateLinksController extends BaseController {
     public ResponseEntity<?> uploadLinks(@RequestParam(value = "file", required = true) MultipartFile file,
             @RequestParam("folder") String folder) throws IOException {
 
-        ContainerNode parent = getFolder(folder);
+        Optional<String> token = tokenProvider.getToken();
+
+        ContainerNode parent = getFolder(folder, token);
 
         String fileContent = new String(file.getBytes());
 
@@ -90,7 +103,7 @@ public class CreateLinksController extends BaseController {
                     httpCallsGroups.add(currentHttpCallsGroup);
                 }
 
-                currentHttpCallsGroup.add(CompletableFuture.supplyAsync(() -> client.createNode(link), Runnable::run));
+                currentHttpCallsGroup.add(CompletableFuture.supplyAsync(() -> client.createNode(link, token), requestsExecutor));
             }
         }
 
@@ -123,9 +136,9 @@ public class CreateLinksController extends BaseController {
         }
     }
 
-    private ContainerNode getFolder(String folderPath) {
+    private ContainerNode getFolder(String folderPath, Optional<String> token) {
         try {
-            return (ContainerNode) client.getNode("/" + folderPath);
+            return (ContainerNode) client.getNode("/" + folderPath, token);
         } catch (VOSpaceStatusException ex) {
             if (ex.getHttpStatus() == 404) {
                 throw new BadRequestException("Folder parameter specified a non-existent folder: /" + folderPath);
diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/DownloadController.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/DownloadController.java
index 381dd858e7194af5a8d009d5a1965fa2fe563ce4..faaf782042c926c73233ca1c2cf36d83ec7e28c0 100644
--- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/DownloadController.java
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/DownloadController.java
@@ -8,6 +8,7 @@ package it.inaf.ia2.vospace.ui.controller;
 import it.inaf.ia2.aa.ServletRapClient;
 import it.inaf.ia2.aa.data.User;
 import it.inaf.ia2.rap.client.call.TokenExchangeRequest;
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.exception.PermissionDeniedException;
 import it.inaf.oats.vospace.datamodel.NodeUtils;
@@ -43,6 +44,9 @@ public class DownloadController {
     @Autowired
     private ServletRapClient rapClient;
 
+    @Autowired
+    private TokenProvider tokenProvider;
+
     @GetMapping(value = "/download/**")
     public ResponseEntity<?> directDownload() {
 
@@ -61,7 +65,7 @@ public class DownloadController {
         httpsProtocol.setUri("ivo://ivoa.net/vospace/core#httpsget");
         transfer.getProtocols().add(httpsProtocol);
 
-        String url = client.getFileServiceEndpoint(transfer);
+        String url = client.getFileServiceEndpoint(transfer, tokenProvider.getToken());
         HttpHeaders headers = new HttpHeaders();
         headers.set("Location", url);
         return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER);
@@ -78,7 +82,7 @@ public class DownloadController {
             throw new PermissionDeniedException("Token is null");
         }
 
-        String endpoint = client.getArchiveJobHref(jobId);
+        String endpoint = client.getArchiveJobHref(jobId, tokenProvider.getToken());
 
         TokenExchangeRequest exchangeRequest = new TokenExchangeRequest()
                 .setSubjectToken(token)
diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/JobController.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/JobController.java
index d185feb8cf513af4035b2edeecf389b13563147b..87fb86559e94c431cb5c7354a86ba1674e472cc3 100644
--- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/JobController.java
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/JobController.java
@@ -5,13 +5,16 @@
  */
 package it.inaf.ia2.vospace.ui.controller;
 
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.data.Job;
 import it.inaf.ia2.vospace.ui.exception.BadRequestException;
 import it.inaf.oats.vospace.datamodel.Views;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
 import net.ivoa.xml.uws.v1.ErrorType;
 import net.ivoa.xml.uws.v1.ExecutionPhase;
 import net.ivoa.xml.uws.v1.JobSummary;
@@ -40,6 +43,12 @@ public class JobController extends BaseController {
     @Autowired
     private VOSpaceClient client;
 
+    @Autowired
+    private TokenProvider tokenProvider;
+
+    @Autowired
+    private Executor requestsExecutor;
+
     @PostMapping(value = "/recall", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<Job> startRecallFromTapeJob(@RequestBody List<String> paths) {
 
@@ -67,7 +76,9 @@ public class JobController extends BaseController {
             }
         }
 
-        JobSummary job = client.startTransferJob(transfer);
+        Optional<String> token = tokenProvider.getToken();
+
+        JobSummary job = client.startTransferJob(transfer, token);
 
         if (job.getPhase() == ExecutionPhase.QUEUED
                 || job.getPhase() == ExecutionPhase.PENDING
@@ -78,7 +89,7 @@ public class JobController extends BaseController {
         if (job.getPhase() == ExecutionPhase.ERROR) {
             if (job.getErrorSummary() != null) {
                 if (job.getErrorSummary().isHasDetail()) {
-                    errorMessage = client.getErrorDetail(job.getJobId());
+                    errorMessage = client.getErrorDetail(job.getJobId(), token);
                 } else {
                     errorMessage = job.getErrorSummary().getMessage();
                 }
@@ -102,13 +113,13 @@ public class JobController extends BaseController {
     @GetMapping(value = "/jobs", produces = MediaType.APPLICATION_JSON_VALUE)
     public List<Job> getJobs() throws Exception {
 
+        Optional<String> token = tokenProvider.getToken();
+
         CompletableFuture<List<Job>> asyncRecallJobsCall
-                = CompletableFuture.supplyAsync(() -> client.getAsyncRecallJobs(),
-                        Runnable::run);
+                = CompletableFuture.supplyAsync(() -> client.getAsyncRecallJobs(token), requestsExecutor);
 
         CompletableFuture<List<Job>> archiveJobsCall
-                = CompletableFuture.supplyAsync(() -> client.getArchiveJobs(),
-                        Runnable::run);
+                = CompletableFuture.supplyAsync(() -> client.getArchiveJobs(token), requestsExecutor);
 
         CompletableFuture.allOf(asyncRecallJobsCall, archiveJobsCall).join();
 
diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/NodesController.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/NodesController.java
index 50be555ca32b26f7a02967437a662f64cbb4b0cd..f0fa03564b39a4d9544801bce372311bd66d79d6 100644
--- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/NodesController.java
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/NodesController.java
@@ -6,6 +6,7 @@
 package it.inaf.ia2.vospace.ui.controller;
 
 import it.inaf.ia2.aa.data.User;
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.data.Job;
 import it.inaf.ia2.vospace.ui.data.ListNodeData;
@@ -26,6 +27,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -70,6 +72,12 @@ public class NodesController extends BaseController {
     @Autowired
     private HttpServletRequest servletRequest;
 
+    @Autowired
+    private TokenProvider tokenProvider;
+
+    @Autowired
+    private Executor requestsExecutor;
+
     @GetMapping(value = {"/nodes", "/nodes/**"}, produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<ListNodeData> listNodes(User principal) throws Exception {
 
@@ -80,7 +88,7 @@ public class NodesController extends BaseController {
 
         Node node;
         try {
-            node = client.getNode(path);
+            node = client.getNode(path, tokenProvider.getToken());
         } catch (VOSpaceStatusException ex) {
             if (ex.getHttpStatus() == 403) {
                 String message = "You cannot access this node";
@@ -109,7 +117,7 @@ public class NodesController extends BaseController {
 
         ListNodeData listNodeData = new ListNodeData();
 
-        Node node = client.getNode(path);
+        Node node = client.getNode(path, tokenProvider.getToken());
 
         listNodeData.setWritable(NodeUtils.checkIfWritable(node, principal.getName(), principal.getGroups()));
 
@@ -133,13 +141,15 @@ public class NodesController extends BaseController {
             // a container, a VOSpace file or an external file
             List<CompletableFuture<Node>> nodesCalls = new ArrayList<>();
 
+            Optional<String> token = tokenProvider.getToken();
+
             for (LinkNode linkNode : linksToLoad) {
                 String prefix = "vos://" + authority;
                 if (linkNode.getTarget().startsWith(prefix)) {
                     String linkPath = StringUtils.uriDecode(linkNode.getTarget(), StandardCharsets.UTF_8)
                             .substring(prefix.length());
 
-                    nodesCalls.add(CompletableFuture.supplyAsync(() -> client.getNode(linkPath), Runnable::run)
+                    nodesCalls.add(CompletableFuture.supplyAsync(() -> client.getNode(linkPath, token), requestsExecutor)
                             .exceptionally(ex -> null)); // null is returned in case of broken link
                 } else {
                     linkedNodes.add(linkNode);
@@ -183,18 +193,20 @@ public class NodesController extends BaseController {
         creator.setValue(getUser().getName());
         node.getProperties().add(creator);
 
-        client.createNode(node);
+        client.createNode(node, tokenProvider.getToken());
     }
 
     @PostMapping(value = "/delete", consumes = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<?> deleteNodes(@RequestBody List<String> nodesToDelete) {
 
+        Optional<String> token = tokenProvider.getToken();
+
         CompletableFuture[] deleteCalls = nodesToDelete.stream()
                 .map(nodeToDelete -> {
                     return CompletableFuture.runAsync(() -> {
                         LOG.debug("deleteNode called for path {}", nodeToDelete);
-                        client.deleteNode(nodeToDelete);
-                    }, Runnable::run);
+                        client.deleteNode(nodeToDelete, token);
+                    }, requestsExecutor);
                 })
                 .collect(Collectors.toList())
                 .toArray(CompletableFuture[]::new);
@@ -249,7 +261,7 @@ public class NodesController extends BaseController {
         protocol.setUri("ivo://ivoa.net/vospace/core#httpget");
         transfer.getProtocols().add(protocol);
 
-        return new Job(client.startTransferJob(transfer), Job.JobType.ARCHIVE);
+        return new Job(client.startTransferJob(transfer, tokenProvider.getToken()), Job.JobType.ARCHIVE);
     }
 
     private String getUri(String path) {
@@ -285,6 +297,8 @@ public class NodesController extends BaseController {
     @PostMapping(value = "/moveOrCopy")
     public ResponseEntity<List<Job>> moveOrCopyNodes(@RequestBody MoveOrCopyRequest request) throws Exception {
 
+        Optional<String> token = tokenProvider.getToken();
+
         // Creates a transfer request for each copy or move operation
         CompletableFuture<JobSummary>[] futureJobs = request.getTargets().stream().map(t -> {
             String target = urlEncodePath(t);
@@ -293,7 +307,7 @@ public class NodesController extends BaseController {
             transfer.setTarget("vos://" + authority + target);
             transfer.setDirection("vos://" + authority + direction);
             transfer.setKeepBytes(request.isKeepBytes());
-            return CompletableFuture.supplyAsync(() -> client.startTransferJob(transfer), Runnable::run);
+            return CompletableFuture.supplyAsync(() -> client.startTransferJob(transfer, token), requestsExecutor);
         }).collect(Collectors.toList()).toArray(CompletableFuture[]::new);
 
         // starts all HTTP requests in parallel
@@ -321,7 +335,7 @@ public class NodesController extends BaseController {
 
         try {
             // performs polling of job statuses or timeout
-            CompletableFuture.anyOf(jobsPolling(jobs, cancelled), timeout).join();
+            CompletableFuture.anyOf(jobsPolling(jobs, cancelled, token), timeout).join();
         } catch (CompletionException ex) {
             if (ex.getCause() != null && ex.getCause() instanceof VOSpaceException) {
                 throw (VOSpaceException) ex.getCause();
@@ -335,7 +349,7 @@ public class NodesController extends BaseController {
                 .collect(Collectors.toList()));
     }
 
-    private CompletableFuture<?> jobsPolling(List<JobSummary> jobs, AtomicReference<Boolean> cancelled) {
+    private CompletableFuture<?> jobsPolling(List<JobSummary> jobs, AtomicReference<Boolean> cancelled, Optional<String> token) {
         return CompletableFuture.runAsync(() -> {
 
             List<JobSummary> uncompletedJobs;
@@ -350,22 +364,23 @@ public class NodesController extends BaseController {
                     } catch (InterruptedException ex) {
                         break;
                     }
-                    updatePhases(uncompletedJobs);
+                    updatePhases(uncompletedJobs, token);
                 }
             } while (!uncompletedJobs.isEmpty() && !cancelled.get());
-        }, Runnable::run);
+        }, requestsExecutor);
     }
 
-    private void updatePhases(List<JobSummary> uncompletedJobs) {
+    private void updatePhases(List<JobSummary> uncompletedJobs, Optional<String> token) {
+
         CompletableFuture[] phaseFutures = uncompletedJobs.stream()
                 .map(job -> CompletableFuture.runAsync(() -> {
-            ExecutionPhase phase = client.getJobPhase(job.getJobId());
+            ExecutionPhase phase = client.getJobPhase(job.getJobId(), token);
             if (phase == ExecutionPhase.ERROR) {
-                String errorDetail = client.getErrorDetail(job.getJobId());
+                String errorDetail = client.getErrorDetail(job.getJobId(), token);
                 throw new VOSpaceException("Operation failed: " + errorDetail);
             }
             job.setPhase(phase);
-        }, Runnable::run)).collect(Collectors.toList()).toArray(CompletableFuture[]::new);
+        }, requestsExecutor)).collect(Collectors.toList()).toArray(CompletableFuture[]::new);
 
         CompletableFuture.allOf(phaseFutures).join();
     }
diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/UploadController.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/UploadController.java
index 7ddce8eebf291b00147254beac5200bd46fbc5a3..96ab24065321cb09cc139feaed518a6682617451 100644
--- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/UploadController.java
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/UploadController.java
@@ -5,6 +5,7 @@
  */
 package it.inaf.ia2.vospace.ui.controller;
 
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.data.PreUploadResult;
 import it.inaf.ia2.vospace.ui.data.UploadFilesData;
@@ -14,7 +15,9 @@ import it.inaf.ia2.vospace.ui.exception.VOSpaceStatusException;
 import static it.inaf.oats.vospace.datamodel.NodeUtils.urlEncodePath;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
 import javax.validation.Valid;
 import net.ivoa.xml.vospace.v2.DataNode;
@@ -42,15 +45,23 @@ public class UploadController extends BaseController {
     @Autowired
     private VOSpaceClient client;
 
+    @Autowired
+    private TokenProvider tokenProvider;
+
+    @Autowired
+    private Executor requestsExecutor;
+
     @PostMapping(value = "/preupload", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<List<PreUploadResult>> prepareForUpload(@RequestBody @Valid UploadFilesData data) {
 
-        if (getUser() == null) {
+        Optional<String> token = tokenProvider.getToken();
+
+        if (token.isEmpty()) {
             throw new PermissionDeniedException("File upload not allowed to anonymous users");
         }
 
         CompletableFuture<PreUploadResult>[] calls
-                = data.getFiles().stream().map(fileName -> prepareForDownload(getParentPath(data), fileName))
+                = data.getFiles().stream().map(fileName -> prepareForDownload(getParentPath(data), fileName, token))
                         .toArray(CompletableFuture[]::new);
 
         List<PreUploadResult> uploadUrls = CompletableFuture.allOf(calls)
@@ -69,7 +80,9 @@ public class UploadController extends BaseController {
         return parentPath;
     }
 
-    public CompletableFuture<PreUploadResult> prepareForDownload(String parentPath, String fileName) {
+    public CompletableFuture<PreUploadResult> prepareForDownload(String parentPath, String fileName, Optional<String> token) {
+
+        String userName = getUser().getName();
 
         return CompletableFuture.supplyAsync(() -> {
 
@@ -85,7 +98,7 @@ public class UploadController extends BaseController {
             PreUploadResult result = new PreUploadResult();
 
             try {
-                createDataNode(nodeUri, getUser().getName());
+                createDataNode(nodeUri, userName, token);
             } catch (Throwable t) {
                 if (t instanceof VOSpaceStatusException && ((VOSpaceStatusException) t).getHttpStatus() == 409) {
                     result.setError("Node already exists");
@@ -97,7 +110,7 @@ public class UploadController extends BaseController {
             }
 
             try {
-                String uploadUrl = obtainUploadUrl(nodeUri);
+                String uploadUrl = obtainUploadUrl(nodeUri, token);
                 result.setUrl(uploadUrl);
             } catch (Throwable t) {
                 if (t instanceof VOSpaceException) {
@@ -109,17 +122,17 @@ public class UploadController extends BaseController {
 
                 try {
                     // attempt to cleanup node metadata
-                    client.deleteNode(path);
+                    client.deleteNode(path, token);
                 } catch (Throwable dt) {
                     LOG.error("Unable to remove node after failed upload URL retrieval", dt);
                     result.setError("Retrieval of upload URL failed. Manual cleanup of node metadata may be necessary");
                 }
             }
             return result;
-        }, Runnable::run); // Passing current thread Executor to CompletableFuture to avoid "No thread-bound request found" exception
+        }, requestsExecutor);
     }
 
-    private void createDataNode(String nodeUri, String userId) {
+    private void createDataNode(String nodeUri, String userId, Optional<String> token) {
 
         DataNode node = new DataNode();
         node.setUri(nodeUri);
@@ -130,10 +143,10 @@ public class UploadController extends BaseController {
 
         node.getProperties().add(creator);
 
-        client.createNode(node);
+        client.createNode(node, token);
     }
 
-    private String obtainUploadUrl(String uri) {
+    private String obtainUploadUrl(String uri, Optional<String> token) {
 
         Transfer transfer = new Transfer();
         transfer.setDirection("pushToVoSpace");
@@ -143,6 +156,6 @@ public class UploadController extends BaseController {
         protocol.setUri("ivo://ivoa.net/vospace/core#httpput");
         transfer.getProtocols().add(protocol);
 
-        return client.getFileServiceEndpoint(transfer);
+        return client.getFileServiceEndpoint(transfer, token);
     }
 }
diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/SharingService.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/SharingService.java
index 0bfedd6f2d375355e213084d3096761de36e5b8b..37bf7283809e236bf21757a8754b05252eeafddc 100644
--- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/SharingService.java
+++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/SharingService.java
@@ -12,6 +12,7 @@ import it.inaf.ia2.rap.data.Identity;
 import it.inaf.ia2.rap.data.IdentityType;
 import it.inaf.ia2.rap.data.RapUser;
 import it.inaf.ia2.rap.data.TokenContext;
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.data.ShareRequest;
 import it.inaf.ia2.vospace.ui.data.SharingInfo;
@@ -64,15 +65,18 @@ public class SharingService {
     private final GmsClient gmsClient;
     private final ClientCredentialsRapClient rapClient;
     private final VOSpaceClient vospaceClient;
+    private final TokenProvider tokenProvider;
 
     private TokenContext tokenContext;
     private Date lastUpdate;
 
     @Autowired
-    public SharingService(GmsClient gmsClient, ClientCredentialsRapClient gmsRapClient, VOSpaceClient vospaceClient) {
+    public SharingService(GmsClient gmsClient, ClientCredentialsRapClient gmsRapClient,
+            VOSpaceClient vospaceClient, TokenProvider tokenProvider) {
         this.gmsClient = gmsClient;
         this.rapClient = gmsRapClient;
         this.vospaceClient = vospaceClient;
+        this.tokenProvider = tokenProvider;
     }
 
     public SharingInfo getSharingInfo() {
@@ -105,11 +109,13 @@ public class SharingService {
         String groupRead = getGroupString(shareRequest.getGroupRead(), shareRequest.getUserRead());
         String groupWrite = getGroupString(shareRequest.getGroupWrite(), shareRequest.getUserWrite());
 
-        Node node = vospaceClient.getNode(shareRequest.getPath());
+        Optional<String> token = tokenProvider.getToken();
+
+        Node node = vospaceClient.getNode(shareRequest.getPath(), token);
         getNodeProperty(node, NodeProperties.GROUP_READ_URI).setValue(groupRead);
         getNodeProperty(node, NodeProperties.GROUP_WRITE_URI).setValue(groupWrite);
 
-        vospaceClient.setNode(node, shareRequest.isRecursive());
+        vospaceClient.setNode(node, shareRequest.isRecursive(), token);
 
         if (shareRequest.getNewPeople() != null && !shareRequest.getNewPeople().isEmpty()) {
             createSharedLinks(shareRequest);
diff --git a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/client/VOSpaceClientTest.java b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/client/VOSpaceClientTest.java
index 899855046b9876a64ecd983a0ddabe5cf9b435fb..a5f6204a7dd5613333a8ac8d34567f9df1700148 100644
--- a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/client/VOSpaceClientTest.java
+++ b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/client/VOSpaceClientTest.java
@@ -5,6 +5,7 @@
  */
 package it.inaf.ia2.vospace.ui.client;
 
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.exception.BadRequestException;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -17,7 +18,6 @@ import java.net.http.HttpResponse;
 import java.nio.charset.StandardCharsets;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
-import javax.servlet.http.HttpServletRequest;
 import net.ivoa.xml.uws.v1.ExecutionPhase;
 import net.ivoa.xml.vospace.v2.ContainerNode;
 import net.ivoa.xml.vospace.v2.Protocol;
@@ -58,8 +58,6 @@ public class VOSpaceClientTest {
             staticMock.when(HttpClient::newBuilder).thenReturn(builder);
             voSpaceClient = new VOSpaceClient("http://localhost/vospace");
         }
-
-        voSpaceClient.servletRequest = mock(HttpServletRequest.class);
     }
 
     @Test
@@ -69,7 +67,7 @@ public class VOSpaceClientTest {
         CompletableFuture response = getMockedStreamResponseFuture(200, getResourceFileContent("nodes-response.xml"));
         when(mockedHttpClient.sendAsync(any(), any())).thenReturn(response);
 
-        ContainerNode node = (ContainerNode) voSpaceClient.getNode("/node1");
+        ContainerNode node = (ContainerNode) voSpaceClient.getNode("/node1", Optional.empty());
         assertEquals("vos://ia2.inaf.it!vospace/node1", node.getUri());
     }
 
@@ -87,7 +85,7 @@ public class VOSpaceClientTest {
         ContainerNode newNode = new ContainerNode();
         newNode.setUri("vos://ia2.inaf.it!vospace/mynode/newnode");
 
-        ContainerNode responseNode = (ContainerNode) voSpaceClient.createNode(newNode);
+        ContainerNode responseNode = (ContainerNode) voSpaceClient.createNode(newNode, Optional.empty());
         assertEquals(newNode.getUri(), responseNode.getUri());
     }
 
@@ -98,7 +96,7 @@ public class VOSpaceClientTest {
         newNode.setUri("vos://ia2.inaf.it!vospace/mynode/spaces not encoded");
 
         try {
-            voSpaceClient.createNode(newNode);
+            voSpaceClient.createNode(newNode, Optional.empty());
             fail("Exception was expected");
         } catch (RuntimeException ex) {
             assertTrue(ex.getCause() instanceof URISyntaxException);
@@ -111,7 +109,7 @@ public class VOSpaceClientTest {
         CompletableFuture response = getMockedStringResponseFuture(200, "error message");
         when(mockedHttpClient.sendAsync(any(), any())).thenReturn(response);
 
-        assertEquals("error message", voSpaceClient.getErrorDetail("123"));
+        assertEquals("error message", voSpaceClient.getErrorDetail("123", Optional.empty()));
     }
 
     @Test
@@ -128,7 +126,7 @@ public class VOSpaceClientTest {
         CompletableFuture response = getMockedStreamResponseFuture(200, getResourceFileContent("transfer-response-ok.xml"));
         when(mockedHttpClient.sendAsync(any(), any())).thenReturn(response);
 
-        assertEquals("http://storage1.example.com/trans/mynode", voSpaceClient.getFileServiceEndpoint(transfer));
+        assertEquals("http://storage1.example.com/trans/mynode", voSpaceClient.getFileServiceEndpoint(transfer, Optional.empty()));
     }
 
     @Test
@@ -155,7 +153,7 @@ public class VOSpaceClientTest {
         when(mockedHttpClient.sendAsync(any(), any())).thenReturn(response1).thenReturn(response2);
 
         BadRequestException ex = assertThrows(BadRequestException.class, () -> {
-            voSpaceClient.getFileServiceEndpoint(transfer);
+            voSpaceClient.getFileServiceEndpoint(transfer, Optional.empty());
         });
         assertEquals("error message", ex.getMessage());
     }
@@ -184,7 +182,7 @@ public class VOSpaceClientTest {
         when(mockedHttpClient.sendAsync(any(), any())).thenReturn(response1).thenReturn(response2);
 
         BadRequestException ex = assertThrows(BadRequestException.class, () -> {
-            voSpaceClient.getFileServiceEndpoint(transfer);
+            voSpaceClient.getFileServiceEndpoint(transfer, Optional.empty());
         });
         assertEquals("Protocol negotiation failed", ex.getMessage());
     }
@@ -195,7 +193,7 @@ public class VOSpaceClientTest {
         CompletableFuture response = getMockedStreamResponseFuture(200, "COMPLETED");
         when(mockedHttpClient.sendAsync(any(), any())).thenReturn(response);
 
-        assertEquals(ExecutionPhase.COMPLETED, voSpaceClient.getJobPhase("job_id"));
+        assertEquals(ExecutionPhase.COMPLETED, voSpaceClient.getJobPhase("job_id", Optional.empty()));
     }
 
     @Test
@@ -207,7 +205,7 @@ public class VOSpaceClientTest {
         CompletableFuture response = getMockedStreamResponseFuture(200, getResourceFileContent("node-response.xml"));
         when(mockedHttpClient.sendAsync(any(), any())).thenReturn(response);
 
-        voSpaceClient.setNode(node, true);
+        voSpaceClient.setNode(node, true, Optional.empty());
 
         // verifying proper URL encoding of + char
         verify(mockedHttpClient).sendAsync(argThat(req -> {
@@ -221,7 +219,7 @@ public class VOSpaceClientTest {
         CompletableFuture response = getMockedStreamResponseFuture(200, "");
         when(mockedHttpClient.sendAsync(any(), any())).thenReturn(response);
 
-        voSpaceClient.deleteNode("/not urlencoded");
+        voSpaceClient.deleteNode("/not urlencoded", Optional.of("<token>"));
     }
 
     protected static String getResourceFileContent(String fileName) {
diff --git a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/CreateLinksControllerTest.java b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/CreateLinksControllerTest.java
index 92c56f37b89ce9095db770d5d8a58e844be22f56..2a3400411ed6d10c3701eda5391722169f4dddf4 100644
--- a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/CreateLinksControllerTest.java
+++ b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/CreateLinksControllerTest.java
@@ -7,6 +7,7 @@ package it.inaf.ia2.vospace.ui.controller;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import it.inaf.ia2.aa.data.User;
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.data.CreateLinkRequest;
 import it.inaf.ia2.vospace.ui.exception.VOSpaceStatusException;
@@ -16,6 +17,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
 import org.mockito.Mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -43,6 +45,9 @@ public class CreateLinksControllerTest {
     @MockBean
     private VOSpaceClient client;
 
+    @MockBean
+    private TokenProvider tokenProvider;
+
     @Autowired
     private MockMvc mockMvc;
 
@@ -59,7 +64,7 @@ public class CreateLinksControllerTest {
 
         ContainerNode myFolder = new ContainerNode();
         myFolder.setUri("vos://ia2.inaf.it!vospace/path/to/myfolder");
-        when(client.getNode("/path/to/myfolder")).thenReturn(myFolder);
+        when(client.getNode(eq("/path/to/myfolder"), any())).thenReturn(myFolder);
 
         CreateLinkRequest request = new CreateLinkRequest();
 
@@ -78,13 +83,13 @@ public class CreateLinksControllerTest {
 
         verify(client, times(1)).createNode(argThat(node -> {
             return node.getUri().equals("vos://ia2.inaf.it!vospace/path/to/myfolder/myLink");
-        }));
+        }), any());
     }
 
     @Test
     public void testUploadLinksNonExistentFolder() throws Exception {
 
-        when(client.getNode("/path/to/non-existent")).thenThrow(new VOSpaceStatusException("Not found", 404));
+        when(client.getNode(eq("/path/to/non-existent"), any())).thenThrow(new VOSpaceStatusException("Not found", 404));
 
         mockMvc.perform(multipart("/uploadLinks")
                 .file(getListOfLinksMockMultipartFile())
@@ -98,7 +103,7 @@ public class CreateLinksControllerTest {
     public void testUploadLinks() throws Exception {
 
         ContainerNode myFolder = new ContainerNode();
-        when(client.getNode("/path/to/myfolder")).thenReturn(myFolder);
+        when(client.getNode(eq("/path/to/myfolder"), any())).thenReturn(myFolder);
 
         mockMvc.perform(multipart("/uploadLinks")
                 .file(getListOfLinksMockMultipartFile())
@@ -107,7 +112,7 @@ public class CreateLinksControllerTest {
                 .andDo(print())
                 .andExpect(status().isNoContent());
 
-        verify(client, times(75)).createNode(any());
+        verify(client, times(75)).createNode(any(), any());
     }
 
     @Test
@@ -133,7 +138,7 @@ public class CreateLinksControllerTest {
     private void testInvalidContent(String fileContent) throws Exception {
 
         ContainerNode myFolder = new ContainerNode();
-        when(client.getNode("/path/to/myfolder")).thenReturn(myFolder);
+        when(client.getNode(eq("/path/to/myfolder"), any())).thenReturn(myFolder);
 
         MockMultipartFile file = new MockMultipartFile("file", fileContent.getBytes());
 
diff --git a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/DownloadControllerTest.java b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/DownloadControllerTest.java
index 51cd0e737fe7a200af29ca03aa2104ea387fd7fb..31828aa9720d3b7a22f1c367d74636a600465238 100644
--- a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/DownloadControllerTest.java
+++ b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/DownloadControllerTest.java
@@ -7,10 +7,12 @@ package it.inaf.ia2.vospace.ui.controller;
 
 import it.inaf.ia2.aa.ServletRapClient;
 import it.inaf.ia2.aa.data.User;
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import org.junit.jupiter.api.Test;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -35,18 +37,21 @@ public class DownloadControllerTest {
     @MockBean
     private ServletRapClient rapClient;
 
+    @MockBean
+    private TokenProvider tokenProvider;
+
     @Autowired
     private MockMvc mockMvc;
 
     @Test
     public void testDirectDownload() throws Exception {
 
-        when(client.getFileServiceEndpoint(any())).thenReturn("http://redirect");
+        when(client.getFileServiceEndpoint(any(), any())).thenReturn("http://redirect");
 
         mockMvc.perform(get("/download/myfile"))
                 .andExpect(status().is3xxRedirection());
 
-        verify(client, times(1)).getFileServiceEndpoint(any());
+        verify(client, times(1)).getFileServiceEndpoint(any(), any());
     }
 
     @Test
@@ -55,7 +60,7 @@ public class DownloadControllerTest {
         User user = mock(User.class);
         when(user.getAccessToken()).thenReturn("<token>");
 
-        when(client.getArchiveJobHref("job123")).thenReturn("http://file-service/job123.zip");
+        when(client.getArchiveJobHref(eq("job123"), any())).thenReturn("http://file-service/job123.zip");
 
         when(rapClient.exchangeToken(any(), any())).thenReturn("<new-token>");
 
diff --git a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/JobControllerTest.java b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/JobControllerTest.java
index 00b1a262458a78e7a660c658d7b96d9cc863c79f..a3ce64531e127a4bad292783e5b59299ea51badc 100644
--- a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/JobControllerTest.java
+++ b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/JobControllerTest.java
@@ -53,7 +53,7 @@ public class JobControllerTest {
         JobSummary job = new JobSummary();
         job.setPhase(ExecutionPhase.QUEUED);
 
-        when(client.startTransferJob(any())).thenReturn(job);
+        when(client.startTransferJob(any(), any())).thenReturn(job);
 
         mockMvc.perform(post("/recall")
                 .contentType(MediaType.APPLICATION_JSON)
@@ -73,9 +73,9 @@ public class JobControllerTest {
             assertEquals("file1", transfer.getView().getParam().get(0).getValue());
             assertEquals("file2", transfer.getView().getParam().get(1).getValue());
             return true;
-        }))).thenReturn(job);
+        }), any())).thenReturn(job);
 
-        when(client.getFileServiceEndpoint(any())).thenReturn("http://file-service/path/to/file");
+        when(client.getFileServiceEndpoint(any(), any())).thenReturn("http://file-service/path/to/file");
 
         mockMvc.perform(post("/recall")
                 .contentType(MediaType.APPLICATION_JSON)
@@ -89,7 +89,7 @@ public class JobControllerTest {
         JobSummary job = new JobSummary();
         job.setPhase(ExecutionPhase.ERROR);
 
-        when(client.getErrorDetail(any())).thenReturn("Error was xxx");
+        when(client.getErrorDetail(any(), any())).thenReturn("Error was xxx");
 
         ErrorSummary errorSummary = new ErrorSummary();
         errorSummary.setHasDetail(true);
@@ -97,7 +97,7 @@ public class JobControllerTest {
 
         job.setErrorSummary(errorSummary);
 
-        when(client.startTransferJob(any())).thenReturn(job);
+        when(client.startTransferJob(any(), any())).thenReturn(job);
 
         testErrorCall(ex -> assertTrue(ex.getMessage().contains("Error was xxx")));
     }
@@ -114,7 +114,7 @@ public class JobControllerTest {
 
         job.setErrorSummary(errorSummary);
 
-        when(client.startTransferJob(any())).thenReturn(job);
+        when(client.startTransferJob(any(), any())).thenReturn(job);
 
         testErrorCall(ex -> assertTrue(ex.getMessage().contains("simple message") && ex.getMessage().contains("retry")));
     }
@@ -125,7 +125,7 @@ public class JobControllerTest {
         JobSummary job = new JobSummary();
         job.setPhase(ExecutionPhase.ERROR);
 
-        when(client.startTransferJob(any())).thenReturn(job);
+        when(client.startTransferJob(any(), any())).thenReturn(job);
 
         testErrorCall(ex -> assertTrue(ex.getMessage().contains("error")));
     }
@@ -133,8 +133,8 @@ public class JobControllerTest {
     @Test
     public void testGetJobs() throws Exception {
 
-        when(client.getAsyncRecallJobs()).thenReturn(List.of(new Job(new JobSummary(), Job.JobType.ASYNC_RECALL)));
-        when(client.getArchiveJobs()).thenReturn(List.of(new Job(new JobSummary(), Job.JobType.ARCHIVE)));
+        when(client.getAsyncRecallJobs(any())).thenReturn(List.of(new Job(new JobSummary(), Job.JobType.ASYNC_RECALL)));
+        when(client.getArchiveJobs(any())).thenReturn(List.of(new Job(new JobSummary(), Job.JobType.ARCHIVE)));
 
         mockMvc.perform(get("/jobs"))
                 .andExpect(status().isOk())
diff --git a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/NodesControllerTest.java b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/NodesControllerTest.java
index 14c1535cd28eba1f67c75f8c81a17f1a0e3de871..02a43f0eb0ba327bfd2aea3cf50212afc780073f 100644
--- a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/NodesControllerTest.java
+++ b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/NodesControllerTest.java
@@ -7,6 +7,7 @@ package it.inaf.ia2.vospace.ui.controller;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import it.inaf.ia2.aa.data.User;
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.data.MoveOrCopyRequest;
 import it.inaf.ia2.vospace.ui.exception.VOSpaceException;
@@ -47,7 +48,7 @@ import org.springframework.web.util.NestedServletException;
 
 @SpringBootTest
 @AutoConfigureMockMvc
-@TestPropertySource(properties = {"vospace-authority=example.com!vospace", "pollingTimeout=2"})
+@TestPropertySource(properties = {"vospace-authority=example.com!vospace", "pollingTimeout=3"})
 public class NodesControllerTest {
 
     private static final ObjectMapper MAPPER = new ObjectMapper();
@@ -55,6 +56,9 @@ public class NodesControllerTest {
     @MockBean
     private VOSpaceClient client;
 
+    @MockBean
+    private TokenProvider tokenProvider;
+
     @Autowired
     private NodesController nodesController;
 
@@ -64,34 +68,34 @@ public class NodesControllerTest {
     @Test
     public void testListNodesEmpty() throws Exception {
 
-        when(client.getNode(any())).thenReturn(new DataNode());
+        when(client.getNode(any(), any())).thenReturn(new DataNode());
 
         mockMvc.perform(get("/nodes"))
                 .andExpect(status().isOk());
 
-        verify(client, times(1)).getNode(eq("/"));
+        verify(client, times(1)).getNode(eq("/"), any());
     }
 
     @Test
     public void testListNodesRoot() throws Exception {
 
-        when(client.getNode(any())).thenReturn(new DataNode());
+        when(client.getNode(any(), any())).thenReturn(new DataNode());
 
         mockMvc.perform(get("/nodes/"))
                 .andExpect(status().isOk());
 
-        verify(client, times(1)).getNode(eq("/"));
+        verify(client, times(1)).getNode(eq("/"), any());
     }
 
     @Test
     public void testListNodesComplexPath() throws Exception {
 
-        when(client.getNode(any())).thenReturn(new DataNode());
+        when(client.getNode(any(), any())).thenReturn(new DataNode());
 
         mockMvc.perform(get("/nodes/a/b/c"))
                 .andExpect(status().isOk());
 
-        verify(client, times(1)).getNode(eq("/a/b/c"));
+        verify(client, times(1)).getNode(eq("/a/b/c"), any());
     }
 
     @Test
@@ -104,15 +108,15 @@ public class NodesControllerTest {
                 .content(MAPPER.writeValueAsString(paths)))
                 .andExpect(status().isNoContent());
 
-        verify(client, times(1)).deleteNode(eq("/a/b/c"));
-        verify(client, times(1)).deleteNode(eq("/e/f/g"));
+        verify(client, times(1)).deleteNode(eq("/a/b/c"), any());
+        verify(client, times(1)).deleteNode(eq("/e/f/g"), any());
     }
 
     @Test
     public void testErrorOnDelete() throws Exception {
 
         doThrow(new RuntimeException())
-                .when(client).deleteNode(any());
+                .when(client).deleteNode(any(), any());
 
         boolean exception = false;
         try {
@@ -164,9 +168,9 @@ public class NodesControllerTest {
         child7.setTarget("http://external-link");
         parent.getNodes().add(child7);
 
-        when(client.getNode(eq("/a/b/c"))).thenReturn(parent);
-        when(client.getNode(eq("/a/b/c/c1"))).thenReturn(child1);
-        when(client.getNode(eq("/a/b/c/c2"))).thenReturn(child2);
+        when(client.getNode(eq("/a/b/c"), any())).thenReturn(parent);
+        when(client.getNode(eq("/a/b/c/c1"), any())).thenReturn(child1);
+        when(client.getNode(eq("/a/b/c/c2"), any())).thenReturn(child2);
 
         String response = mockMvc.perform(get("/nodesForMoveOrCopy")
                 .param("path", "/a/b/c")
@@ -183,13 +187,13 @@ public class NodesControllerTest {
         assertTrue(response.contains("c6")); // link to container
         assertFalse(response.contains("c7")); // external link
 
-        verify(client, times(1)).getNode(eq("/a/b/c"));
+        verify(client, times(1)).getNode(eq("/a/b/c"), any());
     }
 
     @Test
     public void testMoveNodeSuccess() throws Exception {
 
-        when(client.getJobPhase("job_id"))
+        when(client.getJobPhase(eq("job_id"), any()))
                 .thenReturn(ExecutionPhase.EXECUTING)
                 .thenReturn(ExecutionPhase.COMPLETED);
 
@@ -201,7 +205,7 @@ public class NodesControllerTest {
     @Test
     public void testMoveNodeExecuting() throws Exception {
 
-        when(client.getJobPhase("job_id"))
+        when(client.getJobPhase(eq("job_id"), any()))
                 .thenReturn(ExecutionPhase.EXECUTING);
 
         testMoveNode()
@@ -212,10 +216,10 @@ public class NodesControllerTest {
     @Test
     public void testMoveNodeError() throws Exception {
 
-        when(client.getJobPhase("job_id"))
+        when(client.getJobPhase(eq("job_id"), any()))
                 .thenReturn(ExecutionPhase.ERROR);
 
-        when(client.getErrorDetail("job_id")).thenReturn("move_error");
+        when(client.getErrorDetail(eq("job_id"), any())).thenReturn("move_error");
 
         try {
             testMoveNode();
@@ -239,7 +243,7 @@ public class NodesControllerTest {
                 .content("{\"parentPath\": \"/parent\", \"name\": \"newFolder\"}"))
                 .andExpect(status().is2xxSuccessful());
 
-        verify(client, times(1)).createNode(any());
+        verify(client, times(1)).createNode(any(), any());
     }
 
     @Test
@@ -261,13 +265,13 @@ public class NodesControllerTest {
         DataNode linkedNode = new DataNode();
         linkedNode.setUri("vos://example.com!vospace/myfile");
 
-        when(client.getNode(eq("/"))).thenReturn(parent);
-        when(client.getNode(eq("/myfile"))).thenReturn(linkedNode);
+        when(client.getNode(eq("/"), any())).thenReturn(parent);
+        when(client.getNode(eq("/myfile"), any())).thenReturn(linkedNode);
 
         mockMvc.perform(get("/nodes"))
                 .andExpect(status().isOk());
 
-        verify(client, times(1)).getNode(eq("/"));
+        verify(client, times(1)).getNode(eq("/"), any());
     }
 
     private ResultActions testMoveNode() throws Exception {
@@ -275,7 +279,7 @@ public class NodesControllerTest {
         JobSummary job = new JobSummary();
         job.setJobId("job_id");
 
-        when(client.startTransferJob(any())).thenReturn(job);
+        when(client.startTransferJob(any(), any())).thenReturn(job);
 
         MoveOrCopyRequest request = new MoveOrCopyRequest();
         request.setTargets(List.of("/path/to/target"));
diff --git a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/UploadControllerTest.java b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/UploadControllerTest.java
index 31de6d21f785fa8cd470a03c377b263a994f78fd..5928b82334f2425ee44279f4cf6da3605e864bce 100644
--- a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/UploadControllerTest.java
+++ b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/controller/UploadControllerTest.java
@@ -7,11 +7,13 @@ package it.inaf.ia2.vospace.ui.controller;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import it.inaf.ia2.aa.data.User;
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.data.UploadFilesData;
 import it.inaf.ia2.vospace.ui.exception.VOSpaceException;
 import it.inaf.ia2.vospace.ui.exception.VOSpaceStatusException;
 import java.util.List;
+import java.util.Optional;
 import static org.hamcrest.core.IsNull.nullValue;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -44,6 +46,9 @@ public class UploadControllerTest {
     @MockBean
     private VOSpaceClient client;
 
+    @MockBean
+    private TokenProvider tokenProvider;
+
     @Autowired
     private MockMvc mockMvc;
 
@@ -53,6 +58,7 @@ public class UploadControllerTest {
     @BeforeEach
     public void setUp() {
         when(user.getName()).thenReturn("user_id");
+        when(tokenProvider.getToken()).thenReturn(Optional.of("<token>"));
     }
 
     @Test
@@ -62,7 +68,7 @@ public class UploadControllerTest {
         data.setParentPath("/mynode");
         data.setFiles(List.of("test.txt"));
 
-        when(client.getFileServiceEndpoint(any())).thenReturn("http://files/mynode/test.txt");
+        when(client.getFileServiceEndpoint(any(), any())).thenReturn("http://files/mynode/test.txt");
 
         mockMvc.perform(post("/preupload")
                 .sessionAttr("user_data", user)
@@ -81,7 +87,7 @@ public class UploadControllerTest {
         data.setParentPath("/");
         data.setFiles(List.of("test.txt"));
 
-        when(client.getFileServiceEndpoint(any())).thenReturn("http://files/test.txt");
+        when(client.getFileServiceEndpoint(any(), any())).thenReturn("http://files/test.txt");
 
         mockMvc.perform(post("/preupload")
                 .sessionAttr("user_data", user)
@@ -96,6 +102,8 @@ public class UploadControllerTest {
     @Test
     public void testUploadNotAllowedToAnonymous() throws Exception {
 
+        when(tokenProvider.getToken()).thenReturn(Optional.empty());
+
         UploadFilesData data = new UploadFilesData();
         data.setParentPath("/");
         data.setFiles(List.of("test.txt"));
@@ -113,7 +121,7 @@ public class UploadControllerTest {
         data.setParentPath("/mynode");
         data.setFiles(List.of("test.txt"));
 
-        doThrow(new VOSpaceStatusException("Conflict", 409)).when(client).createNode(any());
+        doThrow(new VOSpaceStatusException("Conflict", 409)).when(client).createNode(any(), any());
 
         mockMvc.perform(post("/preupload")
                 .sessionAttr("user_data", user)
@@ -132,7 +140,7 @@ public class UploadControllerTest {
         data.setParentPath("/mynode");
         data.setFiles(List.of("test.txt"));
 
-        doThrow(new VOSpaceStatusException("Server Error", 500)).when(client).createNode(any());
+        doThrow(new VOSpaceStatusException("Server Error", 500)).when(client).createNode(any(), any());
 
         mockMvc.perform(post("/preupload")
                 .sessionAttr("user_data", user)
@@ -151,7 +159,7 @@ public class UploadControllerTest {
         data.setParentPath("/mynode");
         data.setFiles(List.of("test.txt"));
 
-        doThrow(new VOSpaceException("Unable to connect")).when(client).getFileServiceEndpoint(any());
+        doThrow(new VOSpaceException("Unable to connect")).when(client).getFileServiceEndpoint(any(), any());
 
         mockMvc.perform(post("/preupload")
                 .sessionAttr("user_data", user)
@@ -162,7 +170,7 @@ public class UploadControllerTest {
                 .andExpect(jsonPath("$[0].error").value("Unable to connect"))
                 .andExpect(jsonPath("$[0].url").value(nullValue()));
 
-        verify(client, times(1)).deleteNode(eq("/mynode/test.txt"));
+        verify(client, times(1)).deleteNode(eq("/mynode/test.txt"), any());
     }
 
     @Test
@@ -172,7 +180,7 @@ public class UploadControllerTest {
         data.setParentPath("/mynode");
         data.setFiles(List.of("test.txt"));
 
-        doThrow(new NullPointerException()).when(client).getFileServiceEndpoint(any());
+        doThrow(new NullPointerException()).when(client).getFileServiceEndpoint(any(), any());
 
         mockMvc.perform(post("/preupload")
                 .sessionAttr("user_data", user)
@@ -183,7 +191,7 @@ public class UploadControllerTest {
                 .andExpect(jsonPath("$[0].error").value("Unable to obtain upload URL"))
                 .andExpect(jsonPath("$[0].url").value(nullValue()));
 
-        verify(client, times(1)).deleteNode(eq("/mynode/test.txt"));
+        verify(client, times(1)).deleteNode(eq("/mynode/test.txt"), any());
     }
 
     @Test
@@ -193,8 +201,8 @@ public class UploadControllerTest {
         data.setParentPath("/mynode");
         data.setFiles(List.of("test.txt"));
 
-        doThrow(new NullPointerException()).when(client).getFileServiceEndpoint(any());
-        doThrow(new VOSpaceException("error")).when(client).deleteNode(any());
+        doThrow(new NullPointerException()).when(client).getFileServiceEndpoint(any(), any());
+        doThrow(new VOSpaceException("error")).when(client).deleteNode(any(), any());
 
         mockMvc.perform(post("/preupload")
                 .sessionAttr("user_data", user)
@@ -205,6 +213,6 @@ public class UploadControllerTest {
                 .andExpect(jsonPath("$[0].error").value("Retrieval of upload URL failed. Manual cleanup of node metadata may be necessary"))
                 .andExpect(jsonPath("$[0].url").value(nullValue()));
 
-        verify(client, times(1)).deleteNode(eq("/mynode/test.txt"));
+        verify(client, times(1)).deleteNode(eq("/mynode/test.txt"), any());
     }
 }
diff --git a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/service/SharingServiceTest.java b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/service/SharingServiceTest.java
index df918a0e005288fd7f17e3a78adb2c66fda971c9..fc99091bbb08e8834c8e6d03d3ff15f836c96a37 100644
--- a/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/service/SharingServiceTest.java
+++ b/vospace-ui-backend/src/test/java/it/inaf/ia2/vospace/ui/service/SharingServiceTest.java
@@ -11,6 +11,7 @@ import it.inaf.ia2.rap.data.AccessTokenResponse;
 import it.inaf.ia2.rap.data.Identity;
 import it.inaf.ia2.rap.data.IdentityType;
 import it.inaf.ia2.rap.data.RapUser;
+import it.inaf.ia2.vospace.ui.TokenProvider;
 import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
 import it.inaf.ia2.vospace.ui.data.ShareRequest;
 import it.inaf.ia2.vospace.ui.data.SharingInfo;
@@ -59,6 +60,9 @@ public class SharingServiceTest {
     @Mock
     private VOSpaceClient vospaceClient;
 
+    @Mock
+    private TokenProvider tokenProvider;
+
     @InjectMocks
     private SharingService sharingService;
 
@@ -104,7 +108,7 @@ public class SharingServiceTest {
         groupReadProperty.setValue("group1");
         node.getProperties().add(groupReadProperty);
 
-        when(vospaceClient.getNode(any())).thenReturn(node);
+        when(vospaceClient.getNode(any(), any())).thenReturn(node);
 
         ShareRequest shareRequest = new ShareRequest();
         shareRequest.setPath("/mynode");
@@ -130,7 +134,7 @@ public class SharingServiceTest {
             assertTrue(groupWrite.contains("people.bianca\\.verdi"));
             assertTrue(groupWrite.contains("group2"));
             return true;
-        }), anyBoolean());
+        }), anyBoolean(), any());
     }
 
     @Test
@@ -139,7 +143,7 @@ public class SharingServiceTest {
         DataNode node = new DataNode();
         node.setUri("vos://example.com!vospace/anna.bianchi/mynode");
 
-        when(vospaceClient.getNode(any())).thenReturn(node);
+        when(vospaceClient.getNode(any(), any())).thenReturn(node);
 
         ShareRequest shareRequest = new ShareRequest();
         shareRequest.setPath("/anna.bianchi/mynode");