Skip to content

Commit 296a711

Browse files
committed
context propagation in ServerInterceptor fixed
1 parent e834089 commit 296a711

File tree

2 files changed

+17
-15
lines changed

2 files changed

+17
-15
lines changed

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ YourService.newStub(aChannel).withCallCredentials(callCredentials);
4848

4949
### Server usage
5050
This ensures that only requests with valid `JWT` in `Authorization` header are processed.
51-
The `fromConfig` method automatically downloads the Keycloak public key before the instance is actually created.
5251
```java
5352
import io.grpc.ServerServiceDefinition;
5453
import com.avast.grpc.jwt.keycloak.server.KeycloakJwtServerInterceptor;
@@ -78,4 +77,4 @@ On other hand, `Context key` is set of values that are available during request
7877

7978
So when implementing interceptors, you must be sure that you read Context values from the right thread. It's actually no issue for us because:
8079
1. The right thread is automatically handled by gRPC-core when using`CallCredentials`. So you can call `applier.apply()` method on any thread.
81-
2. Our `ServerInterceptor` implementation is fully synchronous.
80+
2. Our `ServerInterceptor` implementation handles it correctly.

core/src/main/java/com/avast/grpc/jwt/server/JwtServerInterceptor.java

+16-13
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,26 @@ public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
3737
call.close(Status.UNAUTHENTICATED.withDescription(msg), new Metadata());
3838
return new ServerCall.Listener<ReqT>() {};
3939
}
40-
DelayedServerCallListener<ReqT> delayedListener = new DelayedServerCallListener<ReqT>();
40+
DelayedServerCallListener<ReqT> delayedListener = new DelayedServerCallListener<>();
41+
Context context = Context.current(); // we must call this on the right thread
4142
try {
4243
tokenParser
4344
.parseToValid(authHeader.substring(AUTH_HEADER_PREFIX.length()))
4445
.whenComplete(
45-
(token, e) -> {
46-
if (e == null) {
47-
delayedListener.setDelegate(
48-
Contexts.interceptCall(
49-
Context.current().withValue(AccessTokenContextKey, token),
50-
call,
51-
headers,
52-
next));
53-
} else {
54-
delayedListener.setDelegate(handleException(e, call));
55-
}
56-
});
46+
(token, e) ->
47+
context.run(
48+
() -> {
49+
if (e == null) {
50+
delayedListener.setDelegate(
51+
Contexts.interceptCall(
52+
Context.current().withValue(AccessTokenContextKey, token),
53+
call,
54+
headers,
55+
next));
56+
} else {
57+
delayedListener.setDelegate(handleException(e, call));
58+
}
59+
}));
5760
} catch (Exception e) {
5861
return handleException(e, call);
5962
}

0 commit comments

Comments
 (0)