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

Allow for injecting authentication mechanisms #840

Closed
Nevon opened this issue Aug 16, 2020 · 1 comment · Fixed by #1372
Closed

Allow for injecting authentication mechanisms #840

Nevon opened this issue Aug 16, 2020 · 1 comment · Fixed by #1372

Comments

@Nevon
Copy link
Collaborator

Nevon commented Aug 16, 2020

Is your feature request related to a problem? Please describe.
Currently there is no way for a developer to add support for SASL GSSAPI (Kerberos) without bundling that into KafkaJS itself. We would likely not want to do that, as that particular case requires a native module.

I should note that while I think this change makes sense, and I have definitely seen people asking for Kerberos authentication (#609 & #213), I don't have this use-case myself, so unless someone is willing to sponsor the work, consider this more of a roadmap ticket.

Describe the solution you'd like
Similar to how we allow users to add compression codecs, we should expose the list of supported mechanisms and allow users to add their implementations:

const {  SaslMechanisms, SaslAuthenticators } = require('kafkajs')

// Adding support for new mechanism
const GssapiAuthenticator = require('kafkajs-gssapi')
SaslAuthenticators["GSSAPI"] = GssapiAuthenticator

// Overriding built-in authenticator for supported mechanism
const OauthbearerAuthenticator = require('custom-kafkajs-oauthbearer')
SaslAuthenticators[SaslMechanisms.OAUTHBEARER] = OauthbearerAuthenticator

One challenge I see is that the interface for the authenticator is not entirely fit for external usage at the moment. Essentially, an authenticator looks something like this today:

interface AuthenticatorInterface {
    authenticate(): Promise<void>;
}

interface AuthenticatorConstructor {
  new (connection: Connection, logger: Logger, saslAuthenticate: SaslAuthenticationFunction): AuthenticatorInterface;
}

interface Encoder {
    buffer: Buffer
}

interface Request {
    encode(): Promise<Encoder>
}

interface Response {
    decode(data: Buffer): Promise<Buffer>
    parse(data: Buffer): Promise<any> 
}

interface SaslAuthenticationFunctionParams {
    request: Request,
    response: Response,
    authExpectResponse?: boolean
}

type SaslAuthenticationFunction = (params: SaslAuthenticationFunctionParams) => Promise<void>;

AuthenticatorConstructor is where we expose KafkaJS internals. Specifically:

  • Logger - This one is fine. This is already available and has a public interface.
  • Connection - This is worse. This is very much not a public interface.

From what I can see from existing authenticators, we are really only providing the Connection to them because they need a subset of the following information:

  • Broker host and port. From what I can see this is only for logging.
  • sasl username and password. This is obviously needed for the authenticator.

The authenticator does not actually need the connection itself, because the only request it has to make to the broker is done via SaslAuthenticationFunction where it's safely encapsulated. We could just provide the sasl and broker information.

I'm also not entirely sure about the parameter and return types of Request and Response. I think I saw different authenticators return Promise<Encoder|Buffer> for Request.encode() and Promise<Encoder|Buffer|boolean> for Response.decode and Response.parse, so there's probably some cleaning up to do there. If we make it public, it should only accept and return buffers, rather than Encoders.

@Nevon
Copy link
Collaborator Author

Nevon commented Jul 7, 2022

This is now available in 2.2.0-beta.0. Documentation for the feature is available here.

Please try it out and report back with your results and experiences.

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