xor*_*ate 10 android rx-java retrofit okhttp auth0
我正在使用Auth0,它给了我一个JWT(json web令牌)和一个refreshtoken.我在http标头中使用此JWT与我的后端进行通信.
403当它确定JWT已经过期时,它可能会发生,服务器给我一个.在这种情况下,我可以让Auth0使用refreshtoken向我发出一个新的JWT.这意味着我调用Auth0后端,将它传递给refreshtoken,它给了我一个新的JWT,然后我可以在我的请求中使用它.
我的问题是,如何在我的所有网络代码中有效地编写此行为?我将有几个端点可以交谈,他们都可以返回403.
我想我应该首先制作一个拦截器,将JWT添加到所有请求中.
然后应该有检测403的行为,静静地对Auth0进行网络调用,检索新的JWT.然后应该再次尝试原始请求,并在其标题中添加新的JWT.
所以我更希望将403处理到我的其他代码看不到的地方,并且绝对不必在任何地方重写它.
任何关于如何实现这一点的指示将不胜感激.
-
要清楚,我基本上是在寻找如何使用RxAndroid Observables实现这一目标的指针.当某个Observable找到403时,它应该"注入"一个新的网络呼叫.
xor*_*ate 17
我写了一个Interceptorfor 来解决这个问题OkHttp.它检查网络呼叫的状态代码.如果是403,请调用Auth0服务器并请求新的id_token.然后在原始请求的新版本中使用此令牌.
为了测试,我编写了一个小的Web服务器来检查TestHeader是否失败或成功,如果失败则返回403 .
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我将这个Interceptor附加到一个OkHttpClient,我将其插入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();
}
}
)
Run Code Online (Sandbox Code Playgroud)