Hello Benoit, Thanks for your suggestions! That sounds reasonable to me.
I will attempt to apply the suggestions for SMTP. Regards, Quan On Mon, Jun 22, 2026 at 5:17 PM Benoit TELLIER <[email protected]> wrote: > Hello Quan > > Here are my thoughts. > > I think AuthHook encompasses two things: > > - A bad implementation of SASL (no advertized capability) which is Ok > dropping. > > We could potentially even propose a SaslAuthHookAdapter that plugs in the > SASL flow and delegates to the given AuthHook thus easing migration? > It would then be mostly conf to adapt ones axtension... > > - Decorate login eg to push a notif somewhere. > > Maybe we culd have a new hook (SaslAuthResultHook ?) for being able to > decorate this and allow adding side effect effectively? > > > So I'd go with: > - Deprecate AuthHook > - Introduce a SaslAuthHookAdapter that one can extend to record existing > AuthHook. The SaslAuthHookAdapter should be flexible enough to allow > override the PLAIN mechanism. > - Have a new hook: SaslAuthResultHook > - Write an upgrade-instructions regarding this. > > Would this make sense ?-- > > > Best regards, > > Benoit TELLIER > > General manager of Linagora VIETNAM. > Product owner for Twake-Mail product. > Chairman of the Apache James project. > > Mail: [email protected] > Tel: (0033) 6 77 26 04 58 (WhatsApp, Signal) > > > > On Jun 22, 2026 12:08 PM, from Quan Tran Hong > <[email protected]>Hello > folks, > > Following the Generic SASL modularization and adoption for IMAP at > github.com/apache/james-project/pull/3059, I am working further on > the adoption for SMTP (based on the IMAP PR) to see how it goes, before we > can decide if it is good to merge the IMAP PR and go forward with this SASL > refactoring. > > Regarding SMTP adoption, I am not sure if we should drop the `AuthHook` > interface (and its extension capability). > > *If we drop `AuthHook` for SMTP*, then we would rely purely on the SASL > layer for the authentication logic, which should reduce the code > complexity. However, community `AuthHook` extension implementors would then > need to be rewritten under a custom `SaslMechanism` implementation instead. > Example of what we proposed for IMAP custom SASL: > > github.com/apache/james-project/pull/3059/changes/3f0a554e4c3b3914daecbd41b75a6aa21ae9c8cf > . > Also, please note that it may not be straightforward to just replace > `AuthHook` with the `SaslMechanism` extension: AuthHook can extend the > *PLAIN* auth capability, while SaslMechanism would likely be distinct by > the mechanism name (PLAIN) and only override is possible. > > *If we keep `AuthHook` for SMTP,* we would mix the legacy `AuthHook` code > and the modular SASL layer for SMTP authentication, which may introduce > extra complexity for SMTP authentication. Also, having 2 mechanisms to > configure authentication for SMTP (`AuthHook` and `SaslMechanism`) feels > odd. However, keeping the `AuthHook` would be less invasive for community > extension usage, if any. > > I am not sure about the `AuthHook` extension usage in our community, and > the best way to go for SMTP adoption here. Maybe I would go the defensive > way to try to keep the `AuthHook` mechanism, to avoid invasion. Or do you > think the code complexity and the limited adoption of `AuthHook` are not > worth keeping? > > Feedback and opinion are very welcome! > > Quan > > > On Wed, Jun 3, 2026 at 12:30 PM Benoit TELLIER <[email protected]> > wrote: > > > This looks really reasonable to me. > > Other mail servers achieve sasl code mutualisation and expose it as > > extension. > > I'd have naturaly bundled the side effects behind the sasl API to mimic > > current authentication code but I am actually curious to see where the > more > > descriptive approach leads us to! > > -- > > > > > > Best regards, > > > > Benoit TELLIER > > > > General manager of Linagora VIETNAM. > > Product owner for Twake-Mail product. > > Chairman of the Apache James project. > > > > Mail: [email protected] > > Tel: (0033) 6 77 26 04 58 (WhatsApp, Signal) > > > > > > > > On Jun 3, 2026 5:22 AM, from Quan Tran Hong <[email protected] > >Hi > > all, > > > > I would like to propose a generic SASL mechanism extension model for > James > > protocols. > > > > Today, when adding a new authentication mechanism for IMAP or SMTP, we > need > > to modify core protocol code, such as IMAP *AuthenticateProcessor* or > SMTP > > *AuthCmdHandler*. This makes the protocol handlers accumulate > > mechanism-specific branches, and would make future mechanisms such as > > GSSAPI / Kerberos harder to add cleanly. > > > > The goal is: > > > > - adding a new SASL mechanism should not require modifying core > IMAP/SMTP > > command handlers; > > - protocol code should keep protocol framing and side effects; > > - SASL mechanism code should own mechanism semantics and exchange state; > > - existing IMAP/SMTP behavior should remain unchanged when no new > > configuration is provided. > > > > This takes inspiration from JMAP authentication strategies configuration > > and Guice loading. > > > > > > *Configuration shape* > > ------------------- > > > > Each protocol would keep an operator-visible *auth.saslMechanisms* list. > > > > Example for IMAP: > > > > > > > > * <auth> > > > > > <saslMechanisms>PlainSaslMechanism,OauthBearerSaslMechanism,XOauth2SaslMechanism,com.example.james.kerberos.GssapiSaslMechanism</saslMechanisms> > > </auth>* > > > > Example for SMTP: > > > > > > > > * <auth> > > > > > <saslMechanisms>LoginSaslMechanism,PlainSaslMechanism,OauthBearerSaslMechanism,XOauth2SaslMechanism,com.example.james.kerberos.GssapiSaslMechanism</saslMechanisms> > > </auth>* > > > > Expected semantics: > > > > - if *auth.saslMechanisms* is absent, load current protocol defaults; > > - IMAP defaults remain PLAIN, OAUTHBEARER, XOAUTH2; > > - SMTP defaults remain LOGIN, PLAIN, OAUTHBEARER, XOAUTH2; > > - if configured, load the configured list in the configured order; > > - simple class names resolve against James default SASL packages; > > - fully qualified class names allow external/community extensions; > > > > Existing protocol settings still decide availability. For example, plain > > auth restrictions still decide whether PLAIN is advertised, OIDC > > configuration still decides whether OAuth mechanisms are advertised, and > > SMTP *auth.announce* still controls whether SMTP advertises AUTH. > > > > > > *Proposed SPI shape* > > ------------------ > > > > I propose introducing protocol-neutral SASL types in *protocols/api*, for > > example under *org.apache.james.protocols.api.sasl*. > > > > The core idea is a stateful SaslExchange: each SASL mechanism creates one > > exchange per authentication attempt, and that exchange owns mechanism > state > > across the initial request and continuation responses. > > > > Core structure: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > * interface SaslMechanism { String name(); boolean > > supports(SaslProtocol protocol); boolean > > isAvailable(SaslSessionContext context); SaslExchange > > start(SaslInitialRequest request, SaslSessionContext context); } > enum > > SaslProtocol { IMAP, SMTP, MANAGESIEVE, POP3 } record > > SaslInitialRequest(SaslProtocol protocol, String mechanismName, > > Optional<byte[]> initialResponse) { } record SaslIdentity(Username > > authenticationId, Username authorizationId) { } interface > > SaslSessionContext { SaslProtocol protocol(); boolean > > isTlsStarted(); <T> Optional<T> configuration(Class<T> > > configurationType); } interface SaslExchange extends AutoCloseable > { > > SaslStep firstStep(); SaslStep onResponse(byte[] > > clientResponse); void abort(); @Override void > > close(); } interface SaslStep { record > > Challenge(Optional<byte[]> payload) implements SaslStep { } > > record Success(SaslIdentity identity, Optional<byte[]> serverData, String > > log) implements SaslStep { } record Failure(String log) > > implements SaslStep { } }* > > > > The intended split is: > > > > - SASL mechanisms own payload parsing, challenge generation, response > > validation, final SASL identity extraction, and exchange state. > > - IMAP/SMTP bridges own base64/wire framing, continuation responses, > > success/failure session side effects, audit logs, hooks, and > > protocol-specific error responses. > > > > For example, PLAIN and OAUTHBEARER can complete from *firstStep()*, while > > GSSAPI can return Challenge first and complete later from > > *onResponse(...)*. > > > > SaslIdentity carries both the authentication identity and the > authorization > > identity. This keeps delegation expressible by the SPI without granting > it > > automatically. IMAP/SMTP bridges still decide whether delegation is > allowed > > and how to build their protocol session state. > > > > > > *Loading and registry* > > -------------------- > > > > Mechanism loading would follow the same spirit as JMAP authentication > > strategies: > > > > > > > > > > > > > > > > > > > > > > > > > > > > * interface SaslMechanismLoader { ImmutableList<SaslMechanism> > > load(Collection<String> classNames); } class SaslMechanismRegistry > { > > Optional<SaslMechanism> find(String mechanismName, SaslProtocol > > protocol) { // match by mechanism name and supports(protocol) > > } Stream<SaslMechanism> availableFor(SaslProtocol protocol, > > SaslSessionContext context) { // filter supports(protocol) and > > isAvailable(context) } }* > > > > Then implement a GuiceSaslMechanismLoader to actually load the SASL > > mechanisms. > > > > > > *Incremental implementation plan* > > ------------------------------- > > > > I suggest doing this step by step: > > > > - *Step 1*: Start with a POC introducing the shared SaslMechanism SPI and > > adapting IMAP. > > This must not introduce breaking changes to existing authentication > > configs. The SASL SPI can be adopted gradually, protocol by protocol, > > without changing behavior for protocols that have not adopted it yet. > > - *Step 2*: Adapt SASL modularization for SMTP. > > - *Step 3*: Leverage the SASL modularization to implement GSSAPI / > Kerberos > > mechanism support. > > > > ManageSieve and POP3 are not part of the immediate scope, but the SPI > > should make later adoption possible. > > > > *Testing expectations* > > -------------------- > > > > At minimum, I think we should prove: > > > > - no breaking change: absent auth.saslMechanisms keeps existing > IMAP/SMTP > > SASL methods; > > - configured custom SASL mechanism loads and authenticates through real > or > > near-real protocol wiring; > > - authentication / authorization identity handling preserves existing > > delegation behavior (we should already have tests for these); > > - fake multi-step mechanism works for continuation; > > - exchange cleanup is covered. > > > > *Feedback requested* > > ------------------ > > > > Does this refactoring direction look reasonable to you? Feedback and > > discussion are welcome! > > Meanwhile, I would start POC work on my side to see how this design > goes... > > > > Regards, > > Quan > > > > >
