diff --git a/ivy/src/main/java/internal/librarymanagement/JavaNetAuthenticator.java b/ivy/src/main/java/internal/librarymanagement/JavaNetAuthenticator.java new file mode 100644 index 000000000..10a0e6285 --- /dev/null +++ b/ivy/src/main/java/internal/librarymanagement/JavaNetAuthenticator.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2013 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package sbt.internal.librarymanagement; + +import java.io.IOException; +import java.net.Authenticator.RequestorType; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.util.List; +import okhttp3.Authenticator; +import okhttp3.Route; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.HttpUrl; +import okhttp3.Challenge; +import okhttp3.Credentials; + +/** + * Adapts {@link java.net.Authenticator} to {@link Authenticator}. Configure OkHttp to use {@link + * java.net.Authenticator} with {@link OkHttpClient.Builder#authenticator} or {@link + * OkHttpClient.Builder#proxyAuthenticator(Authenticator)}. + */ +public final class JavaNetAuthenticator implements Authenticator { + @Override public Request authenticate(Route route, Response response) throws IOException { + List challenges = response.challenges(); + Request request = response.request(); + HttpUrl url = request.url(); + boolean proxyAuthorization = response.code() == 407; + Proxy proxy = null; + if (route != null) { + proxy = route.proxy(); + } + + for (int i = 0, size = challenges.size(); i < size; i++) { + Challenge challenge = challenges.get(i); + if (!"Basic".equalsIgnoreCase(challenge.scheme())) continue; + + PasswordAuthentication auth; + if (proxyAuthorization) { + InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address(); + auth = java.net.Authenticator.requestPasswordAuthentication( + proxyAddress.getHostName(), getConnectToInetAddress(proxy, url), proxyAddress.getPort(), + url.scheme(), challenge.realm(), challenge.scheme(), url.url(), + RequestorType.PROXY); + } else { + auth = java.net.Authenticator.requestPasswordAuthentication( + url.host(), getConnectToInetAddress(proxy, url), url.port(), url.scheme(), + challenge.realm(), challenge.scheme(), url.url(), RequestorType.SERVER); + } + + if (auth != null) { + String credential = Credentials.basic(auth.getUserName(), new String(auth.getPassword())); + return request.newBuilder() + .header(proxyAuthorization ? "Proxy-Authorization" : "Authorization", credential) + .build(); + } + } + + return null; // No challenges were satisfied! + } + + private InetAddress getConnectToInetAddress(Proxy proxy, HttpUrl url) throws IOException { + return (proxy != null && proxy.type() != Proxy.Type.DIRECT) + ? ((InetSocketAddress) proxy.address()).getAddress() + : InetAddress.getByName(url.host()); + } +} diff --git a/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/GigahorseUrlHandler.scala b/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/GigahorseUrlHandler.scala index a1109dc91..e760483a8 100644 --- a/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/GigahorseUrlHandler.scala +++ b/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/GigahorseUrlHandler.scala @@ -9,7 +9,7 @@ import scala.util.control.NonFatal import okhttp3.{ MediaType, OkUrlFactory, Request, RequestBody } import okhttp3.internal.http.HttpDate -import okhttp3._ +import okhttp3.{ JavaNetAuthenticator => _, _ } import okio._ import org.apache.ivy.util.{ CopyProgressEvent, CopyProgressListener, Message } @@ -198,7 +198,7 @@ class GigahorseUrlHandler extends AbstractURLHandler { object GigahorseUrlHandler { import gigahorse.HttpClient import gigahorse.support.okhttp.Gigahorse - import okhttp3.{ OkHttpClient, JavaNetAuthenticator } + import okhttp3.OkHttpClient // This is requires to access the constructor of URLInfo. private[sbt] class SbtUrlInfo(available: Boolean, @@ -219,7 +219,7 @@ object GigahorseUrlHandler { http .underlying[OkHttpClient] .newBuilder() - .authenticator(new JavaNetAuthenticator) + .authenticator(new sbt.internal.librarymanagement.JavaNetAuthenticator) .followRedirects(true) .followSslRedirects(true) .build