changeset 6240:a6c9451fbade

propagating the authentication payload to the REST handlers
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 11 Jul 2025 09:41:19 +0200
parents 5c9fc31d1555
children 54c8e2398c94
files NEWS OrthancFramework/Sources/HttpServer/FilesystemHttpHandler.cpp OrthancFramework/Sources/HttpServer/FilesystemHttpHandler.h OrthancFramework/Sources/HttpServer/HttpServer.cpp OrthancFramework/Sources/HttpServer/HttpServer.h OrthancFramework/Sources/HttpServer/IHttpHandler.cpp OrthancFramework/Sources/HttpServer/IHttpHandler.h OrthancFramework/Sources/RestApi/RestApi.cpp OrthancFramework/Sources/RestApi/RestApi.h OrthancFramework/UnitTestsSources/RestApiTests.cpp OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Engine/OrthancPlugins.h OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h OrthancServer/Sources/EmbeddedResourceHttpHandler.cpp OrthancServer/Sources/EmbeddedResourceHttpHandler.h OrthancServer/Sources/OrthancHttpHandler.cpp OrthancServer/Sources/OrthancHttpHandler.h OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestApi.h
diffstat 19 files changed, 119 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Thu Jul 10 18:36:36 2025 +0200
+++ b/NEWS	Fri Jul 11 09:41:19 2025 +0200
@@ -31,6 +31,8 @@
     DICOM resource from a plugin.
   - "OrthancPluginRegisterHttpAuthentication()" to install a custom
     callback to authenticate HTTP requests.
+* The OrthancPluginHttpRequest structure provides the payload of
+  the possible HTTP authentication callback.
 * OrthancPluginCallRestApi() now also returns the body of DELETE requests:
   https://discourse.orthanc-server.org/t/response-to-plugin-from-orthanc-api-delete-endpoint/6022
 
--- a/OrthancFramework/Sources/HttpServer/FilesystemHttpHandler.cpp	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancFramework/Sources/HttpServer/FilesystemHttpHandler.cpp	Fri Jul 11 09:41:19 2025 +0200
@@ -128,7 +128,8 @@
                                      const HttpToolbox::Arguments& headers,
                                      const HttpToolbox::GetArguments& arguments,
                                      const void* /*bodyData*/,
-                                     size_t /*bodySize*/)
+                                     size_t /*bodySize*/,
+                                     const std::string& authenticationPayload /* ignored */)
   {
     if (!Toolbox::IsChildUri(pimpl_->baseUri_, uri))
     {
--- a/OrthancFramework/Sources/HttpServer/FilesystemHttpHandler.h	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancFramework/Sources/HttpServer/FilesystemHttpHandler.h	Fri Jul 11 09:41:19 2025 +0200
@@ -50,7 +50,8 @@
                                             const char* username,
                                             HttpMethod method,
                                             const UriComponents& uri,
-                                            const HttpToolbox::Arguments& headers) ORTHANC_OVERRIDE
+                                            const HttpToolbox::Arguments& headers,
+                                            const std::string& authenticationPayload /* ignored */) ORTHANC_OVERRIDE
     {
       return false;
     }
@@ -64,7 +65,8 @@
                         const HttpToolbox::Arguments& headers,
                         const HttpToolbox::GetArguments& arguments,
                         const void* /*bodyData*/,
