Android - Retrofit 2 - Authenticator Result

前端 未结 3 771
时光说笑
时光说笑 2020-12-29 15:46

I\'m trying to use Retrofit (2.0.0-beta3), but when using an Authenticator to add a token, I can\'t seem to get the data from the synchronous call. Our logging on the back-e

3条回答
  •  無奈伤痛
    2020-12-29 16:16

    I know it's a late answer but for anyone still wondering how to Add / Refresh token with Retrofit 2 Authenticator, here is a working solution:

    Note: preferenceHelper is your Preference Manager class where you set/get your shared preferences.

    public class AuthenticationHelper implements Authenticator {
    
        private static final String HEADER_AUTHORIZATION = "Authorization";
        private static final int REFRESH_TOKEN_FAIL = 403;
    
        private Context context;
    
        AuthenticationHelper(@ApplicationContext Context context) {
            this.context = context;
        }
    
        @Override
        public Request authenticate(@NonNull Route route, @NonNull Response response) throws IOException {
            // We need to have a token in order to refresh it.
            String token = preferencesHelper.getAccessToken();
            if (token == null)
                return null;
    
            synchronized (this) {
                String newToken = preferencesHelper.getAccessToken();
                if (newToken == null)
                    return null;
    
                // Check if the request made was previously made as an authenticated request.
                if (response.request().header(HEADER_AUTHORIZATION) != null) {
    
                    // If the token has changed since the request was made, use the new token.
                    if (!newToken.equals(token)) {
                        return response.request()
                                .newBuilder()
                                .removeHeader(HEADER_AUTHORIZATION)
                                .addHeader(HEADER_AUTHORIZATION, "Bearer " + newToken)
                                .build();
                    }
    
                    JsonObject refreshObject = new JsonObject();
                    refreshObject.addProperty("refreshToken", preferencesHelper.getRefreshToken());
    
                    retrofit2.Response tokenResponse = apiService.refreshToken(refreshObject).execute();
    
                    if (tokenResponse.isSuccessful()) {
    
                        UserToken userToken = tokenResponse.body();
                        if (userToken == null)
                            return null;
    
                        preferencesHelper.saveAccessToken(userToken.getToken());
                        preferencesHelper.saveRefreshToken(userToken.getRefreshToken());
    
    
                        // Retry the request with the new token.
                        return response.request()
                                .newBuilder()
                                .removeHeader(HEADER_AUTHORIZATION)
                                .addHeader(HEADER_AUTHORIZATION, "Bearer " + userToken.getToken())
                                .build();
                    } else {
                        if (tokenResponse.code() == REFRESH_TOKEN_FAIL) {
                            logoutUser();
                        }
                    }
                }
            }
            return null;
        }
    
        private void logoutUser() {
            // logout user
        }
    }
    

    Also note:

    1. preferenceHelper and apiService needs to be provided in some way.
    2. This is not an example that will work for all systems and api's but an example in how adding and refreshing the token should be done using Retrofit 2 Authenticator

提交回复
热议问题