Cómo manejar el error auth0 403 sin agregar código específico en todas partes (Retrofit / okhttp / RxAndroid)

Estoy utilizando Auth0, que me da un JWT (json web token) y un refreshtoken. Yo uso este JWT en los encabezados http para comunicarse con mi backend.

Podría suceder, que el servidor me da un 403 , cuando se decide que el JWT ha expirado. En este caso, puedo pedir a Auth0 que me emita un nuevo JWT, usando el refreshtoken. Significa que llamo al backend de Auth0, lo paso el refreshtoken, y me da un nuevo JWT, que puedo utilizar entonces en mis peticiones.

Mi pregunta es, ¿cómo puedo escribir eficientemente este comportamiento en todo mi código de red? Tendré un par de puntos finales para hablar, y todos ellos podrían devolver el 403.

Estoy pensando que primero debería hacer un interceptor que añade el JWT a todas las solicitudes.

Entonces debe haber un comportamiento que detecta el 403, silenciosamente hace una llamada de red a Auth0, recuperando el nuevo JWT. Entonces la petición original debe ser intentada otra vez, con el nuevo JWT en sus cabeceras.

Así que prefiero tener este 403 manipulación en algún lugar invisible a mi otro código, y definitivamente no tiene que volver a escribir en todas partes.

Cualquier sugerencia sobre cómo lograr esto será apreciada.

Para ser claro, estoy básicamente buscando punteros sobre cómo lograr esto utilizando RxAndroid Observables. Cuando un determinado Observable encuentra el 403, debe 'inyectar' una nueva llamada de red.

OkHttp este problema escribiendo un Interceptor para OkHttp . Comprueba el statuscode de la llamada de red. Si es un 403, llame a los servidores Auth0 y solicite una nueva id_token. A continuación, utilice este token en una nueva versión de la solicitud original.

Para probar, escribí un pequeño servidor web que comprueba el TestHeader para fallar o tener éxito y devuelve un 403 si falla .

 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; } } } 

A continuación, adjunto este Interceptor a un OkHttpClient que enchufar en el adaptador de Retrofit:

 // 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(); } } ) 

En lugar de refrescar fichas sólo después de recibir una respuesta 403, puede comprobar el tiempo de caducidad localmente y actualizar en consecuencia al comprobar la reclamación exp del token. Por ejemplo, este ejemplo utiliza el mismo enfoque en Angular . No es específico de Android, pero la idea es la misma:

 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; } } 
  • ¿Cómo actualizar observable en RxJava?
  • RxAndroid: cambios de interfaz de usuario en el subproceso Schedulers.io ()
  • Cómo hacer que flatMap se ejecute en un subproceso de fondo
  • Retrofit con Rxjava Schedulers.newThread () vs Schedulers.io ()
  • RxJava: ¿Cómo reanudar el trabajo de un observable si se produce un cambio de configuración?
  • Cómo amortiguar solamente la última emisión de rx.Observable durante contrapresión
  • Robolectric Test no llama a textWatcher.onTextChanged
  • convertir a lambda de rx java expresión
  • Acceso al dominio desde un subproceso incorrecto Excepción mientras se envió una copia usando copyFromRealm
  • Suscribir un cajón de navegación a un Observable
  • RxJava y datos almacenados en caché
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.