-                        size_t /*bodySize*/) ORTHANC_OVERRIDE;
+                        size_t /*bodySize*/,
+                        const std::string& authenticationPayload /* ignored */) ORTHANC_OVERRIDE;
 
     bool IsListDirectoryContent() const
     {
--- a/OrthancFramework/Sources/HttpServer/HttpServer.cpp	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancFramework/Sources/HttpServer/HttpServer.cpp	Fri Jul 11 09:41:19 2025 +0200
@@ -349,6 +349,7 @@
     bool                  isJQueryUploadChunk_;
     std::string           jqueryUploadFileName_;
     size_t                jqueryUploadFileSize_;
+    const std::string&    authenticationPayload_;
 
     void HandleInternal(const MultipartStreamReader::HttpHeaders& headers,
                         const void* part,
@@ -359,7 +360,7 @@
       HttpToolbox::GetArguments getArguments;
       
       if (!handler_.Handle(fakeOutput, RequestOrigin_RestApi, remoteIp_.c_str(), username_.c_str(), 
-                           HttpMethod_Post, uri_, headers, getArguments, part, size))
+                           HttpMethod_Post, uri_, headers, getArguments, part, size, authenticationPayload_))
       {
         throw OrthancException(ErrorCode_UnknownResource);
       }
@@ -371,14 +372,16 @@
                              const std::string& remoteIp,
                              const std::string& username,
                              const UriComponents& uri,
-                             const MultipartStreamReader::HttpHeaders& headers) :
+                             const MultipartStreamReader::HttpHeaders& headers,
+                             const std::string& authenticationPayload) :
       handler_(handler),
       chunkStore_(chunkStore),
       remoteIp_(remoteIp),
       username_(username),
       uri_(uri),
       isJQueryUploadChunk_(false),
-      jqueryUploadFileSize_(0)  // Dummy initialization
+      jqueryUploadFileSize_(0),  // Dummy initialization
+      authenticationPayload_(authenticationPayload)
     {
       typedef HttpToolbox::Arguments::const_iterator Iterator;
       
@@ -471,9 +474,10 @@
                                             const UriComponents& uri,
                                             const std::map<std::string, std::string>& headers,
                                             const std::string& body,
-                                            const std::string& boundary)
+                                            const std::string& boundary,
+                                            const std::string& authenticationPayload)
   {
-    MultipartFormDataHandler handler(GetHandler(), pimpl_->chunkStore_, remoteIp, username, uri, headers);
+    MultipartFormDataHandler handler(GetHandler(), pimpl_->chunkStore_, remoteIp, username, uri, headers, authenticationPayload);
           
     MultipartStreamReader reader(boundary);
     reader.SetHandler(handler);
@@ -1269,7 +1273,7 @@
     const IIncomingHttpRequestFilter *filter = server.GetIncomingHttpRequestFilter();
 
     // Authenticate this connection
-    std::string customPayload;
+    std::string authenticationPayload;
     std::string redirection;
     IIncomingHttpRequestFilter::AuthenticationStatus status;
 
@@ -1279,7 +1283,7 @@
     }
     else
     {
-      status = filter->CheckAuthentication(customPayload, redirection, requestUri, headers);
+      status = filter->CheckAuthentication(authenticationPayload, redirection, requestUri, headers);
     }
 
     switch (status)
@@ -1295,7 +1299,6 @@
         break;
 
       case IIncomingHttpRequestFilter::AuthenticationStatus_Success:
-        printf("PAYLOAD: [%s]\n", customPayload.c_str());
         break;
 
       case IIncomingHttpRequestFilter::AuthenticationStatus_Redirect:
@@ -1434,7 +1437,7 @@
         status = ReadBodyToString(body, connection, headers);
         if (status == PostDataStatus_Success)
         {
-          server.ProcessMultipartFormData(remoteIp, username, uri, headers, body, boundary);
+          server.ProcessMultipartFormData(remoteIp, username, uri, headers, body, boundary, authenticationPayload);
           output.SendStatus(HttpStatus_200_Ok);
           return;
         }
@@ -1447,7 +1450,7 @@
         if (server.HasHandler())
         {
           found = server.GetHandler().CreateChunkedRequestReader
-            (stream, RequestOrigin_RestApi, remoteIp, username.c_str(), method, uri, headers);
+            (stream, RequestOrigin_RestApi, remoteIp, username.c_str(), method, uri, headers, authenticationPayload);
         }
         
         if (found)
@@ -1496,7 +1499,7 @@
         server.HasHandler())
     {
       found = server.GetHandler().Handle(output, RequestOrigin_RestApi, remoteIp, username.c_str(), 
-                                         method, uri, headers, argumentsGET, body.c_str(), body.size());
+                                         method, uri, headers, argumentsGET, body.c_str(), body.size(), authenticationPayload);
     }
 
     if (!found)
--- a/OrthancFramework/Sources/HttpServer/HttpServer.h	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancFramework/Sources/HttpServer/HttpServer.h	Fri Jul 11 09:41:19 2025 +0200
@@ -227,7 +227,8 @@
                                   const UriComponents& uri,
                                   const std::map<std::string, std::string>& headers,
                                   const std::string& body,
-                                  const std::string& boundary);
+                                  const std::string& boundary,
+                                  const std::string& authenticationPayload);
 
     MetricsRegistry::SharedMetrics& GetAvailableHttpThreadsMetrics()
     {
--- a/OrthancFramework/Sources/HttpServer/IHttpHandler.cpp	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancFramework/Sources/HttpServer/IHttpHandler.cpp	Fri Jul 11 09:41:19 2025 +0200
@@ -49,7 +49,7 @@
     HttpOutput http(stream, false /* assume no keep-alive */, 0);
 
     if (handler.Handle(http, origin, LOCALHOST, "", HttpMethod_Get, curi, 
-                       httpHeaders, getArguments, NULL /* no body for GET */, 0))
+                       httpHeaders, getArguments, NULL /* no body for GET */, 0, "" /* no authentication payload */))
     {
       if (stream.GetStatus() == HttpStatus_200_Ok)
       {
@@ -89,7 +89,7 @@
     HttpOutput http(stream, false /* assume no keep-alive */, 0);
 
     if (handler.Handle(http, origin, LOCALHOST, "", method, curi, 
-                       httpHeaders, getArguments, bodyData, bodySize))
+                       httpHeaders, getArguments, bodyData, bodySize, "" /* no authentication payload */))
     {
       stream.GetBody(answerBody);
 
@@ -149,7 +149,7 @@
     HttpOutput http(stream, false /* assume no keep-alive */, 0);
 
     if (handler.Handle(http, origin, LOCALHOST, "", HttpMethod_Delete, curi, 
-                       httpHeaders, getArguments, NULL /* no body for DELETE */, 0))
+                       httpHeaders, getArguments, NULL /* no body for DELETE */, 0, "" /* no authentication payload */))
     {
       stream.GetBody(answerBody);
 
--- a/OrthancFramework/Sources/HttpServer/IHttpHandler.h	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancFramework/Sources/HttpServer/IHttpHandler.h	Fri Jul 11 09:41:19 2025 +0200
@@ -72,7 +72,8 @@
                                             const char* username,
                                             HttpMethod method,
                                             const UriComponents& uri,
-                                            const HttpToolbox::Arguments& headers) = 0;
+                                            const HttpToolbox::Arguments& headers,
+                                            const std::string& authenticationPayload) = 0;
 
     virtual bool Handle(HttpOutput& output,
                         RequestOrigin origin,
@@ -83,7 +84,8 @@
                         const HttpToolbox::Arguments& headers,
                         const HttpToolbox::GetArguments& getArguments,
                         const void* bodyData,
-                        size_t bodySize) = 0;
+                        size_t bodySize,
+                        const std::string& authenticationPayload) = 0;
 
 
     /**
--- a/OrthancFramework/Sources/RestApi/RestApi.cpp	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancFramework/Sources/RestApi/RestApi.cpp	Fri Jul 11 09:41:19 2025 +0200
@@ -775,7 +775,8 @@
                                            const char* username,
                                            HttpMethod method,
                                            const UriComponents& uri,
-                                           const HttpToolbox::Arguments& headers)
+                                           const HttpToolbox::Arguments& headers,
+                                           const std::string& authenticationPayload)
   {
     return false;
   }
@@ -790,7 +791,8 @@
                        const HttpToolbox::Arguments& headers,
                        const HttpToolbox::GetArguments& getArguments,
                        const void* bodyData,
-                       size_t bodySize)
+                       size_t bodySize,
+                       const std::string& authenticationPayload)
   {
     RestApiOutput wrappedOutput(output, method);
 
--- a/OrthancFramework/Sources/RestApi/RestApi.h	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancFramework/Sources/RestApi/RestApi.h	Fri Jul 11 09:41:19 2025 +0200
@@ -46,7 +46,8 @@
                                             const char* username,
                                             HttpMethod method,
                                             const UriComponents& uri,
-                                            const HttpToolbox::Arguments& headers) ORTHANC_OVERRIDE;
+                                            const HttpToolbox::Arguments& headers,
+                                            const std::string& authenticationPayload) ORTHANC_OVERRIDE;
 
     virtual bool Handle(HttpOutput& output,
                         RequestOrigin origin,
@@ -57,7 +58,8 @@
                         const HttpToolbox::Arguments& headers,
                         const HttpToolbox::GetArguments& getArguments,
                         const void* bodyData,
-                        size_t bodySize) ORTHANC_OVERRIDE;
+                        size_t bodySize,
+                        const std::string& authenticationPayload) ORTHANC_OVERRIDE;
 
     void Register(const std::string& path,
                   RestApiGetCall::Handler handler);
--- a/OrthancFramework/UnitTestsSources/RestApiTests.cpp	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancFramework/UnitTestsSources/RestApiTests.cpp	Fri Jul 11 09:41:19 2025 +0200
@@ -1290,7 +1290,8 @@
                                             const char* username,
                                             HttpMethod method,
                                             const UriComponents& uri,
-                                            const HttpToolbox::Arguments& headers) ORTHANC_OVERRIDE
+                                            const HttpToolbox::Arguments& headers,
+                                            const std::string& authenticationPayload) ORTHANC_OVERRIDE
     {
       return false;
     }
@@ -1304,7 +1305,8 @@
                         const HttpToolbox::Arguments& headers,
                         const HttpToolbox::GetArguments& getArguments,
                         const void* bodyData,
-                        size_t bodySize) ORTHANC_OVERRIDE
+                        size_t bodySize,
+                        const std::string& authenticationPayload) ORTHANC_OVERRIDE
     {
       printf("received %d\n", static_cast<int>(bodySize));
 
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Fri Jul 11 09:41:19 2025 +0200
@@ -2459,7 +2459,8 @@
     public:
       HttpRequestConverter(const RestCallbackMatcher& matcher,
                            HttpMethod method,
-                           const HttpToolbox::Arguments& headers)
+                           const HttpToolbox::Arguments& headers,
+                           const std::string& authenticationPayload)
       {
         memset(&converted_, 0, sizeof(OrthancPluginHttpRequest));
 
@@ -2502,6 +2503,14 @@
           converted_.headersKeys = &headersKeys_[0];
           converted_.headersValues = &headersValues_[0];
         }
+
+        converted_.authenticationPayload = authenticationPayload.empty() ? NULL : authenticationPayload.c_str();
+        converted_.authenticationPayloadSize = static_cast<uint32_t>(authenticationPayload.size());
+
+        if (converted_.authenticationPayloadSize != authenticationPayload.size())
+        {
+          throw OrthancException(ErrorCode_NotEnoughMemory);
+        }
       }
 
       void SetGetArguments(const HttpToolbox::GetArguments& getArguments)
@@ -2573,7 +2582,8 @@
                                               HttpMethod method,
                                               const UriComponents& uri,
                                               const HttpToolbox::Arguments& headers,
-                                              const HttpToolbox::GetArguments& getArguments)
+                                              const HttpToolbox::GetArguments& getArguments,
+                                              const std::string& authenticationPayload)
   {
     RestCallbackMatcher matcher(uri);
 
@@ -2622,7 +2632,7 @@
       }
       else
       {
-        HttpRequestConverter converter(matcher, method, headers);
+        HttpRequestConverter converter(matcher, method, headers, authenticationPayload);
         converter.SetGetArguments(getArguments);
       
         PImpl::PluginHttpOutput pluginOutput(output);
@@ -2648,7 +2658,8 @@
                               const HttpToolbox::Arguments& headers,
                               const HttpToolbox::GetArguments& getArguments,
                               const void* bodyData,
-                              size_t bodySize)
+                              size_t bodySize,
+                              const std::string& authenticationPayload)
   {
     RestCallbackMatcher matcher(uri);
 
@@ -2669,12 +2680,12 @@
     if (callback == NULL)
     {
       // Callback not found, try to find a chunked callback
-      return HandleChunkedGetDelete(output, method, uri, headers, getArguments);
+      return HandleChunkedGetDelete(output, method, uri, headers, getArguments, authenticationPayload);
     }
 
     CLOG(INFO, PLUGINS) << "Delegating HTTP request to plugin for URI: " << matcher.GetFlatUri();
 
-    HttpRequestConverter converter(matcher, method, headers);
+    HttpRequestConverter converter(matcher, method, headers, authenticationPayload);
     converter.SetGetArguments(getArguments);
     converter.GetRequest().body = bodyData;
     converter.GetRequest().bodySize = bodySize;
@@ -6662,7 +6673,8 @@
                                                   const char* username,
                                                   HttpMethod method,
                                                   const UriComponents& uri,
-                                                  const HttpToolbox::Arguments& headers)
+                                                  const HttpToolbox::Arguments& headers,
+                                                  const std::string& authenticationPayload)
   {
     if (method != HttpMethod_Post &&
         method != HttpMethod_Put)
@@ -6718,7 +6730,7 @@
       {
         CLOG(INFO, PLUGINS) << "Delegating chunked HTTP request to plugin for URI: " << matcher.GetFlatUri();
 
-        HttpRequestConverter converter(matcher, method, headers);
+        HttpRequestConverter converter(matcher, method, headers, authenticationPayload);
         converter.GetRequest().body = NULL;
         converter.GetRequest().bodySize = 0;
 
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.h	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.h	Fri Jul 11 09:41:19 2025 +0200
@@ -106,7 +106,8 @@
                                 HttpMethod method,
                                 const UriComponents& uri,
                                 const HttpToolbox::Arguments& headers,
-                                const HttpToolbox::GetArguments& getArguments);
+                                const HttpToolbox::GetArguments& getArguments,
+                                const std::string& authenticationPayload);
 
     void RegisterOnStoredInstanceCallback(const void* parameters);
 
@@ -291,7 +292,8 @@
                         const HttpToolbox::Arguments& headers,
                         const HttpToolbox::GetArguments& getArguments,
                         const void* bodyData,
-                        size_t bodySize) ORTHANC_OVERRIDE;
+                        size_t bodySize,
+                        const std::string& authenticationPayload) ORTHANC_OVERRIDE;
 
     virtual bool InvokeService(SharedLibrary& plugin,
                                _OrthancPluginService service,
@@ -399,7 +401,8 @@
                                             const char* username,
                                             HttpMethod method,
                                             const UriComponents& uri,
-                                            const HttpToolbox::Arguments& headers) ORTHANC_OVERRIDE;
+                                            const HttpToolbox::Arguments& headers,
+                                            const std::string& authenticationPayload) ORTHANC_OVERRIDE;
 
     // New in Orthanc 1.6.0
     IStorageCommitmentFactory::ILookupHandler* CreateStorageCommitment(
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Fri Jul 11 09:41:19 2025 +0200
@@ -419,6 +419,23 @@
      **/
     const char* const*      headersValues;
 
