Как добавить аутентификацию с токеном обновления с помощью асинхронного запроса в аутентификаторе okhttp3
У меня есть аутентификатор, подключенный к клиенту Okhttp3, который успешно вызывается, когда приходит ответ 401. В аутентификаторе я хочу аутентифицировать пользователя с токеном обновления. Я использую IBM AppId для аутентификации.
private Authenticator getAuthenticator() {
return new Authenticator() {
@Override
public Request authenticate(Route route, Response response) throws IOException {
// code to authenticate with refresh token
return null;
}
};
}
И у меня есть следующий код для аутентификации с помощью токена обновления:
AppID.getInstance().signinWithRefreshToken(getApplicationContext(), refreshTokenString, new AuthorizationListener() {
@Override
public void onAuthorizationFailure(AuthorizationException exception) {
//Exception occurred
}
@Override
public void onAuthorizationCanceled() {
//Authentication canceled by the user
}
@Override
public void onAuthorizationSuccess(AccessToken accessToken, IdentityToken identityToken, RefreshToken refreshToken) {
//User authenticated
}
});
Теперь, как вы можете видеть, что это асинхронный запрос, и я не могу поместить этот код в аутентификатор, потому что метод будет возвращаться до вызова onAuthorizationSuccess(). Кроме того, у AppId нет синхронного типа запроса, который я могу использовать. Подскажите, пожалуйста, как мне использовать этот код в классе аутентификатора. Пожалуйста, помогите мне с этим вопросом.
2 ответа
У меня есть решение для этого. Пожалуйста, попробуйте ниже код.
Сделать класс как: TokenAuthenticator.java
import android.content.Context;
import android.support.annotation.Nullable;
import com.dmlllc.insideride.common.Preferences;
import com.dmlllc.insideride.model.AccessToken;
import com.dmlllc.insideride.restModel.RestResponse;
import com.dmlllc.insideride.restModel.requestModel.AccessTokenReq;
import java.io.IOException;
import okhttp3.Authenticator;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;
public class TokenAuthenticator implements Authenticator {
private Context context;
public TokenAuthenticator(Context context) {
this.context = context;
}
@Nullable
@Override
public Request authenticate(Route route, Response response) throws IOException {
// Refresh your access_token using a synchronous api request
AccessTokenReq accessTokenReq = new AccessTokenReq(Preferences.getPreferenceString(context, Preferences.USERNAME_FOR_TOKEN, ""),
Preferences.getPreferenceString(context, Preferences.PASSWORD_FOR_TOKEN, ""));
try {
retrofit2.Response<RestResponse<AccessToken>> tokenResponse = Global.initRetrofit(context).getAccessToken(accessTokenReq).execute();
if (tokenResponse.body() != null) {
if (tokenResponse.body().getResStatus().equals("success")) {
SessionManager sessionManager = new SessionManager(context);
sessionManager.storeToken(tokenResponse.body().getResults().getYourAccessToken());
Preferences.setPreferenceString(context, Preferences.ACCESS_TOKEN, tokenResponse.body().getResults().getYourAccessToken());
}
}
}catch (Exception e){
e.printStackTrace();
}
// Add new header to rejected request and retry it
return response.request().newBuilder()
.header("Authorization", Preferences.getPreferenceString(context, Preferences.ACCESS_TOKEN, ""))
.build();
}
}
А затем используйте этот класс в своем методе модернизации, как:
public static RestApi initRetrofit(Context context) {
// For logging request & response (Optional)
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
TokenAuthenticator tokenAuthenticator = new TokenAuthenticator(context);
OkHttpClient client = new OkHttpClient.Builder()
.authenticator(tokenAuthenticator)
.addInterceptor(loggingInterceptor)
.connectTimeout(1, TimeUnit.MINUTES)
.writeTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit.create(RestApi.class);
}
Надеюсь, это поможет вам также. :) Счастливого кодирования...!!!
У меня есть два решения, которые могут вас заинтересовать:
- Вызов API самостоятельно. Это может быть сложно, но вы также можете просмотреть AppId SDK за помощью.
- Разветвите и измените AppId SDK с помощью синхронного вызова signinWithRefreshToken() и используйте его. Также убедитесь, что вы создали запрос функции или запрос на извлечение информации об этом изменении в исходном репо, чтобы он мог быть включен в следующую версию.
Недостатком этого является то, что вам нужно поддерживать еще один ответвление AppId SDK и объединять новые изменения в случае необходимости.