How to handle auth0 403 error without adding specific code everywhere (Retrofit/okhttp/RxAndroid)

后端 未结 2 1600
野趣味
野趣味 2021-01-02 02:05

I am using Auth0, which gives me a JWT (json web token) and a refreshtoken. I use this JWT in the http headers to communicate with my backend.

It could happen, that

相关标签:
2条回答
  • 2021-01-02 02:37

    I solved this issue by writing an Interceptor for OkHttp. It checks the statuscode of the network call. If it's a 403, call Auth0 servers and request a new id_token. Then use this token in a new version of the original request.

    To test, I wrote a little webserver that checks the TestHeader for fail or succeed and returns a 403 if it's fail.

    public class AuthenticationInterceptor implements Interceptor {
    
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();
            Request authenticationRequest = originalRequest.newBuilder()
                    .header("TestHeader", "fail")
                    .build();
    
            Response origResponse = chain.proceed(authenticationRequest);
    
            // server should give us a 403, since the header contains 'fail'
            if (origResponse.code() == 403) {
                String refreshToken = "abcd"; // you got this from Auth0 when logging in
    
                // start a new synchronous network call to Auth0
                String newIdToken = fetchNewIdTokenFromAuth0(refreshToken);
    
                // make a new request with the new id token
                Request newAuthenticationRequest = originalRequest.newBuilder()
                        .header("TestHeader", "succeed")
                        .build();
    
                // try again
                Response newResponse = chain.proceed(newAuthenticationRequest);
    
                // hopefully we now have a status of 200
                return newResponse;
            } else {
                return origResponse;
            }
        }
    }
    

    Then I attach this Interceptor to an OkHttpClient which I plug into the Retrofit adapter:

    // add the interceptor to an OkHttpClient
    
    public static OkHttpClient getAuthenticatingHttpClient() {
        if (sAuthenticatingHttpClient == null) {
            sAuthenticatingHttpClient = new OkHttpClient();
            sAuthenticatingHttpClient.interceptors().add(new AuthenticationInterceptor());
        }
        return sAuthenticatingHttpClient;
    }
    
    // use the OkHttpClient in a Retrofit adapter
    
    mTestRestAdapter = new RestAdapter.Builder()
        .setClient(new OkClient(Network.getAuthenticatingHttpClient()))
        .setEndpoint("http://ip_of_server:port")
        .setLogLevel(RestAdapter.LogLevel.FULL)
        .build();
    
    // call the Retrofit method on buttonclick
    
    ViewObservable.clicks(testNetworkButton)
        .map(new Func1<OnClickEvent, Object>() {
                 @Override
                 public Object call(OnClickEvent onClickEvent) {
                     return mTestRestAdapter.fetchTestResponse();
                 }
             }
        )
    
    0 讨论(0)
  • 2021-01-02 02:59

    Instead of refreshing tokens only after receiving a 403 response, you could check the expiration time locally and refresh accordingly by checking the token's exp claim. For example, this example uses the same approach in Angular. It's not specific to Android, but the idea is the same:

    jwtInterceptorProvider.tokenGetter = function(store, jwtHelper, auth) {
      var idToken = store.get('token');
      var refreshToken = store.get('refreshToken');
      if (!idToken || !refreshToken) {
        return null;
      }
      // If token has expired, refresh it and return the new token
      if (jwtHelper.isTokenExpired(idToken)) {
        return auth.refreshIdToken(refreshToken).then(function(idToken) {
          store.set('token', idToken);
          return idToken;
        });
      // If not expired, return the token directly
      } else {
        return idToken;
      }
    }
    
    0 讨论(0)
提交回复
热议问题