Giter VIP home page Giter VIP logo

unauthorized's Introduction

Sticky '401 Unauthorized' response

Recently it was observed that under a specific set of pre-conditions Apache's HttpClient could be left in a non functional state. This project is a simplified reproduction of the problem.

More specifically, if basic authentication is implemented in minimalistic way passing multiple CredentialsProvider instances through same context, socket timeouts may cause client to enter a state where it always returns '401 Unauthorized' response to any request to the same service.

This example/test/demo is using traditional blocking http client 4.5.13, but identical behavior was observed using asynchronous (non-blocking) apache http client 4.1.4 (not covered by code in this demo).

Desired outcome

Future versions of apache http client (both blocking and non-blocking) should handle timeouts in such a way that socket timeouts cause only transient errors, without long lasting effects, even if its usage may be considered unconventional. If that is not possible, then usage of http client that could lead to this issue should fail fast.

Issue description

  • normally apache http client issues pairs of requests for endpoints protected by basic http authentication - first one comes either with no 'Authorization' header or with previously used credentials, and then after '401 Unauthorized' response http client sends second request that uses credentials generated by provided CredentialsProvider
  • if api server always uses the same credentials, then after initial '401 Unauthorized' response all requests (made with the same context) will be authorized by default, simplifying request flow and eliminating issue observed
  • if api server requires different credentials for different requests (lets say, endpoint's url contains account id and different accounts require different credentials), then quite often wrong (cached on the context) credentials will be sent to the server before client rights itself by actually asking CredentialsProvider for new credentials - this is somewhat unintuitive behavior, but it is documented in javadocs, and expected
  • if first request from the pair of requests returns '401 Unauthorized' as it should, but next (properly authenticated) request times out, http client enters a strange 'damaged' state where for any following requests resulting in '401 Unauthorized' response they will NEVER be followed up by another request using provided credentials; because of this, one single network timeout can take out http client out of commision forever - it stays broken until JVM restart
  • if it is first request from the pair of requests that times out instead of returning '401 Unauthorized' response, http client does not enter 'damaged' state and behaves properly during next request using the same context
  • occasional http timeouts will take our some http clients from the usual pooled configuration, resulting in strange intermittent '401 Unauthorized' failures, that are difficult to troubleshoot and are easy to blame on bugs in api/server implementation; a spike of timeouts that can sometime happen takes down all available http clients, resulting in inability to communicate with api until JVM restart

Workarounds discovered

  • use new context for every request
  • add code that forces apache client to perform preemptive authentication - every call to http client results in only one http request, and timeouts are handled properly
  • reset AuthState after every http call - that ensures that fresh credentials are used for every request, and it also somehow ensures that timeouts are handled properly
  • do not use CredentialsProvider at all and just insert 'Authorization' header directly, effectively implementing preemptive authentication

Why this issue is quite dangerous

While workarounds are a fairly good idea all by themselves (if one deals with api that uses multiple credentials, it is good idea to use one of those approaches anyway), they are not exactly intuitive and may be left out by many developers unfamiliar with the details of apache http client library.

Default behavior in this case might be slightly inefficient (with half of http requests having either no credentials or wrong credentials) but it will still function as expected, until a particular sequence of timeouts happens, resulting in either partial or complete downtime for a service.

How to reproduce the issue

To build/run project, you should have maven installed, and you can just execute

./run.sh

This project contains embedded web server implementing required endpoint, so it is fairly self-contained, but you have to make sure that port 8089 is available, or change SERVER_PORT constant.

Test outputs main events to stdout, so it is fairly easy to follow what happens without resorting to a debugger.

There is a variable TRIGGER_TIMEOUT in file ApacheTimeoutExample.java, you can change it from 'true' to 'false', re-run the experiment, and see how it behaves under normal conditions (without timeout). There is also flag RESET_AUTH_STATE that allows resetting AuthState after every request, you can enable it and observe disappearance of the 'sticky' '401 Unauthorized' responses.

If more debugging output from apache http client is desired, modify some pre-existing setup in script run.sh (verbose logging is disabled by default).

Examples of services affected by this issue

unauthorized's People

Contributors

olek avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.