in httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/HttpAuthenticator.java [150:289]
public boolean updateAuthState(
final HttpHost host,
final ChallengeType challengeType,
final HttpResponse response,
final AuthenticationStrategy authStrategy,
final AuthExchange authExchange,
final HttpContext context) {
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final String exchangeId = clientContext.getExchangeId();
if (LOG.isDebugEnabled()) {
LOG.debug("{} {} requested authentication", exchangeId, host.toHostString());
}
final Header[] headers = response.getHeaders(
challengeType == ChallengeType.PROXY ? HttpHeaders.PROXY_AUTHENTICATE : HttpHeaders.WWW_AUTHENTICATE);
final Map<String, AuthChallenge> challengeMap = new HashMap<>();
for (final Header header: headers) {
final CharArrayBuffer buffer;
final int pos;
if (header instanceof FormattedHeader) {
buffer = ((FormattedHeader) header).getBuffer();
pos = ((FormattedHeader) header).getValuePos();
} else {
final String s = header.getValue();
if (s == null) {
continue;
}
buffer = new CharArrayBuffer(s.length());
buffer.append(s);
pos = 0;
}
final ParserCursor cursor = new ParserCursor(pos, buffer.length());
final List<AuthChallenge> authChallenges;
try {
authChallenges = parser.parse(challengeType, buffer, cursor);
} catch (final ParseException ex) {
if (LOG.isWarnEnabled()) {
LOG.warn("{} Malformed challenge: {}", exchangeId, header.getValue());
}
continue;
}
for (final AuthChallenge authChallenge: authChallenges) {
final String schemeName = authChallenge.getSchemeName().toLowerCase(Locale.ROOT);
if (!challengeMap.containsKey(schemeName)) {
challengeMap.put(schemeName, authChallenge);
}
}
}
if (challengeMap.isEmpty()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} Response contains no valid authentication challenges", exchangeId);
}
authExchange.reset();
return false;
}
switch (authExchange.getState()) {
case FAILURE:
return false;
case SUCCESS:
authExchange.reset();
break;
case CHALLENGED:
case HANDSHAKE:
Asserts.notNull(authExchange.getAuthScheme(), "AuthScheme");
case UNCHALLENGED:
final AuthScheme authScheme = authExchange.getAuthScheme();
if (authScheme != null) {
final String schemeName = authScheme.getName();
final AuthChallenge challenge = challengeMap.get(schemeName.toLowerCase(Locale.ROOT));
if (challenge != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} Authorization challenge processed", exchangeId);
}
try {
authScheme.processChallenge(challenge, context);
} catch (final MalformedChallengeException ex) {
if (LOG.isWarnEnabled()) {
LOG.warn("{} {}", exchangeId, ex.getMessage());
}
authExchange.reset();
authExchange.setState(AuthExchange.State.FAILURE);
return false;
}
if (authScheme.isChallengeComplete()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} Authentication failed", exchangeId);
}
authExchange.reset();
authExchange.setState(AuthExchange.State.FAILURE);
return false;
}
authExchange.setState(AuthExchange.State.HANDSHAKE);
return true;
}
authExchange.reset();
// Retry authentication with a different scheme
}
}
final List<AuthScheme> preferredSchemes = authStrategy.select(challengeType, challengeMap, context);
final CredentialsProvider credsProvider = clientContext.getCredentialsProvider();
if (credsProvider == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} Credentials provider not set in the context", exchangeId);
}
return false;
}
final Queue<AuthScheme> authOptions = new LinkedList<>();
if (LOG.isDebugEnabled()) {
LOG.debug("{} Selecting authentication options", exchangeId);
}
for (final AuthScheme authScheme: preferredSchemes) {
try {
final String schemeName = authScheme.getName();
final AuthChallenge challenge = challengeMap.get(schemeName.toLowerCase(Locale.ROOT));
authScheme.processChallenge(challenge, context);
if (authScheme.isResponseReady(host, credsProvider, context)) {
authOptions.add(authScheme);
}
} catch (final AuthenticationException | MalformedChallengeException ex) {
if (LOG.isWarnEnabled()) {
LOG.warn(ex.getMessage());
}
}
}
if (!authOptions.isEmpty()) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} Selected authentication options: {}", exchangeId, authOptions);
}
authExchange.reset();
authExchange.setState(AuthExchange.State.CHALLENGED);
authExchange.setOptions(authOptions);
return true;
}
return false;
}