6

Since 23 sdk Android class were excluded classes:

org.apache.http.auth.AuthScheme;
org.apache.http.auth.AuthSchemeFactory;
org.apache.http.impl.auth.NTLMScheme;
org.apache.http.impl.auth.NTLMEngine;
org.apache.http.impl.auth.NTLMEngineException;

As it is now authorized in AD, with login and password through a retrofit? There OKHttpklient can be through headers?

Vadim Seleznev
  • 471
  • 1
  • 6
  • 6

2 Answers2

2

1) add package org.apache.httpcomponents:httpclient:4.5 to build.gradle (app)

//noinspection DuplicatePlatformClasses
implementation '**org.apache.httpcomponents:httpclient:4.5**'

2) Add package org.apache.http.impl.auth to your project (folder in /java)

3) Create public class in added org.apache.http.impl.auth package

public class PublicNTLMEngineImpl implements NTLMEngine {
  // with content of http://svn.apache.org/repos/asf/httpcomponents/httpclient/tags/4.5.2/httpclient/src/main/java/org/apache/http/impl/auth/NTLMEngineImpl.java
}

4) use Giohji's NTLMAuthenticator with instance of new PublicNTLMEngineImpl

OkHttpClient httpClient = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .authenticator(new NTLMAuthenticator(username, password, domainOrComputerName))
                .build();

5) source code: http://svn.apache.org/repos/asf/httpcomponents/httpclient/tags/4.5.2/httpclient/src/main/java/org/apache/http/impl/auth/

Roman M
  • 450
  • 1
  • 5
  • 12
0

I found the answer on okhttp's github. It was posted by SelvinPL.

First you have to implement the NTLM authenticator (it uses NTLMEngineImpl, a standalone version of org.apache.http.impl.auth.NTLMEngineImpl, which was also created by SelvinPL). The code below is a slightly modified version of SelvinPL's implementation to run on the latest retrofit's version (2.1.0).

private static class NTLMAuthenticator implements Authenticator {
    final NTLMEngineImpl engine = new NTLMEngineImpl();
    private final String domain;
    private final String username;
    private final String password;
    private final String ntlmMsg1;

    private NTLMAuthenticator(String username, String password, String domain) {
        this.domain = domain;
        this.username = username;
        this.password = password;
        String localNtlmMsg1 = null;
        try {
            localNtlmMsg1 = engine.generateType1Msg(null, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        ntlmMsg1 = localNtlmMsg1;
    }

    @Override
    public Request authenticate(Route route, Response response) throws IOException {
        final List<String> WWWAuthenticate = response.headers().values("WWW-Authenticate");
        if (WWWAuthenticate.contains("NTLM")) {
            return response.request().newBuilder().header("Authorization", "NTLM " + ntlmMsg1).build();
        }
        String ntlmMsg3 = null;
        try {
            ntlmMsg3 = engine.generateType3Msg(username, password, domain, "android-device", WWWAuthenticate.get(0).substring(5));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response.request().newBuilder().header("Authorization", "NTLM " + ntlmMsg3).build();
    }
}

Then you can register the authenticator like this example:

OkHttpClient client = new OkHttpClient.Builder()
            .authenticator(new NTLMAuthenticator(username, password, domain))
            .build();
Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(getURL(context))
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();
return retrofit.create(Api.class);

It works for com.squareup.retrofit2:retrofit:2.1.0.

Giohji
  • 714
  • 7
  • 12