at the first I am sorry for my poor english.
I am developing an android app with nodejs backend.JWT is used for authorization, so I send access token to the server to authorize my request. access token life is short and expire in 60s. for refreshing the access token the app must to send refresh token to server. for this purpose I am using OkHttp authenticator but authenticator is not work. can any body help me to solve this problem
ServiceGenerator
public class ServiceGenerator {
private static final OkHttpClient httpClient =
new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.build();
private static final Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static Retrofit retrofit = builder.build();
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient).build();
return retrofit.create(serviceClass);
}
public static <S> S createServiceWithAuth(Class<S> serviceClass, String accessToken, Context context) {
OkHttpClient newClient = httpClient.newBuilder().addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
if(!accessToken.isEmpty()){
builder.addHeader("x-auth-token", accessToken);
}
request = builder.build();
return chain.proceed((request));
}
}).authenticator(CustomAuthenticator.getInstance(accessToken, context))
.build();
Retrofit newRetrofit = retrofit.newBuilder().client(newClient).baseUrl(API_BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
return newRetrofit.create(serviceClass);
}
}
CustomAuthenticator
public class CustomAuthenticator implements Authenticator {
private String accessToken;
private static CustomAuthenticator INSTANCE;
Context context;
private CustomAuthenticator(String accessToken, Context context){
this.accessToken = accessToken;
Hawk.init(context).build();
this.context = context;
}
static synchronized CustomAuthenticator getInstance(String accessToken, Context context){
if(INSTANCE == null){
INSTANCE = new CustomAuthenticator(accessToken, context);
}
return INSTANCE;
}
@Nullable
@Override
public Request authenticate(@Nullable Route route, @NotNull Response response) throws IOException {
if(responseCount(response) >= 2){
return null;
}
ApiClient client = ServiceGenerator.createService(ApiClient.class);
User user = new User();
user.setRefreshToken(Hawk.get("RefreshToken"));
Call<User> refreshAccessTokenCall = client.refresh(user);
retrofit2.Response<User> res = refreshAccessTokenCall.execute();
if(res.isSuccessful()){
assert res.body() != null;
String accessToken = res.body().getAccessToken();
Hawk.put("AccessToken", accessToken);
return response.request().newBuilder().addHeader("x-auth-token", res.body().getAccessToken()).build();
}else{
return null;
}
}
private int responseCount(Response response){
int result = 1;
while ((response = response.priorResponse()) != null){
result++;
}
return result;
}
}
and method that POST data to server (in Fragment)
private void saveExpert() {
if (!validate()) {
return;
}
progressBar.setVisibility(View.VISIBLE);
Objects.requireNonNull(getActivity()).getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
String first_and_last_name = firstAndLastName.getText().toString();
String national_code = nationalCode.getText().toString();
String phone_number = phoneNumber.getText().toString();
String home_office_city = homeOfficeCity.getText().toString();
String _address = address.getText().toString();
String _field = field.getText().toString();
String sub_field = subField.getText().toString();
String _grade = grade.getText().toString();
ApiClient client = ServiceGenerator.createServiceWithAuth(ApiClient.class, Hawk.get("AccessToken"), getContext());
SetExpert setExpert = new SetExpert(first_and_last_name, national_code, phone_number, home_office_city, _address, _field, sub_field, _grade);
Call<Expert> expertCall = client.saveExpert(setExpert);
expertCall.enqueue(new Callback<Expert>() {
@Override
public void onResponse(@NotNull Call<Expert> call, @NotNull Response<Expert> response) {
if (response.isSuccessful()) {
Expert expert = response.body();
if (expert != null) {
Hawk.init(Objects.requireNonNull(getContext())).build();
Hawk.put("ExpertNationalCode", expert.getNational_code());
progressBar.setVisibility(View.GONE);
Objects.requireNonNull(getActivity()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
new MaterialDialog.Builder(Objects.requireNonNull(getContext()))
.typeface("IRANSansWebMedium.ttf", "IRANSansWeb.ttf")
.title("???? ?????")
.content(expert.getFirst_and_last_name() + " ???? ?? ???? ?? ??? ??? ???. ??? ??? ??? ?? ????? ????? ????? ????? ? ?? ?? ????? ?????? ? ?????? ?? ??? ???? ????? ????? ??.")
.positiveText("?????.")
.canceledOnTouchOutside(false)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dismiss();
}
})
.show();
}
} else {
ApiError apiError = ErrorUtils.parseError(response);
progressBar.setVisibility(View.GONE);
Objects.requireNonNull(getActivity()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
Toast.makeText(getContext(), apiError.getMessage(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(@NotNull Call<Expert> call, @NotNull Throwable t) {
progressBar.setVisibility(View.GONE);
Objects.requireNonNull(getActivity()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
question from:
https://stackoverflow.com/questions/65857818/retrofit-authenticator-called-but-not-work 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…