Uploaded image for project: 'Nuxeo Platform'
  1. Nuxeo Platform
  2. NXP-30507

Skip handleLogin when HTTP response has already been commited

    XMLWordPrintable

    Details

    • Type: Question
    • Status: Resolved
    • Priority: Minor
    • Resolution: Fixed
    • Affects Version/s: 10.10
    • Fix Version/s: 2023.1, 2021.42
    • Component/s: Authentication
    • Release Notes Summary:
      The Keycloak module delegates the redirect after auth failure to the default authentication mechanism.
    • Backlog priority:
      600
    • Sprint:
      nxsupport 16

      Description

      This scenario leads to an error:

      1. Use this authentication chain
          <extension target="org.nuxeo.ecm.platform.ui.web.auth.service.PluggableAuthenticationService" point="specificChains">
            <specificAuthenticationChain name="RestAPI">
              <urlPatterns>
                <url>(.*)/api/v.*</url>
              </urlPatterns>
              <replacementChain>
                <plugin>AUTOMATION_BASIC_AUTH</plugin>
                <plugin>KEYCLOAK_AUTH</plugin>
              </replacementChain>
            </specificAuthenticationChain>
          </extension>
        
      2. Get a Keycloak token
        curl --location --request POST 'https://{{url_keycloak}}/auth/realms/{{REALM}}/protocol/openid-connect/token' \
        --header 'Content-Type: application/x-www-form-urlencoded' \
        --data-urlencode 'client_id={{client_id}}' \
        --data-urlencode 'grant_type=password' \
        --data-urlencode 'scope=openid' \
        --data-urlencode 'username={{user}}' \
        --data-urlencode 'password={{password}}'
        
      3. Wait for the token to expire
      4. Use the expired token to run a REST call
        curl --location --request GET '{{nuxeo_url}}/nuxeo/api/v1/path/default-domain/workspaces/upload/test.mp4' \
        --header 'Authorization: Bearer  {{Jeton_KeyCloak}'
        
      5. The request returns a HTTP 500 error with this server error
        ERROR [http-nio-0.0.0.0-8080-exec-3] [DefaultNuxeoExceptionHandler] java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
        java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
                at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:472) ~[catalina-9.0.45.jar:9.0.45]
                at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129) ~[servlet-api-9.0.45.jar:4.0.FR]
                at org.nuxeo.ecm.platform.ui.web.auth.plugins.BasicAuthenticator.handleLoginPrompt(BasicAuthenticator.java:76) ~[nuxeo-platform-web-common-10.10-HF44.jar:?]
                at org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter.handleLogin(NuxeoAuthenticationFilter.java:1120) ~[nuxeo-platform-web-common-10.10-HF44.jar:?]
                at org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter.handleLoginPrompt(NuxeoAuthenticationFilter.java:1078) ~[nuxeo-platform-web-common-10.10-HF44.jar:?]
                at org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter.doFilterInternal(NuxeoAuthenticationFilter.java:563) ~[nuxeo-platform-web-common-10.10-HF44.jar:?]
                at org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter.doFilter(NuxeoAuthenticationFilter.java:431) ~[nuxeo-platform-web-common-10.10-HF44.jar:?]
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina-9.0.45.jar:9.0.45]
        

      The root cause is that the Keycloak module, which handles the authentication with the expired token, will return AuthOutcome.FAILED result and at the same time it will send the error in the HTTP response, and commits the response.

      Back to NuxeoAuthenticationFilter, it iterates over all available authentication plugin to find an appropriate one to prompt a login and BasicAuth will also return an error in the HTTP response which provokes the exception.

      Expected behavior is to return a HTTP 401 with no errror in the logs.

      Suggested fix:

      diff --git a/nuxeo-services/nuxeo-platform-web-common/src/main/java/org/nuxeo/ecm/platform/ui/web/auth/NuxeoAuthenticationFilter.java b/nuxeo-services/nuxeo-platform-web-common/src/main/java/org/nuxeo/ecm/platform/ui/web/auth/NuxeoAuthenticationFilter.java
      index 77198ecf3ba..0c53cf606da 100644
      --- a/nuxeo-services/nuxeo-platform-web-common/src/main/java/org/nuxeo/ecm/platform/ui/web/auth/NuxeoAuthenticationFilter.java
      +++ b/nuxeo-services/nuxeo-platform-web-common/src/main/java/org/nuxeo/ecm/platform/ui/web/auth/NuxeoAuthenticationFilter.java
      @@ -1080,8 +1080,11 @@ public class NuxeoAuthenticationFilter implements Filter {
           }
       
           private boolean handleLogin(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
      -        String baseURL = service.getBaseURL(httpRequest);
      +        if (httpResponse.isCommitted()) {
      +            return true;
      +        }
       
      +        String baseURL = service.getBaseURL(httpRequest);
               // go through plugins to get UserIdentity
               for (String pluginName : service.getAuthChain(httpRequest)) {
                   NuxeoAuthenticationPlugin plugin = service.getPlugin(pluginName);
      

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0 minutes
                  0m
                  Logged:
                  Time Spent - 5 hours, 30 minutes
                  5h 30m