Re: [DISCUSS] Generic SASL mechanism extension model for James protocols
Benoit TELLIER <[email protected]> Mon, 22 Jun 2026 10:16:53 +0000
| Newsgroups | gmane.comp.jakarta.james.devel |
|---|---|
| Message-ID | <[email protected]> |
---=Part.595.6aa5647b1a752c3e.19eeed5419e.eefae479d3e859ed=-
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Accept-Language: fr-FR, en-US, vi-VN, ru-RU, ar-TN, it-IT, de-DE
Content-Language: en-US
Hello Quan
Here are my thoughts=2E
I think AuthHook encompasses two thing=
s:
=C2=A0- A bad implementation of SASL (no advertized capability) which i=
s Ok dropping=2E
We could potentially even propose a SaslAuthHookAdapter t=
hat plugs in the SASL flow and delegates to the given AuthHook thus easing =
migration?
It would then be mostly conf to adapt ones axtension=2E=2E=2E
=
=C2=A0- Decorate login eg to push a notif somewhere=2E=C2=A0
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:
=C2=A0- Deprecate=
=C2=A0AuthHook
=C2=A0- Introduce a=C2=A0SaslAuthHookAdapter that one can ex=
tend to record existing AuthHook=2E The=C2=A0SaslAuthHookAdapter should be =
flexible enough to allow override the PLAIN mechanism=2E
=C2=A0- Have a new=
hook:=C2=A0SaslAuthResultHook
=C2=A0- Write an upgrade-instructions regard=
ing this=2E
Would this make sense ?--=C2=A0
Best regards,
Benoit TELLIE=
R
General manager of Linagora VIETNAM=2E
Product owner for Twake-Mail prod=
uct=2E
Chairman of the Apache James project=2E
Mail: btellier@linagora=2Ec=
om
Tel: (0033) 6 77 26 04 58 (WhatsApp, Signal)
On Jun 22, 2026 12:08 PM=
, from Quan Tran Hong <quan=2Etranhong1999@gmail=2Ecom>Hello folks,
Follow=
ing the Generic SASL modularization and adoption for IMAP at
github=2Ecom/a=
pache/james-project/pull/3059, I am working further on
the adoption for SMT=
P (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=2E
Reg=
arding SMTP adoption, I am not sure if we should drop the `AuthHook`
interf=
ace (and its extension capability)=2E
*If we drop `AuthHook` for SMTP*, th=
en we would rely purely on the SASL
layer for the authentication logic, whi=
ch should reduce the code
complexity=2E However, community `AuthHook` exten=
sion implementors would then
need to be rewritten under a custom `SaslMecha=
nism` implementation instead=2E
Example of what we proposed for IMAP custom=
SASL:
github=2Ecom/apache/james-project/pull/3059/changes/3f0a554e4c3b3914=
daecbd41b75a6aa21ae9c8cf
=2E
Also, please note that it may not be straightf=
orward to just replace
`AuthHook` with the `SaslMechanism` extension: AuthH=
ook can extend the
*PLAIN* auth capability, while SaslMechanism would likel=
y be distinct by
the mechanism name (PLAIN) and only override is possible=
=2E
*If we keep `AuthHook` for SMTP,* we would mix the legacy `AuthHook` c=
ode
and the modular SASL layer for SMTP authentication, which may introduce=
extra complexity for SMTP authentication=2E Also, having 2 mechanisms to
c=
onfigure authentication for SMTP (`AuthHook` and `SaslMechanism`) feels
odd=
=2E However, keeping the `AuthHook` would be less invasive for community
ex=
tension usage, if any=2E
I am not sure about the `AuthHook` extension usag=
e in our community, and
the best way to go for SMTP adoption here=2E Maybe =
I would go the defensive
way to try to keep the `AuthHook` mechanism, to av=
oid invasion=2E Or do you
think the code complexity and the limited adoptio=
n of `AuthHook` are not
worth keeping?
Feedback and opinion are very welco=
me!
Quan
On Wed, Jun 3, 2026 at 12:30=E2=80=AFPM Benoit TELLIER <btellie=
r@linagora=2Ecom>
wrote:
> This looks really reasonable to me=2E
> Other m=
ail servers achieve sasl code mutualisation and expose it as
> extension=2E=
> 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 mo=
re
> descriptive approach leads us to!
> --
>
>
> Best regards,
>
> Benoit =
TELLIER
>
> General manager of Linagora VIETNAM=2E
> Product owner for Twak=
e-Mail product=2E
> Chairman of the Apache James project=2E
>
> Mail: btell=
ier@linagora=2Ecom
> Tel: (0033) 6 77 26 04 58 (WhatsApp, Signal)
>
>
>
> O=
n Jun 3, 2026 5:22 AM, from Quan Tran Hong <quan=2Etranhong1999@gmail=2Ecom=
>Hi
> all,
>
> I would like to propose a generic SASL mechanism extension m=
odel for James
> protocols=2E
>
> Today, when adding a new authentication m=
echanism for IMAP or SMTP, we need
> to modify core protocol code, such as =
IMAP *AuthenticateProcessor* or SMTP
> *AuthCmdHandler*=2E This makes the p=
rotocol handlers accumulate
> mechanism-specific branches, and would make f=
uture mechanisms such as
> GSSAPI / Kerberos harder to add cleanly=2E
>
> T=
he 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 se=
mantics and exchange state;
> - existing IMAP/SMTP behavior should remain =
unchanged when no new
> configuration is provided=2E
>
> This takes inspira=
tion from JMAP authentication strategies configuration
> and Guice loading=
=2E
>
>
> *Configuration shape*
> -------------------
>
> Each protocol wou=
ld keep an operator-visible *auth=2EsaslMechanisms* list=2E
>
> Example for=
IMAP:
>
>
>
> * <auth>
>
> <saslMechanisms>PlainSaslMechanism,OauthBear=
erSaslMechanism,XOauth2SaslMechanism,com=2Eexample=2Ejames=2Ekerberos=2EGss=
apiSaslMechanism</saslMechanisms>
> </auth>*
>
> Example for SMTP:
>
>
>
=
> * <auth>
>
> <saslMechanisms>LoginSaslMechanism,PlainSaslMechanism,Oau=
thBearerSaslMechanism,XOauth2SaslMechanism,com=2Eexample=2Ejames=2Ekerberos=
=2EGssapiSaslMechanism</saslMechanisms>
> </auth>*
>
> Expected semantics=
:
>
> - if *auth=2EsaslMechanisms* is absent, load current protocol defaul=
ts;
> - IMAP defaults remain PLAIN, OAUTHBEARER, XOAUTH2;
> - SMTP defaul=
ts remain LOGIN, PLAIN, OAUTHBEARER, XOAUTH2;
> - if configured, load the =
configured list in the configured order;
> - simple class names resolve ag=
ainst James default SASL packages;
> - fully qualified class names allow e=
xternal/community extensions;
>
> Existing protocol settings still decide a=
vailability=2E For example, plain
> auth restrictions still decide whether =
PLAIN is advertised, OIDC
> configuration still decides whether OAuth mecha=
nisms are advertised, and
> SMTP *auth=2Eannounce* still controls whether S=
MTP advertises AUTH=2E
>
>
> *Proposed SPI shape*
> ------------------
>
> =
I propose introducing protocol-neutral SASL types in *protocols/api*, for
>=
example under *org=2Eapache=2Ejames=2Eprotocols=2Eapi=2Esasl*=2E
>
> The c=
ore idea is a stateful SaslExchange: each SASL mechanism creates one
> exch=
ange per authentication attempt, and that exchange owns mechanism state
> a=
cross the initial request and continuation responses=2E
>
> Core structure:=
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
=
>
>
> * interface SaslMechanism { String name(); boolean
>=
supports(SaslProtocol protocol); boolean
> isAvailable(SaslSessionC=
ontext context); SaslExchange
> start(SaslInitialRequest request, Sa=
slSessionContext context); } enum
> SaslProtocol { IMAP, SMTP,=
MANAGESIEVE, POP3 } record
> SaslInitialRequest(SaslProtocol protoco=
l, String mechanismName,
> Optional<byte[]> initialResponse) { } reco=
rd 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[]
> clientR=
esponse); void abort(); @Override void
> close(); }=
interface SaslStep { record
> Challenge(Optional<byte[]> payload=
) implements SaslStep { }
> record Success(SaslIdentity identity, Op=
tional<byte[]> serverData, String
> log) implements SaslStep { } =
record Failure(String log)
> implements SaslStep { } }*
>
> T=
he intended split is:
>
> - SASL mechanisms own payload parsing, challenge=
generation, response
> validation, final SASL identity extraction, and exc=
hange state=2E
> - IMAP/SMTP bridges own base64/wire framing, continuation=
responses,
> success/failure session side effects, audit logs, hooks, and
=
> protocol-specific error responses=2E
>
> For example, PLAIN and OAUTHBEAR=
ER can complete from *firstStep()*, while
> GSSAPI can return Challenge fir=
st and complete later from
> *onResponse(=2E=2E=2E)*=2E
>
> SaslIdentity ca=
rries both the authentication identity and the authorization
> identity=2E =
This keeps delegation expressible by the SPI without granting it
> automati=
cally=2E IMAP/SMTP bridges still decide whether delegation is allowed
> and=
how to build their protocol session state=2E
>
>
> *Loading and registry*
=
> --------------------
>
> Mechanism loading would follow the same spirit a=
s JMAP authentication
> strategies:
>
>
>
>
>
>
>
>
>
>
>
>
>
> * interf=
ace SaslMechanismLoader { ImmutableList<SaslMechanism>
> load(Collec=
tion<String> classNames); } class SaslMechanismRegistry {
> Opt=
ional<SaslMechanism> find(String mechanismName, SaslProtocol
> protocol) { =
// match by mechanism name and supports(protocol)
> } =
Stream<SaslMechanism> availableFor(SaslProtocol protocol,
> SaslSessionCon=
text context) { // filter supports(protocol) and
> isAvailable(c=
ontext) } }*
>
> Then implement a GuiceSaslMechanismLoader to act=
ually load the SASL
> mechanisms=2E
>
>
> *Incremental implementation plan*=
> -------------------------------
>
> I suggest doing this step by step:
>=
> - *Step 1*: Start with a POC introducing the shared SaslMechanism SPI an=
d
> adapting IMAP=2E
> This must not introduce breaking changes to existi=
ng authentication
> configs=2E The SASL SPI can be adopted gradually, proto=
col by protocol,
> without changing behavior for protocols that have not ad=
opted it yet=2E
> - *Step 2*: Adapt SASL modularization for SMTP=2E
> - *St=
ep 3*: Leverage the SASL modularization to implement GSSAPI / Kerberos
> me=
chanism support=2E
>
> ManageSieve and POP3 are not part of the immediate s=
cope, but the SPI
> should make later adoption possible=2E
>
> *Testing exp=
ectations*
> --------------------
>
> At minimum, I think we should prove:
=
>
> - no breaking change: absent auth=2EsaslMechanisms keeps existing IMAP=
/SMTP
> SASL methods;
> - configured custom SASL mechanism loads and authe=
nticates 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 wor=
ks for continuation;
> - exchange cleanup is covered=2E
>
> *Feedback requ=
ested*
> ------------------
>
> Does this refactoring direction look reason=
able to you? Feedback and
> discussion are welcome!
> Meanwhile, I would st=
art POC work on my side to see how this design goes=2E=2E=2E
>
> Regards,
>=
Quan
>
>
---=Part.595.6aa5647b1a752c3e.19eeed5419e.eefae479d3e859ed=---