Как добавить аутентификацию с токеном обновления с помощью асинхронного запроса в аутентификаторе 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 не имеет синхронного типа запроса, который я могу использовать. Не могли бы вы указать мне, как мне использовать этот код в классе аутентификатора. Пожалуйста, помогите мне с этой проблемой.


person Rahul Chaurasia    schedule 20.08.2018    source источник
comment
App ID не имеет синхронного API. Все API в Android SDK являются асинхронными. Однако вы можете обернуть их синхронно, отправив запрос с помощью AppID.getInstance().signinWithRefreshToken и остановив текущий поток до тех пор, пока ответ не будет возвращен в обратном вызове. Вы можете попытаться добиться этого с помощью одного из параметров синхронизации потоков Java, таких как: ожидание/уведомление, CountDownLatch, BlockingQueue, Future и т. д.   -  person Moty Drimer    schedule 21.08.2018


Ответы (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);
    }

Надеюсь, это поможет и вам. :) Удачного программирования...!!!

person Devangi    schedule 13.09.2018

У меня есть два решения, которые могут вас заинтересовать:

  1. Вызов API самостоятельно. Это может быть сложно, но вы также можете просмотреть AppId SDK для помощь.
  2. Разветвите и измените AppId SDK с помощью синхронного вызова signinWithRefreshToken() и использовать это. Также не забудьте создать запрос функции или запрос на извлечение об этом изменении в исходном репозитории, чтобы это могло быть включено в следующую версию.
    Недостатком этого является то, что вам нужно поддерживать другую вилку SDK AppId и объединять новые меняет сверхурочные, если это необходимо.
person Flekken    schedule 20.08.2018