-
Notifications
You must be signed in to change notification settings - Fork 434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Security implementation broken #157
Comments
Thanks for your investigation. The implementation is not broken, but obtaining the current user in authenticated call might be, via SecurityContextHolder. It will be replaced with GRPC Context native API. |
It is broken. Once you try to implement it via Please refer to the official repo for an example of contextual data inside an interceptor: public static <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
Context context,
ServerCall<ReqT, RespT> call,
Metadata headers,
ServerCallHandler<ReqT, RespT> next) {
Context previous = context.attach();
try {
return new ContextualizedServerCallListener<>(
next.startCall(call, headers),
context);
} finally {
context.detach(previous);
}
} https://github.com/grpc/grpc-java/blob/master/api/src/main/java/io/grpc/Contexts.java#L72-L80 @Override
public void onMessage(ReqT message) {
Context previous = context.attach();
try {
super.onMessage(message);
} finally {
context.detach(previous);
}
} As you can see the context is cleared after the method call and reattached and cleared for the nested calls. |
This is what I meant - Authentication will be passed via managed context |
I'm not sure whether i got you right or whether you got me right. |
I'm not sure if I have configured it correctly, but now with the implementation resolving this issue, the security context is cleared after returning the listener.
|
|
Thank you for the quick response. public class AuthenticationInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
return new SimpleForwardingServerCallListener<ReqT>(next.startCall(call, headers)) {
@Override
public void onHalfClose() {
try {
SecurityContextHolder.getContext().setAuthentication((Authentication)GrpcSecurity.AUTHENTICATION_CONTEXT_KEY.get());
super.onHalfClose();
} finally {
SecurityContextHolder.clearContext();
}
}
};
}
} Just for me to understand, but why wasn't something like this implemented in the |
Which security features you are talking about further down in your services? |
We currently use |
Sure, I'll try to accomplish this once I'm back from vacation( ~ end of July) |
If the |
I have created #233 as a possible implementation. |
The security implementation (#155) as released in v4.0.0 is vulnerable to concurrency issues.
Do NOT use that feature.
(Originally posted in #155 (comment) . I moved it here for better visibility)
Proof
Here a JUnit test that can be used to verify the issue (Click to expand)
You will encounter the following errors in the test:
This error is caused by another call that completed and thus the security being cleared before this call was processed.
However, it is also possible that if two authenticated calls were to happen at the same time to gain the authentication of the other call/user.
Note
Due to the structure of this library's interceptor you cannot (not sure) bypass authentication, but can still obtain a different users authentication (or loose your own as shown in the above stacktrace). Especially for streaming calls.
EDIT: You can also bypass security annotations (in non-streaming calls only) if the server uses them instead of the
GrpcSecurityConfigurerAdapter
(Not tested, but it's the same as the above error).See also
The text was updated successfully, but these errors were encountered: