1

What is the right way to have a REST endpoint support basic authentication and work with XHR?

I am using the Django REST Framework (DRF) to create a set of REST endpoints. These endpoints will be used by an single-page application (SPA) through a set of XHR (AJAX) calls as well from a C++ application. The C++ application is currently using the Qt framework. Within the Qt framework, I am using QNetworkAccessManager along with QAuthenticator. The authenticationRequired signal is emitted "whenever a final server requests authentication" which I believe is driven by the WWW-Authenticate header in a 401 response (I am currently using basic authentication).

I am trying to figure out how to set up Authentication in Django REST to make both my SPA and the C++ application happy. I posted this question: Why does SessionAuthentication in Django REST Framework Never Return HTTP401 and what I learned is that I can get 401s (with the WWW-Authenticate header) from DRF if I set the first Authentication class to BasicAuthentication. This however causes the browser to popup a modal login dialog when it receives the 401.

What is the best way to make the browser happy and provide the 401s with WWW-Authenticate header? One idea would be to use one Authentication class for requests from the C++ app and a different Authentication class for requests from a browser.

Login box on Chrome: login_box

Community
  • 1
  • 1
Alex Rothberg
  • 10,243
  • 13
  • 60
  • 120

2 Answers2

1

The way I ended up solving this was to subclass BasicAuthentication and override authenticate_header to return the 401 code with the WWW-Authenticate header only if a certain header is set in the request. Any client needing the 401 code (e.g. the C++ Application) make sure to set this header value in all of the requests that it makes. In DRF settings, I then set this authentication class as the first class and then put SessionAuthentication second.

Alex Rothberg
  • 10,243
  • 13
  • 60
  • 120
0

If the client knows a priori that the server requires basic authentication for a resource, it can include the Authorization header with each request and avoid receiving the 401 (Unauthorized) response with the WWW-Authorization header.

On the client (both javascript and c++), concatenate the client identifier (e.g., the username if the client is making a request on behalf of a user) and the shared secret (such as a password) as <identifier>:<secret>, and then compute a Base64 encoding of this text. Include the value of the resulting text in an Authorization header in client requests:

Authorization: Basic <Base64 encoded value>
vahan
  • 21
  • 3