Skip to content
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

Need a way to set http headers from Java Client API #767

Closed
tdiepenbrock opened this issue Jul 7, 2017 · 5 comments
Closed

Need a way to set http headers from Java Client API #767

tdiepenbrock opened this issue Jul 7, 2017 · 5 comments

Comments

@tdiepenbrock
Copy link

tdiepenbrock commented Jul 7, 2017

Related to issue #766.

In the short term, we need a way to set generic HTTP headers via the Java Client API. This is important because many of our customers are using enterprise SSO systems where user credential information is returned via HTTP headers. The username and any groups/roles are returned in specific headers for different categories of roles, so we need to be able to transmit this information to the server to use in application-level authentication.

Also this is important if we are using 2-way SSL for authentication. In the "old days" of J2EE, particularly Weblogic, servers that were behind a load balancer needed to authenticate the user via client certificate. The issue was that the load balancer would handle the initial SSL negotiation, so the certificate information was lost. The solution was to write a script for the load balancer to take the public certificate from the initial request and place it into headers where the Weblogic authenticators expected to find them, and then send the request to the server via plain HTTP. The authenticators would find the user certificate information they needed in the headers and authenticate the user. We could use exactly the same mechanism in MarkLogic if we had a generic HTTP header capability. This would be a huge benefit to our government customers, who tend to rely very heavily on 2-way SSL authentication.

Besides authentication, we could use HTTP headers to specify information that might be used by custom transforms—maybe a redaction method for the redaction API, for example, etc via a header. There are lots of uses for this sort of thing.

As for timing, my thinking is that this would be needed per-request. If the server is asking to set cookies, perhaps the Transaction class might be the place. There may be the need to override headers that the Client API may set itself--I'm not sure of all the headers the API sets (likely other customers won't either). But, when the situation arises where API is doing something (like setting a header) that breaks your application, we should provide a way for skilled developers to alter that behavior.

@sammefford
Copy link
Contributor

sammefford commented Jul 7, 2017

@tdiepenbrock I'm curious how committed you are to this solution or if we might be able to explore different ways to properly address these use cases. In general, the Java Client API strives to expose straight-forward functionality while abstracting away the implementation. Of course no abstraction is perfect, and we'll have to make exceptions. However, with HTTP/2 fast gaining traction, we're reminded that even widely-accepted foundations like HTTP can be shaken. So the more we tie ourselves to our current HTTP implementation, the more we'll struggle to change that implementation without deprecating important parts of the API.

Additionally, we're currently replacing our core HTTP library, Jersey, with OkHttp. This process has made it clear that we exposed too much HTTP functionality as not everything implemented in Jersey (which builds on HttpClient) is available via OkHttp. Therefore, to make this transition properly we're wrestling with how much implementation and QA burden to take on for work like SSL cert parsing which is not even core to our business.

For the specific scenario of SSL Client Cert auth, I have a few concerns:

  1. The Java Client API talks to REST endpoints which do not offer you access to the headers you may pass to them
  2. We added SSL Client Cert auth in 4.0.1 (docs coming soon). Though that's obviously different because the client is the Java application and the server is MarkLogic.
  3. The scenario you present is one in which the client is a web client and the server is a Java app server, and a load balancer is in front of the app server. That part doesn't involve the Java Client API which comes in later, when the Java application is ready to send database requests to the backend. If a load balancer interacts with Java Client API, it is between the application and MarkLogic. So I can't see how adding header support to the Java Client API would help in such a scenario.

@sammefford
Copy link
Contributor

sammefford commented Jul 7, 2017

In the short term, we need a way to set generic HTTP headers via the Java Client API. This is important because many of our customers are using enterprise SSO systems where user credential information is returned via HTTP headers. The username and any groups/roles are returned in specific headers for different categories of roles, so we need to be able to transmit this information to the server to use in application-level authentication.

Sorry, I didn't address this part. This makes sense, since I'm familiar with your current approach. Would you recommend that other clients take your current approach? I'm thinking we might want to seek a more accessible path for broad adoption. Specifically, it makes sense that we need a solution for "application-level authentication" #766 and that solution needs to allow you a way to transmit any groups/roles and potentially other app-specific information as part of the auth request. Does that sound right?

@tdiepenbrock
Copy link
Author

tdiepenbrock commented Jul 7, 2017 via email

@sammefford
Copy link
Contributor

One small clarification: replacing Jersey doesn't complicate things from a design standpoint. It's just a use case to teach about the perils of exposing too much tied to the underlying implementation. The specific case is that we exposed DatabaseClientFactory.SSLHostnameVerifier.ANY, COMMON, and STRICT (based on org.apache.http.conn.ssl.*HostnameVerifier). The loose docs we had for them left them more or less tied to the vague semantics of the Apache HttpClient implementation. While they are useful in theory, they introduce a challenge as we move off Apache HttpClient.

In this case of this RFE, the generic underlying implementation under discussion is HTTP. While that's not likely to change, we're wary of treating the Java Client API as an HTTP pass-thru, especially when the target are our supported REST endpoints. We need to be thoughtful about whether to expose something like this. So far we haven't needed to do it to achieve our goals.

@sammefford
Copy link
Contributor

I believe the pressing need for this has gone away. Please re-open if I'm wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants