MATLAB Answers

0

How do I preemptively include a Basic Authentication header when working with "webread"/​"webwrite"​/"websave" in MATLAB R2019b?

I have a web server which allows Basic authentication for non-interactive workflows and which supports a form based login plus cookies for interactive workflows. This means that:
1. If I make a request with a valid Basic Authentication header, the request simply succeeds, and
2. If I make a request without any Authentication header, the server redirects to the login form, i.e. it does not respond with 401 and a WWW-Authenticate header specifying which authorization methods it supports.
In MATLAB releases prior to R2019b, I could successfully work with this server using "webread" and passing along "weboptions" in which I specified 'Username' and 'Password', I got the response which I was expecting. In MATLAB R2019b making the same request returns the login page however instead of the data which I was expecting.

Tags

No tags entered yet.

Products

1 Answer

Answer by MathWorks Support Team on 12 Sep 2019
Edited by MathWorks Support Team on 12 Sep 2019
 Accepted Answer

In MATLAB releases prior to MATLAB R2019b, when you specified a 'Username' and 'Password' MATLAB would preemptively pass along these in a Basic Authentication header in the first request which "webread" makes. In MATLAB R2019b this changed, MATLAB now follows the challenge and response workflows from RFC-7235 more closely; which basically means it first makes a request without credentials expecting the server to return an "401 - Unauthorized" response in combination with a 'WWW-Authenticate' header specifying which authentication methods it supports. MATLAB then makes a second request with that particular authentication method. This is a more secure approach but this breaks workflows working with servers like the one described above.
If you still want "webread"/"webwrite"/"websave" to preemptive include a Basic Authentication header in the first request, do not specify 'Username' and 'Password' property/value pairs in "weboptions", instead use 'HeaderFields' to specify your own Authentication header. A Basic Authentication header is very simple to form: it is simply the text 'Basic ', followed by [username] colon [password] in base64 encoded format. So in MATLAB you could for example write:
% Example username and password
username = 'myUser';
password = 'myPassword';
% Manually set Authorization header field in weboptions
options = weboptions('HeaderFields',{'Authorization',...
['Basic ' matlab.net.base64encode([username ':' password])]});
% Make a request using these options
webread('https://httpbin.org/hidden-basic-auth/myUser/myPassword', options)
Note httpbin.org is a service for testing HTTP requests, the 'hidden-basic-auth' endpoint behaves in a way similar to described above (the request succeeds if you preemptively include a Basic Authorization header but immediately returns "404 - Not Found" if no (valid) authentication header was present). The myUser and myPassword specified in the request URL here is part of this particular testing endpoint, when calling your actual server you would normally not include your username and password in the request URL in this way, also do not call httpbin.org with you real username and password.
This approach also works correctly in MATLAB releases prior to R2019b.
Further note that the workflow for the HTTP interface has not changed. In this interface, if you explicitly specify 'Username', 'Password' and exactly one authentication method using a Credentials object, the Authorization header was always- and still is- preemptively included in the first request. So you can still write:
import matlab.net.http.*
% Create a credentials object. If you specify exactly one Scheme, we
% immediately automatically add the Authorization header for this Scheme,
% if you do not specify a Scheme we first make a request without any
% Authorization header expecting a server challenge.
creds = Credentials('Username','myUser','Password','myPassword',...
'Scheme', AuthenticationScheme.Basic);
% Add these credentials to the options
options = HTTPOptions('Credentials', creds);
% Create a request
req = RequestMessage('GET');
% Execute this request on some URL with these options
response = req.send('https://httpbin.org/hidden-basic-auth/myUser/myPassword',options);

  0 Comments

Sign in to comment.