in lib/src/http_impl.dart [341:451]
Future<HttpClientResponse> _authenticate(bool proxyAuth) {
Future<HttpClientResponse> retry() {
// Drain body and retry.
return drain().then((_) {
return _httpClient
._openUrlFromRequest(
_httpRequest.method, _httpRequest.uri, _httpRequest)
.then((request) => request.close());
});
}
List<String> authChallenge() {
return proxyAuth
? headers[HttpHeaders.PROXY_AUTHENTICATE]
: headers[HttpHeaders.WWW_AUTHENTICATE];
}
_Credentials findCredentials(_AuthenticationScheme scheme) {
return proxyAuth
? _httpClient._findProxyCredentials(_httpRequest._proxy, scheme)
: _httpClient._findCredentials(_httpRequest.uri, scheme);
}
void removeCredentials(_Credentials cr) {
if (proxyAuth) {
_httpClient._removeProxyCredentials(cr);
} else {
_httpClient._removeCredentials(cr);
}
}
Future<bool> requestAuthentication(
_AuthenticationScheme scheme, String realm) {
if (proxyAuth) {
if (_httpClient._authenticateProxy == null) {
return Future.value(false);
}
var proxy = _httpRequest._proxy;
return _httpClient._authenticateProxy(
proxy.host, proxy.port, scheme.toString(), realm);
} else {
if (_httpClient._authenticate == null) {
return Future.value(false);
}
return _httpClient._authenticate(
_httpRequest.uri, scheme.toString(), realm);
}
}
List<String> challenge = authChallenge();
assert(challenge != null || challenge.length == 1);
HeaderValueImpl header =
HeaderValueImpl.parse(challenge[0], parameterSeparator: ",");
_AuthenticationScheme scheme =
_AuthenticationScheme.fromString(header.value);
String realm = header.parameters["realm"];
// See if any matching credentials are available.
_Credentials cr = findCredentials(scheme);
if (cr != null) {
// For basic authentication don't retry already used credentials
// as they must have already been added to the request causing
// this authenticate response.
if (cr.scheme == _AuthenticationScheme.BASIC && !cr.used) {
// Credentials where found, prepare for retrying the request.
return retry();
}
// Digest authentication only supports the MD5 algorithm.
if (cr.scheme == _AuthenticationScheme.DIGEST &&
(header.parameters["algorithm"] == null ||
header.parameters["algorithm"].toLowerCase() == "md5")) {
if (cr.nonce == null || cr.nonce == header.parameters["nonce"]) {
// If the nonce is not set then this is the first authenticate
// response for these credentials. Set up authentication state.
if (cr.nonce == null) {
cr
..nonce = header.parameters["nonce"]
..algorithm = "MD5"
..qop = header.parameters["qop"]
..nonceCount = 0;
}
// Credentials where found, prepare for retrying the request.
return retry();
} else if (header.parameters["stale"] != null &&
header.parameters["stale"].toLowerCase() == "true") {
// If stale is true retry with new nonce.
cr.nonce = header.parameters["nonce"];
// Credentials where found, prepare for retrying the request.
return retry();
}
}
}
// Ask for more credentials if none found or the one found has
// already been used. If it has already been used it must now be
// invalid and is removed.
if (cr != null) {
removeCredentials(cr);
cr = null;
}
return requestAuthentication(scheme, realm).then((credsAvailable) {
if (credsAvailable) {
cr = _httpClient._findCredentials(_httpRequest.uri, scheme);
return retry();
} else {
// No credentials available, complete with original response.
return this;
}
});
}