使用Java在gRPC中实现OAuth
我正在尝试使用拦截器在gRPC服务器和客户端应用程序之间实现OAuth2,步骤如下:
- 客户端应用程序调用服务器的gRPC方法
- 服务器应用程序以
UNAUTHENTICATED
状态和头中的redirect-url
进行响应 - 客户端获得
redirect-url
,使用它访问授权服务器,最后获得access_token
- 客户端应用程序调用服务器的gRPC方法(这次使用
access_token
)
然而,由于交易已经在第2步结束,因此在一次通话中第4步似乎是不可能的。有没有办法在一次gRPC服务呼叫中完成这4个步骤
这是我的ClientInterceptor课程。我指出了代码中的4个步骤(参见代码注释)
public class OAuthClientInterceptor implements ClientInterceptor {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return new CheckedForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
@Override
public void checkedStart(Listener<RespT> responseListener, Metadata headers) {
if (redirectUrl != null) {
try {
//[Step #3] Obtain the access token
accessToken = obtainAccessToken(redirectUrl);
} catch (ConnectException e) {
throw new StatusRuntimeException(Status.UNAUTHENTICATED.withCause(e));
}
}
if (accessToken != null) {
headers.put(Key.of("Authorization",
Metadata.ASCII_STRING_MARSHALLER), "Bearer " + accessToken);
}
if (recursiveCall) {
//[Step #4] PROBLEM: still results to UNAUTHENTICATED
next.newCall(method, callOptions).start(responseListener, headers);
recursiveCall = false;
return;
}
OAuthResponseListener<RespT> oAuthRespListener = new OAuthResponseListener(responseListener);
oAuthRespListener.setUnauthenticatedListener(trailers->{
//[Step #2] Obtain the redirect-url
redirectUrl = trailers.get(Key.of("redirect-url", Metadata.ASCII_STRING_MARSHALLER));
recursiveCall = true;
//[Step #3 and 4] Invoke the retrieval of access token and the 2nd call to gRPC method
checkedStart(responseListener, headers);
});
//[Step #1] Call the gRPC method
delegate().start(oAuthRespListener, headers);
}
};
}
}
# 1 楼答案
我已经解决了这个问题,但我希望找到一些内置的身份验证机制或对blockingStub函数的多次调用来支持这个oAuth流,但没有找到任何
所以我至少打了两次电话给
blockingStub.invokeServerMethod()
redirect-url
invokeServerMethod
并将access_token
附加到标题李>请注意,我有30个服务器方法,我必须对所有这些方法调用实现相同的步骤。为了尽量减少每个服务器方法的代码重复,我创建了一个
RetryUtil
类,将为每个服务器方法调用该类。以下是我所做的: