-
Notifications
You must be signed in to change notification settings - Fork 39
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
Feature Request: Server Side JWT Security Support #164
Comments
Worth adding as a new module |
Sounds like a good idea, want to do a PR? |
Sure, I can take a stab at it. Is it better suited to live in this project or within https://github.com/micronaut-projects/micronaut-security ? |
this project is fine |
@brianwyka did you still want to submit a PR? |
Sorry @graemerocher, totally lost track of this. I can get something going this weekend. |
@graemerocher, I was planning on reusing some of the JWT security configuration and beans from Should I copy code into this new module or call the deprecated code? Here is what my "basic" first take of an implementation looks like: Configuration class: @ConfigurationProperties(GrpcServerSecurityJwtConfiguration.PREFIX)
@Requires(property = GrpcServerSecurityJwtConfiguration.PREFIX + ".enabled", value = "true", defaultValue = "false")
public interface GrpcServerSecurityJwtConfiguration {
String PREFIX = GrpcServerConfiguration.PREFIX + ".security.jwt";
/**
* Whether or not JWT server interceptor is enabled
*
* @return true if enabled, false otherwise
*/
boolean isEnabled();
/**
* The order to be applied to the server interceptor in the interceptor chain
*
* @return the order
*/
int getOrder();
/**
* The name of the metadata key which holds the JWT
*
* @return the metadata key name
*/
String getMetadataKeyName();
} Server Interceptor: @Singleton
@Requires(beans = GrpcServerSecurityJwtConfiguration.class)
public class GrpcServerSecurityJwtInterceptor implements ServerInterceptor, Ordered {
private static final Logger LOG = LoggerFactory.getLogger(GrpcServerSecurityJwtInterceptor.class);
private final int order;
private final Metadata.Key<String> jwtMetadataKey;
private final JwtValidator jwtValidator;
/**
* Create the interceptor based on the configuration.
*
* @param config the gRPC Security JWT configuration
* @param jwtValidator the JWT validator
*/
@Inject
public GrpcServerSecurityJwtInterceptor(final GrpcServerSecurityJwtConfiguration config, final JwtValidator jwtValidator) {
this.order = config.getOrder();
this.jwtMetadataKey = Metadata.Key.of(config.getMetadataKeyName(), Metadata.ASCII_STRING_MARSHALLER);
this.jwtValidator = jwtValidator;
}
/**
* Intercept the call to validate the JSON web token. If the token is not present in the metadata, or
* if the token is not valid, this method will deny the request with a {@link StatusRuntimeException}
*
* @param call the server call
* @param metadata the metadata
* @param next the next processor in the interceptor chain
* @param <T> the type of the server request
* @param <S> the type of the server response
* @throws StatusRuntimeException if token not present or invalid
*/
@Override
public <T, S> ServerCall.Listener<T> interceptCall(final ServerCall<T, S> call, final Metadata metadata, final ServerCallHandler<T, S> next) {
if (!metadata.containsKey(jwtMetadataKey)) {
if (LOG.isErrorEnabled()) {
LOG.error("{} key missing in gRPC metadata", jwtMetadataKey.name());
}
throw new StatusRuntimeException(Status.UNAUTHENTICATED);
}
final ServerCall.Listener<T> listener = next.startCall(call, metadata);
final Optional<JWT> jwtOptional = jwtValidator.validate(metadata.get(jwtMetadataKey));
if (!jwtOptional.isPresent()) {
throw Status.PERMISSION_DENIED.withDescription("JWT validation failed").asRuntimeException();
}
if (LOG.isDebugEnabled()) {
LOG.debug("JWT: {}", jwtOptional.get().serialize());
}
return new ForwardingServerCallListener.SimpleForwardingServerCallListener<T>(listener) { };
}
/**
* Get the order for this interceptor within the interceptor chain
*
* @return the order
*/
@Override
public int getOrder() {
return order;
}
} |
@jameskleeh @sdelamo can you provide some suggestions with regards to integrating security with gRPC here? |
@jameskleeh, @sdelamo, any feedback? |
@brianwyka As you have discovered many of the APIs in security are tied to the notion of an HttpRequest. If the same sort of practices for normal http services also apply to GRPC then perhaps I would consider creating a |
any news? we are in need of this functionality. |
Thanks for the feedback @jameskleeh, I'll see if I can make that work, otherwise will resort to some duplication if necessary. |
@jameskleeh, based on some brief analysis, doesn't look like a I noticed that Or can I leverage calling that with a I'm thinking that perhaps an enhancement can be made to If we want to make it more useful for other security purposes outside of |
That isn't temporary. We want to allow for validation of JWTs outside of a request. You can pass null there. Some of the cases where the request is available are because users requested access to it, not because the framework itself needed the data |
Thanks @jameskleeh, that will work for this use case. |
#322 has been opened to support JWT server-side security |
I believe that a pretty crucial part is missing here for this to be on par with the "HTTP security" module: token propagation. Ideally, it should be possible to configure HTTP → gRPC, gRPC → HTTP and gRPC → gRPC token propagation. |
@pfyod that would be useful |
Do we have news about this feature? 👀 |
@brunorafaeli, still waiting on feedback on some design direction from Micronaut team. |
Any update on it would be great |
@FrogDevelopper I'll be looking at this later this week |
Hello, happy new year for all the team 🎉 🍾 Hoping you'll get time for this feature soon🤞🏻 |
@burtbeckwith |
@burtbeckwith any update? |
Any update on the issue? |
Still no update on this issue ? |
Allow for integration with
micronaut-security
to provide server interceptors to enforce different types of authenticationBase use case would be
micronaut-security-jwt
to be used for validating JWT tokens. Example below:The text was updated successfully, but these errors were encountered: