У меня есть конечная точка входа в систему, по которой я получаю authToken и refreshToken. Срок действия первого истекает через час, поэтому я должен использовать второй, чтобы обновить его и продолжить работу приложения.
Теперь мое приложение повсюду заполнено вызовами на модернизацию, и я потенциально могу получить 401 в любой момент, так как я могу сделать так, чтобы каждый раз, когда я получаю 401, выдается токен обновления, а затем повторяется исходный запрос?
Это моя подпись обновления:
@POST("/auth/actions/refresh")
fun refreshToken(@Body tokenRefresh: TokenRefresh): Single<LoginResponse>
Я думал о создании базового класса репозитория с помощью метода withAuth(), который берет любой Observable / Single / Flowable, а затем применяет эту логику, но я не могу найти способ ее реализовать.
Видел кучу реализаций, но ни одна из них не соответствует моим потребностям ... может ли кто-нибудь подтолкнуть меня в правильном направлении?
Это ближайший Я обнаружил, однако, похоже, есть некоторые ошибки на плоском отображении
Я столкнулся с аналогичным требованием и предложил следующее решение. Это довольно просто, он просто делает одну попытку вызвать конечную точку REST, и если этот вызов терпит неудачу с HTTP 401, он повторно аутентифицируется и повторяет вызов снова. В противном случае он просто выдает исходную ошибку.
fun <T> Single<T>.withAuth() = retryWhen { errors ->
var firstAttempt = true
errors.flatMapSingle { error ->
if (firstAttempt && error is HttpException && error.code() == 401) {
firstAttempt = false
reauthenticate()
} else {
Single.error(it)
}
}
}
где функция повторной аутентификации имеет следующую подпись:
fun reauthenticate(): Single<AnyAuthResponse>
Обратите внимание, что конкретный тип исключения может зависеть от реализации HTTP, которую вы действительно используете, поэтому вы можете обновить условие для обнаружения ответа HTTP 401, но код должен дать вам общую картину того, как решить вашу проблему.
Я думаю, вы можете сделать это, не изменяя все вызовы. Добавьте Authenticator к вашему дооснащению
Обновление токена OAuth с помощью Retrofit без изменения всех вызовов
Вы можете использовать перехватчик, чтобы перехватить каждый запрос и проверить, возвращает ли он 401 - несанкционированный доступ, а затем обновить токен и воспроизвести текущий запрос API.
public final class SessionInterceptor implements Interceptor {
// gets intercept
@Override public Response intercept(@NonNull final Chain chain) throws IOException {
final Request request = chain.request();
final Response response = chain.proceed(request);
final ResponseBody responseBody = response.body();
if (response.code() == 401) {
synchronized (this) {
// Refresh your token
// Update your authToken + Refreshed token
final retrofit2.Response response = refreshToken();
}
}
// Replay the original request
// Perform request, here original request will be executed
final Request original = chain.request();
final Request.Builder builder = original.newBuilder();
// Set your new refreshed token
if (accessToken.isSet()) {
builder.header(AUTHORIZATION, String.format(BEARER,
accessToken.get()));
}
final Request request = builder.method(original.method(), original.body()).build();
return chain.proceed(request);
}
}