Я пытаюсь реализовать OAuth2 между моим сервером gRPC и клиентскими приложениями, используя перехватчики, с помощью следующих шагов:
- клиентское приложение вызывает метод gRPC сервера
- серверное приложение отвечает с
UNAUTHENTICATED
статусом и redirect-url
в заголовках
- клиент получает
redirect-url
, использует его для доступа к серверу авторизации и, наконец, получает access_token
- клиентское приложение вызывает метод gRPC сервера (на этот раз с
access_token
)
Однако шаг № 4 кажется невозможным всего за один вызов, поскольку транзакция уже закрыта на шаге № 2. Есть ли способ выполнить эти 4 шага всего за один вызов службы gRPC?
Вот мой класс 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);
}
};
}
}