+
+    /* --------------------------------------------------
+       New in version 1.12.9
+       -------------------------------------------------- */
+
+    /**
+     * @brief If a HTTP authentication callback is registered, the
+     * content of the custom payload generated by the callback.
+     **/
+    const void*             authenticationPayload;
+
+    /**
+     * @brief The size of the custom authentication payload (0 if no
+     * authentication callback is registered).
+     **/
+    uint32_t                authenticationPayloadSize;
+
   } OrthancPluginHttpRequest;
 
 
@@ -10398,26 +10415,27 @@
   /**
    * @brief Register a callback to handle HTTP authentication.
    *
-   * This function installs a callback that is executed on each
+   * This function installs a callback that is executed for each
    * incoming HTTP request to handle HTTP authentication. At most one
    * plugin can register such a callback. This gives the opportunity
    * to one plugin to validate access tokens (such as a JWT), possibly
-   * redirecting the user to a login page. The callback can generate a
-   * custom payload that will be provided to the possible subsequent
-   * HTTP authorizer (cf. function XXX).
-   *
-   * If one plugin installs such a callback, the built-in HTTP
-   * authentication of Orthanc is disabled. This means that the
-   * "RegisteredUsers" and "AuthenticationEnabled" configuration
-   * options of Orthanc are totally ignored. In addition, tokens
-   * generated by OrthancPluginGenerateRestApiAuthorizationToken()
-   * become ineffective.
+   * redirecting the user to a login page. The authentication callback
+   * can generate a custom payload that will be provided to the
+   * subsequent REST handling callback.
    *
    * The HTTP authentication callback can notably be used if some
    * resource in the REST API must be available for public access, as
    * soon as the "RemoteAccessAllowed" configuration option is set to
    * "true".
    *
+   * If one plugin installs a HTTP authentication callback, the
+   * built-in HTTP authentication of Orthanc is disabled. This means
+   * that the "RegisteredUsers" and "AuthenticationEnabled"
+   * configuration options of Orthanc are totally ignored. In
+   * addition, tokens generated by
+   * OrthancPluginGenerateRestApiAuthorizationToken() become
+   * ineffective.
+   *
    * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
    * @param callback The HTTP authentication callback.
    * @return 0 if success, other value if error.
--- a/OrthancServer/Sources/EmbeddedResourceHttpHandler.cpp	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancServer/Sources/EmbeddedResourceHttpHandler.cpp	Fri Jul 11 09:41:19 2025 +0200
@@ -51,7 +51,8 @@
     const HttpToolbox::Arguments& headers,
     const HttpToolbox::GetArguments& arguments,
     const void* /*bodyData*/,
-    size_t /*bodySize*/)
+    size_t /*bodySize*/,
+    const std::string& /*authenticationPayload*/)
   {
     if (!Toolbox::IsChildUri(baseUri_, uri))
     {
--- a/OrthancServer/Sources/EmbeddedResourceHttpHandler.h	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancServer/Sources/EmbeddedResourceHttpHandler.h	Fri Jul 11 09:41:19 2025 +0200
@@ -47,7 +47,8 @@
                                             const char* username,
                                             HttpMethod method,
                                             const UriComponents& uri,
-                                            const HttpToolbox::Arguments& headers) ORTHANC_OVERRIDE
+                                            const HttpToolbox::Arguments& headers,
+                                            const std::string& authenticationPayload) ORTHANC_OVERRIDE
     {
       return false;
     }
@@ -61,6 +62,7 @@
                         const HttpToolbox::Arguments& headers,
                         const HttpToolbox::GetArguments& arguments,
                         const void* /*bodyData*/,
-                        size_t /*bodySize*/) ORTHANC_OVERRIDE;
+                        size_t /*bodySize*/,
+                        const std::string& authenticationPayload) ORTHANC_OVERRIDE;
   };
 }
--- a/OrthancServer/Sources/OrthancHttpHandler.cpp	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancServer/Sources/OrthancHttpHandler.cpp	Fri Jul 11 09:41:19 2025 +0200
@@ -36,7 +36,8 @@
     const char* username,
     HttpMethod method,
     const UriComponents& uri,
-    const HttpToolbox::Arguments& headers)
+    const HttpToolbox::Arguments& headers,
+    const std::string& authenticationPayload)
   {
     if (method != HttpMethod_Post &&
         method != HttpMethod_Put)
@@ -47,7 +48,7 @@
     for (Handlers::const_iterator it = handlers_.begin(); it != handlers_.end(); ++it) 
     {
       if ((*it)->CreateChunkedRequestReader
-          (target, origin, remoteIp, username, method, uri, headers))
+          (target, origin, remoteIp, username, method, uri, headers, authenticationPayload))
       {
         if (target.get() == NULL)
         {
@@ -71,12 +72,13 @@
                                   const HttpToolbox::Arguments& headers,
                                   const HttpToolbox::GetArguments& getArguments,
                                   const void* bodyData,
-                                  size_t bodySize)
+                                  size_t bodySize,
+                                  const std::string& authenticationPayload)
   {
     for (Handlers::const_iterator it = handlers_.begin(); it != handlers_.end(); ++it) 
     {
       if ((*it)->Handle(output, origin, remoteIp, username, method, uri, 
-                        headers, getArguments, bodyData, bodySize))
+                        headers, getArguments, bodyData, bodySize, authenticationPayload))
       {
         return true;
       }
--- a/OrthancServer/Sources/OrthancHttpHandler.h	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancServer/Sources/OrthancHttpHandler.h	Fri Jul 11 09:41:19 2025 +0200
@@ -46,7 +46,8 @@
                                             const char* username,
                                             HttpMethod method,
                                             const UriComponents& uri,
-                                            const HttpToolbox::Arguments& headers) ORTHANC_OVERRIDE;
+                                            const HttpToolbox::Arguments& headers,
+                                            const std::string& authenticationPayload) ORTHANC_OVERRIDE;
 
     virtual bool Handle(HttpOutput& output,
                         RequestOrigin origin,
@@ -57,7 +58,8 @@
                         const HttpToolbox::Arguments& headers,
                         const HttpToolbox::GetArguments& getArguments,
                         const void* bodyData,
-                        size_t bodySize) ORTHANC_OVERRIDE;
+                        size_t bodySize,
+                        const std::string& authenticationPayload) ORTHANC_OVERRIDE;
 
     void Register(IHttpHandler& handler,
                   bool isOrthancRestApi);
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp	Fri Jul 11 09:41:19 2025 +0200
@@ -297,13 +297,14 @@
                               const HttpToolbox::Arguments& headers,
                               const HttpToolbox::GetArguments& getArguments,
                               const void* bodyData,
-                              size_t bodySize)
+                              size_t bodySize,
+                              const std::string& authenticationPayload)
   {
     MetricsRegistry::Timer timer(context_.GetMetricsRegistry(), "orthanc_rest_api_duration_ms");
     MetricsRegistry::ActiveCounter counter(activeRequests_);
 
     return RestApi::Handle(output, origin, remoteIp, username, method,
-                           uri, headers, getArguments, bodyData, bodySize);
+                           uri, headers, getArguments, bodyData, bodySize, authenticationPayload);
   }
 
 
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.h	Thu Jul 10 18:36:36 2025 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.h	Fri Jul 11 09:41:19 2025 +0200
@@ -78,7 +78,8 @@
                         const HttpToolbox::Arguments& headers,
                         const HttpToolbox::GetArguments& getArguments,
                         const void* bodyData,
-                        size_t bodySize) ORTHANC_OVERRIDE;
+                        size_t bodySize,
+                        const std::string& authenticationPayload) ORTHANC_OVERRIDE;
 
     const bool& LeaveBarrierFlag() const
     {