Dynamically Change Credentials
Closed this issue · 3 comments
Hello everyone.
I need to change the Credentials on runtime without having to build a new instance of my OkHttpClient.
Is it possible? What would be a good alternative?
I am using Dagger2 to keep singleton instances of my Retrofit and OkHttpClient. It works flawlessly with the credentials of the 'default' user but I need to change them later on to access other methods.
@Provides
@Singleton
@DigestAuth
Credentials provideDigestAuthCredentials(){
return new Credentials("default", "default");
}
@Provides
@Singleton
@DigestAuth
OkHttpClient provideDigestAuthOkHttpClient(@DigestAuth Credentials credentials,
@DigestAuth UrlHostSelectionInterceptor urlHostSelectionInterceptor){
final DigestAuthenticator digestAuthenticator = new DigestAuthenticator(credentials);
final Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>();
return new OkHttpClient.Builder()
.addInterceptor(urlHostSelectionInterceptor)
.authenticator(new CachingAuthenticatorDecorator(digestAuthenticator,authCache))
.addInterceptor(new AuthenticationCacheInterceptor(authCache))
.build();
}
@Provides
@Singleton
@DigestAuth
Retrofit provideDigestAuthRetrofit(@DigestAuth OkHttpClient okHttpClient, Gson gson){
return new Retrofit.Builder()
.baseUrl(GlobalConstants.LAN_DEFAULT_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpClient)
.build();
}
Hello!
I have been using thus far something like this, since I don't have the credentials on app startup:
public interface CredentialsProvider {
@Nullable String getIdentity();
@Nullable String getPassword();
}
public class Credentials extends com.burgstaller.okhttp.digest.Credentials {
private final @NonNull CredentialsProvider provider;
public Credentials(
@NonNull CredentialsProvider provider
) {
super(null, null);
this.provider = Check.nonNull(provider);
}
@Override
public @Nullable String getUserName() {
return provider.getIdentity();
}
@Override
public @Nullable String getPassword() {
return provider.getPassword();
}
@Override
public final void setUserName(String userName) {
throw new UnsupportedOperationException();
}
@Override
public final void setPassword(String password) {
throw new UnsupportedOperationException();
}
}
By using an interface to supply the credentials you can avoid recreating the whole client, but maybe the cache Map<String, CachingAuthenticator>
should be cleared when changing them.
clearing the cache is definitely necessary as pre-existing authentications will probalby no longer work.
sorry for not coming back earlier
I have added a test case for how updating the username/password mid-flight. https://github.com/rburgst/okhttp-digest/blob/master/src/test/java/com/burgstaller/okhttp/basic/BasicAuthenticatorWithMockWebserverTest.java#L111.
Please let me know if I should keep this issue open, otherwise I will close it in the coming days.