Skip to content

Conversation

@raccoonback
Copy link
Contributor

@raccoonback raccoonback commented Jun 23, 2025

Summary

Add flexible HTTP authentication framework to HttpClient with support for custom authentication mechanisms including SPNEGO/Negotiate, OAuth, Bearer tokens, and Basic authentication.

Changes

httpAuthentication - For immediate credential computation

HttpClient.httpAuthentication(
                               BiPredicate<HttpClientRequest, HttpClientResponse> retryPredicate,
                               BiConsumer<HttpClientRequest, SocketAddress> authenticator)

HttpClient.httpAuthentication(
                               BiPredicate<HttpClientRequest, HttpClientResponse> retryPredicate,
                               BiConsumer<HttpClientRequest, SocketAddress> authenticator,
                               int maxRetries)

httpAuthenticationWhen - For deferred credential retrieval

HttpClient.httpAuthenticationWhen(
                                 BiPredicate<HttpClientRequest, HttpClientResponse> retryPredicate,
                                 BiFunction<HttpClientRequest, SocketAddress, Mono<Void>> authenticator)

HttpClient.httpAuthenticationWhen(
                                 BiPredicate<HttpClientRequest, HttpClientResponse> retryPredicate,
                                 BiFunction<HttpClientRequest, SocketAddress, Mono<Void>> authenticator,
                                 int maxRetries)

Key Features

  • Flexible authentication framework: Support for any HTTP-based authentication flow
  • Configurable retry mechanism: Custom predicate to determine when to retry authentication
  • Configurable max retries: Set maximum authentication retry attempts (default: 1)
  • Retry tracking: authenticationRetryCount() method in HttpClientInfos to track retry attempts
  • Exception handling: New HttpClientAuthenticationException for authentication failures

Authentication Flow

  1. Initial request sent to protected resource
  2. Server responds with authentication challenge (e.g., 401 Unauthorized)
  3. Retry predicate evaluates response to determine if authentication is needed
  4. Authenticator adds credentials to request headers
  5. Request retried with authentication credentials
  6. Process repeats up to maxRetries if authentication continues to fail

Related Issue

Fixes #3079

@raccoonback
Copy link
Contributor Author

I tested Kerberos authentication using the krb5 available at https://formulae.brew.sh/formula/krb5.

@raccoonback raccoonback force-pushed the issue-3079 branch 5 times, most recently from 19ccf13 to 090e1c2 Compare June 26, 2025 06:49
@raccoonback raccoonback changed the title Support SPNEGO (Kerberos) Authentication in HttpClient Support SPNEGO Authentication in HttpClient Jun 27, 2025
@raccoonback raccoonback force-pushed the issue-3079 branch 3 times, most recently from a6efd89 to 96aa2ba Compare July 1, 2025 08:57
@raccoonback raccoonback force-pushed the issue-3079 branch 2 times, most recently from 8fcac3f to a77c0a5 Compare July 5, 2025 03:43
@raccoonback
Copy link
Contributor Author

@violetagg
Hello!
Please check this PR when you have a chance. 😃

@wendigo
Copy link

wendigo commented Jul 23, 2025

This is so great! Looking forward to get this in :)

@wendigo
Copy link

wendigo commented Jul 23, 2025

I can provide some guidance around APIs and configuration. Not every kerberos-enabled client uses JAAS, therefore the direct Subject/SPNEGO token support should be provided

@raccoonback
Copy link
Contributor Author

@wendigo
Hello!
Thank you for the great point. 😀

I was thinking of allowing users to implement the SpnegoAuthenticator interface, similar to JaasAuthenticator, to support custom authentication logic if needed.

If I understood you correctly, you're suggesting that we should provide a way for users to directly supply a Subject, as in the example below:

public class DirectSubjectAuthenticator implements SpnegoAuthenticator {

    // ...
    private Subject subject;

    @Override
    public Subject login() throws LoginException {
        return subject;
    }

    // ...
}

Would you be able to share a more concrete example or use case?
It would help refine the design in the right direction.

@wendigo
Copy link

wendigo commented Jul 24, 2025

Sure @raccoonback.

I'd like to use reactor-netty in the trino CLI/JDBC/client libraries.

We support delegated/constrained/unconstrained kerberos authentication. Relevant code is here:

https://github.com/trinodb/trino/tree/master/client/trino-client/src/main/java/io/trino/client/auth/kerberos

This is how we add it to the okhttp: https://github.com/trinodb/trino/blob/master/client/trino-client/src/main/java/io/trino/client/auth/kerberos/SpnegoHandler.java

Configurability is important as we expose configuration that allows the user to pass remote service name, service principal name, whether to canonicalize hostname: https://github.com/trinodb/trino/blob/master/client/trino-client/src/main/java/io/trino/client/auth/kerberos/SpnegoHandler.java#L50C5-L54C48

@raccoonback
Copy link
Contributor Author

@violetagg
I think supporting not only JAAS-based authentication but also allowing the user to provide a GSSCredential directly could improve configurability and flexibility.
This would be especially useful in environments where JAAS is not preferred or where credentials need to be managed programmatically.
What do you think about this direction?

cc. @wendigo

@violetagg
Copy link
Member

violetagg commented Jul 28, 2025 via email

@raccoonback
Copy link
Contributor Author

@wendigo
I've added GSSCredential-based SPNEGO authentication and support for service name and canonical hostname configuration.
Thank you for the suggestion.

@raccoonback raccoonback force-pushed the issue-3079 branch 2 times, most recently from 685924c to b082661 Compare July 30, 2025 23:39
@raccoonback
Copy link
Contributor Author

@violetagg
Hello.
I would appreciate it if you could review this PR.
Thanks!

@violetagg
Copy link
Member

@violetagg Hello. I would appreciate it if you could review this PR. Thanks!

I'm just returning fro vacation, will check it in the next days or so

@raccoonback
Copy link
Contributor Author

@violetagg
Hello.
I would appreciate it if you could review this PR.
Thanks!

@violetagg
Copy link
Member

I will check this one ... just need to finalise some other tasks.

Signed-off-by: raccoonback <kosb15@naver.com>
@raccoonback
Copy link
Contributor Author

@violetagg
I’ve applied all the review comments.
Please take another look. 🙂

Signed-off-by: raccoonback <kosb15@naver.com>
This change updates the httpAuthentication() method to require both a retry predicate and an authenticator, allowing users to customize when authentication retry should occur.

Signed-off-by: raccoonback <kosb15@naver.com>
Signed-off-by: raccoonback <kosb15@naver.com>
Signed-off-by: raccoonback <kosb15@naver.com>
Signed-off-by: raccoonback <kosb15@naver.com>
Signed-off-by: raccoonback <kosb15@naver.com>
@raccoonback
Copy link
Contributor Author

@violetagg
I’ve applied all the review comments!
Please take another look.

Signed-off-by: raccoonback <kosb15@naver.com>
@raccoonback
Copy link
Contributor Author

@violetagg
Hello.
I'd appreciate it if you could review this PR.

Copy link
Member

@violetagg violetagg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's also expose the number of authentication retries similar to reactor.netty.http.client.HttpClientInfos#redirectedFrom, it might be helpful when users need to decide whether want to continue the retry or not. What do you think?

Move retry limit check from HttpClientHandler to HttpClientOperations to ensure the response is delivered to the user when authentication retries are exhausted, rather than failing the entire request.

Signed-off-by: raccoonback <kosb15@naver.com>
@raccoonback
Copy link
Contributor Author

Let's also expose the number of authentication retries similar to reactor.netty.http.client.HttpClientInfos#redirectedFrom, it might be helpful when users need to decide whether want to continue the retry or not. What do you think?

@violetagg
That’s an excellent suggestion. I’ll go ahead and add it.

Signed-off-by: raccoonback <kosb15@naver.com>
…latile update

Signed-off-by: raccoonback <kosb15@naver.com>
…rd compatible

Signed-off-by: raccoonback <kosb15@naver.com>
@raccoonback raccoonback requested a review from violetagg December 1, 2025 14:25
@raccoonback
Copy link
Contributor Author

raccoonback commented Dec 1, 2025

@violetagg
Hello.
I've reflect it.
Please check this PR!

The AtomicInteger overhead is unnecessary for this use case.
Added @SuppressWarnings annotation to suppress the non-atomic operation warning.

Signed-off-by: raccoonback <kosb15@naver.com>
@raccoonback raccoonback requested a review from violetagg December 2, 2025 04:15
Document the authenticationRetryCount() method in the HTTP Authentication section,
including usage examples and best practices for tracking authentication retry attempts.

Signed-off-by: raccoonback <kosb15@naver.com>
@raccoonback
Copy link
Contributor Author

@violetagg
Hello.
I've reflect it.
Please check this PR. 😀😃

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support For Spnego Auth scheme support for netty HttpClient similar to Apache's

3 participants