How to implement a refresh token process with JWT for Android apps
13:29 23 Jul 2015

I'm working on a Oauth2 Token system to access my REST API for my Android app. I'm having some problems with the token refreshment part on the client side.

Here is the flow: My app makes a request (with an access Token in parameter) to the server thanks some asynctask ( PostCommentAsyncTask(), AddFriendAsyncTask() etc...), so if the accessToken is valid it's ok, but if it has expired I call another AsyncTask (GetRefreshTokenAsyncTask()) from the onPostExecute() method of the precedent AsyncTask to get new accessToken. Here is the tricky part for me. When I get the new access Token I want to re-execute the initial AsyncTask request to the server. I can't figure out how to do it properly.

example1:

request PostCommentAsyncTask() --> (acessToken expired) -->GetRefreshTokenAsyncTask()-->request PostCommentAsyncTask()--> (good token)--> Ok

EDIT:

I finally chose to use the Volley library ( no need to use Asynctask anymore ). As I use JSON Web Token I can check the expire date which is encoded in the payload of the token.

Here is the isAccessTokenExpired() method to check if the Access Token is not expired before making a request to the server:

public Boolean isAccessTokenExpired(String accessToken){

        String[] accessTokenPart = accessToken.split("\\.");
        String header =accessTokenPart[0];
        String payload =accessTokenPart[1];
        String signature =accessTokenPart[2];
              
        try {

            byte[] decodedPayload = Base64.decode(payload, Base64.DEFAULT);
            payload = new String(decodedPayload,"UTF-8");
        } catch(UnsupportedEncodingException e) {
            e.printStackTrace();
        }


        try {
            JSONObject obj = new JSONObject(payload);
            int expireDate = obj.getInt("exp");
            Timestamp timestampExpireDate= new Timestamp( expireDate);
            long time = System.currentTimeMillis();
            Timestamp timestamp = new Timestamp(time);

            return  timestamp.after(timestampExpireDate);
        
        } catch (JSONException e) {
            e.printStackTrace();
            return true;
        }

    }

And here is the refreshJsonWebToken() method to get a new pair of Access token/Refresh token from my OAUTH2 server:

public void refreshJsonWebToken(){


            SharedPreferences settings = getActivity().getSharedPreferences(PREFS_NAME, 0);
            String refreshToken = settings.getString("refreshToken", null);

            final HashMap params = new HashMap();
            params.put("grant_type","refresh_token");
            params.put("client_id","client");
            params.put("refresh_token",refreshToken);

            JsonObjectRequest req = new JsonObjectRequest(URL_OAUTH2, new JSONObject(params), new Response.Listener() {

                @Override
                public void onResponse(JSONObject response) {

                        try {
                            
                            String newRefreshToken = response.getString("refresh_token");
                            SharedPreferences settings = getActivity().getSharedPreferences(PREFS_NAME, 0);
                            SharedPreferences.Editor editor = settings.edit();
                            editor.putString("accessToken", newAccessToken);
                            editor.putString("refreshToken", newRefreshToken);
                            editor.apply();
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
            }, new Response.ErrorListener() {
               
       
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("grid", "Error: " + error.getMessage());
                    
                    }
                }
            });
                                
            AppController.getInstance().addToRequestQueue(req);
                                
                
    }

And finally the getPost() method where I use the precedent methods:

private void getPost(String latitude, String longitude) {

        SharedPreferences settings = getActivity().getSharedPreferences(PREFS_NAME, 0);
        String accessToken = settings.getString("accessToken", null);
        final HashMap params = new HashMap();
        params.put("action", "getLocalPosts");
        params.put("latitude", latitude);
        params.put("longitude", longitude);

        if (isAccessTokenExpired(accessToken)){
            refreshJsonWebToken();
        }

        settings = getActivity().getSharedPreferences(PREFS_NAME, 0);
        accessToken = settings.getString("accessToken", null);
        JsonObjectRequest req = new JsonObjectRequest(URL_APP+accessToken, new JSONObject(params), new Response.Listener() {

            //Some code ....
        });

        AppController.getInstance().addToRequestQueue(req);

    }
android android-asynctask oauth-2.0 android-volley jwt