Good afternoon overfloftsy ! We are working on a project, the other day, we encountered a flaw in the AppAuth-Android library. There is no synchronous request to update tokens.

After each data request, a check is performed: has the token failed? If this is the case, it should update it and repeat the request for the data. The library implements token update only asynchronously . But in the logic of this application, and the class, the request must be synchronous. Now, the implementation of the update is done in the forehead, i.e. a request is made, and sends for receiving a token. Alas, for some reason the request does not work. Swears at the wrong request, although the fields are verified and tried again 10. I am tired of the right to deal with him, and try to fix this crutch. Tell me, how can you implement the synchronous update logic using this? Perhaps someone faced this problem.

AuthInterceptorBase interceptor code :

public class AuthInterceptorBase implements Interceptor{ protected Context context; private static final String TAG = "AuthInterceptorBase"; public AuthInterceptorBase(Context context) { this.context = context; } @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); Response response = chain.proceed(chain.request()); if (response.code() == 401){ Log.i(TAG, "Refreshing..."); Request.Builder newRequestBuilder = chain.request().newBuilder(); boolean isSuccess = refreshToken(context); if (!isSuccess){ Log.i(TAG, "Refreshing failed!"); return new Response.Builder().request(originalRequest) .protocol(Protocol.HTTP_2) .code(401) .message("Refreshing token failed") .addHeader("Content-Type", "application/vnd.aditro.hateoas+json; charset=utf-8") .body(response.body()) //body is necessary for Response otherwise Runtime exception will be thrown .build(); } else { String newAccessToken = SharedPrefsUtils.getAccessToken(context); newRequestBuilder.header("Authorization", "Bearer " + newAccessToken); return chain.proceed(newRequestBuilder.build()); } } else { return response; } } private static synchronized boolean refreshToken(Context context) { try { OkHttpClient client = new OkHttpClient(); String oldToken = SharedPrefsUtils.getAccessToken(context); String oldRefreshToken = AuthStateHelper.getRefreshToken(context); if (StringFormatter.isStringNullOrEmpty(oldToken) || StringFormatter.isStringNullOrEmpty(oldRefreshToken)){ Log.e(TAG, "no oldToken or refreshToken found: " + oldToken); return false; } RequestBody formBody = new FormBody.Builder() .add("grant_type", "refresh_token") .add("scope", "openid graph-api offline_access") .add("client_id", "native-app-client") .add("refresh_token", oldRefreshToken) .add("token_type", "Bearer") .build(); final Request request = new Request .Builder() .addHeader("Accept", "application/json") .addHeader("Authorization", "Bearer " + oldToken) .addHeader("Content-Type", "application/x-www-form-urlencoded") .url(APIConfig.TOKEN_ENDPOINT) .post(formBody) .build(); Response response = client.newCall(request).execute(); Log.i(TAG, "Response: " + response.body()); if (response.code() != 200) return false; try{ String body = response.body().string(); JSONObject object = new JSONObject(body); AuthStateHelper.saveAuthState( context, object.getString("access_token"), object.getString("id_token"), object.getString("refresh_token")); Log.i(TAG, "New access token: " + object.getString("access_token")); Log.i(TAG, "New refresh token: " + object.getString("refresh_token")); return true; } catch (JSONException e){ e.printStackTrace(); return false; } } catch (IOException e) { e.printStackTrace(); return false; } } } 

The library is used in both ISO and Android versions. Project outsource . IOS has the same problem.

    1 answer 1

    In the end, it was still easier to fix the request. Resource https://jwt.io/ helped - parse tokens, we saw invalid fields. Changed them - it all worked.