it fits with a Zero Trust Architecture (ZTA), the core philosophy is
"never trust, always verify."
Token expiry is vital. It ensures that "trust" is never a permanent state,
but rather a temporary grant that must be constantly re-validated.
forcing a connection close to force a reconnect and validation is a
necessary step towards that.

On Wed, 1 Apr 2026 at 15:27, Grzegorz Grzybek <[email protected]> wrote:

> śr., 1 kwi 2026 o 15:13 Clebert Suconic <[email protected]>
> napisał(a):
> >
> > @Grzegorz I wonder if the right thing to do is to close a connection
> > after a timeout on the token.
> >
> > shouldn't you just use the token within its creation timeout? (For
> > example, if you connect after the given timeout, the connection
> > shouldn't be allowed, but after created you leave it alive)
> >
> > But is closing the connection after a timeout the right thing to do?
> > Is this a standard used in other systems?
>
> I've created https://issues.apache.org/jira/browse/ARTEMIS-5983 with
> more details.
>
> So first - you may configure your token issuer (like Keycloak) to have
> longer-living tokens.
> Initially I was thinking about the client side of things and how a
> connection pool or
> product-related JMS ConnectionFactory could handle expiring
> credentials (tokens).
>
> qpid-jms has something called PASSWORD_OVERRIDE, where you effective
> pass a BiFunction that
> returns a String (password) which may be used to obtain tokens (using
> JDK HTTP Client for
> example).
>
> But then, I realized that the usual scenario (like with camel-jms) is
> to configure your connection
> pool (pooled-jms) with fixed credentials and then, transactionally get
> a connection, send/receive
> a message and close it, where "close" == "return to the pool without
> real close". So there's no
> nice way to have "expiring connections" here.
>
> But then looking from the Artemis side, when a connection is authenticated
> with JWT there SHOULD be a way to enforce the connection close based
> on the token validity
>  - whether or not the client will re-establish the connection.
>
> I have no good solution for messaging systems. OAuth2 (and OpenID
> Connection which adds some
> _extensions_) is very generic and there are no strict rules of how it
> should be used.
>
> From the broker perspective it's just a "credential" but with few
> "attributes" that could
> be used for the connection being authenticated.
>
> We could continue this under
> https://issues.apache.org/jira/browse/ARTEMIS-5983
>
> regards
> Grzegorz Grzybek
> >
> >
> > Creating a connection is "expensive," and having users constantly
> > connecting and disconnecting wouldn't scale well in a messaging
> > system.
> >
> > On Mon, Mar 30, 2026 at 8:27 AM Grzegorz Grzybek <[email protected]>
> wrote:
> > >
> > > pon., 30 mar 2026 o 11:07 Gary Tully <[email protected]>
> napisał(a):
> > > >
> > > > Maybe the expiry plugin could communicate via the authenticated
> subject?
> > > > Track the fields from private cred, rather then context parameters?
> > > >
> > > > That would be a nice feature I think
> > >
> > > As a proof of concept, I've:
> > >  - configured keycloak to give me tokens valid for 10 seconds
> > >  - changed org.apache.qpid.jms.example.HelloWorld to get a token
> > > and send a message every 1 second for 15 seconds
> > >  - changed
> org.apache.activemq.artemis.protocol.amqp.proton.AMQPConnectionContext#validateUser()
> > > to get the JWT token from
> > > connectionCallback.getProtonConnectionDelegate().getSubject() and
> > > schedule
> > > a connection close into broker's scheduler
> > >
> > > In server logs I got this (for PoC):
> > >
> > > 2026-03-30 14:16:12,172 DEBUG [OIDCLoginModule] JAAS login successful
> > > for JWT token with jti=trrtcc:23e984ba-cdf2-6247-686a-205e3dec8491,
> > > aud=[externally-managed-broker,account]
> > > 2026-03-30 14:16:12,174 DEBUG [OIDCLoginModule] Found identities:
> > > a6ba4a84-c2de-4982-97f4-86d13de0c1e6
> > > 2026-03-30 14:16:12,174 DEBUG [OIDCLoginModule] Found roles:
> > > offline_access, uma_authorization, default-roles-artemis, openid,
> > > profile, email, artemis-2.47.2
> > > 2026-03-30 14:16:12,191 INFO  [AMQPConnectionContext] Scheduling
> > > connection close in 8 seconds
> > > 2026-03-30 14:16:21,001 INFO  [AMQPConnectionContext] Closing the
> > > connection for token trrtcc:23e984ba-cdf2-6247-686a-205e3dec8491
> > >
> > > and at the client side I got
> > >
> org.apache.qpid.jms.provider.exceptions.ProviderConnectionRemotelyClosedException
> > > wrapped in org.apache.qpid.jms.JmsConnectionRemotelyClosedException
> > > via jakarta.jms.ExceptionListener
> > >
> > > That's the minimal, but sufficient result I wanted to achieve...
> > >
> > > ~Grzegorz Grzybek
> > >
> > > >
> > > >
> > > >
> > > >
> > > > On Mon, Mar 30, 2026, 09:09 Grzegorz Grzybek <[email protected]>
> wrote:
> > > >
> > > > > Hello
> > > > >
> > > > > pt., 27 mar 2026 o 11:25 Gary Tully <[email protected]>
> napisał(a):
> > > > > >
> > > > > > this is all great work.
> > > > > > one note, for expiry service side, one solution, quite blunt but
> > > > > effective
> > > > > > is to configure the expiry plugin on an acceptor and force
> reconnect on
> > > > > the
> > > > > > same schedual as tokens.
> > > > > > see: https://issues.apache.org/jira/browse/ARTEMIS-4709
> > > > >
> > > > > Just checked ConnectionPeriodicExpiryPlugin. Over the weekend
> > > > > I was thinking about this and took the suggestions from Tim Bish.
> Here's
> > > > > what I think would be least intrusive:
> > > > >  - pooled-jms - no changes needed at all
> > > > >  - qpid-jms - provide _examples_ where
> > > > > o.a.qpid.jms.JmsConnectionExtensions#PASSWORD_OVERRIDE
> > > > >  is a JWT retrieval
> > > > >  - Artemis itself - implement a plugin similar to
> > > > > ConnectionPeriodicExpiryPlugin, which would expire the
> > > > > connections based on `exp` claim from JWT - this "valid until"
> field
> > > > > could be added to
> > > > >
> org.apache.activemq.artemis.protocol.amqp.proton.AMQPConnectionContext, as
> > > > > it
> > > > > already contains username/password/validatedUser - it could contain
> > > > > one additional timestamp field
> > > > >
> > > > > would this be acceptable path?
> > > > >
> > > > > kind regards
> > > > > Grzegorz Grzybek
> > > > >
> > > > > >
> > > > > > On Fri, 27 Mar 2026 at 10:16, Grzegorz Grzybek <
> [email protected]>
> > > > > wrote:
> > > > > >
> > > > > > > Hello
> > > > > > >
> > > > > > > First time writing, so a quick introduction - for many years I
> was
> > > > > working
> > > > > > > (among others) on Hawtio console (since it was based on
> Angular.js
> > > > > 1.2) and
> > > > > > > after I implemented its OIDC Login module and after it was
> used in
> > > > > Artemis
> > > > > > > Console I was more and more involved with Artemis.
> > > > > > >
> > > > > > > 1. == Bringing Hawtio's OIDC Login module to Artemis
> > > > > > >
> > > > > > > in Hawtio, the JAAS LoginModule implementation depends on few
> Hawtio
> > > > > > > classes and the configuration is in special
> hawtio-oidc.properties (as
> > > > > we
> > > > > > > need browser-related configuration there as well).
> > > > > > > For Artemis, I've implemented the login module fully
> configurable using
> > > > > > > etc/login.config
> > > > > > >
> > > > > > > 2. == Artemis OIDC LoginModule features
> > > > > > >
> > > > > > > ARTEMIS-5200 is implemented and PR is green
> > > > > > > https://github.com/apache/artemis/pull/6304 and here's a
> quick list of
> > > > > > > features:
> > > > > > >  - handling signed JWT tokens using one library -
> > > > > > > com.nimbusds:nimbus-jose-jwt
> > > > > > >  - handling claim verification (mandatory claims, expiration,
> required
> > > > > > > audience)
> > > > > > >  - caching public keys from OIDC Provider key endpoints (EC
> and RSA, no
> > > > > > > Hmac support)
> > > > > > >  - configurable token "paths" to retrieve user "identities"
> (like
> > > > > "sub" or
> > > > > > > "preferred_username") and "roles" (like "realm_access.roles"
> from
> > > > > Keycloak)
> > > > > > >  - cnf/x5t#256 certificate "proof of possession" from RFC 8705
> > > > > > >
> > > > > > > I've also added quite extensive test suite.
> > > > > > >
> > > > > > > Note: ActiveMQ "classic" has similar feature:
> > > > > > > https://github.com/apache/activemq/issues/1737 but with less
> flexible
> > > > > > > configuration.
> > > > > > >
> > > > > > > 3. == Passing JWT in messaging protocols
> > > > > > >
> > > > > > > AMQP has SASL frames (but limited to 512 bytes in spec - has
> to be
> > > > > > > explicitly configured to support larger "initial frames")
> where a
> > > > > token can
> > > > > > > be passed and there are two SASL mechanisms dedicated for this:
> > > > > > >  - XOAUTH2 - marked as OBSOLETE at
> > > > > > >
> https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml
> > > > > ,
> > > > > > > originated from gmail, but supported
> > > > > > > by org.apache.qpid.jms.sasl.XOauth2MechanismFactory
> > > > > > >  - OAUTHBEARER - RFC 7628, handled by Kafka for example, but
> not used
> > > > > in
> > > > > > > qpid-jms or proton-j2
> > > > > > >
> > > > > > > I've added XOAUTH2 and OAUTHBEARER as implementations
> > > > > > > of org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL
> and
> > > > > checked
> > > > > > > some simple qpid-jms example which gets a token and sends as
> JMS
> > > > > password.
> > > > > > >
> > > > > > > MQTT mentions (5.x: "4.12 Enhanced authentication"):
> > > > > > > > While these fields are named for a simple password
> authentication,
> > > > > they
> > > > > > > can be used to carry other forms of authentication such as
> passing a
> > > > > token
> > > > > > > as the Password.
> > > > > > > but I didn't touch MQTT yet
> > > > > > >
> > > > > > > 4. == Now the high-level aspect of "JWT Authentication"
> > > > > > >
> > > > > > > I don't think there's anything to do at JMS API side - I
> assume that
> > > > > > > "username" and "password" arguments to
> > > > > > > `jakarta.jms.ConnectionFactory#createConnection()` needs to
> bend to
> > > > > > > password=token interpretation.
> > > > > > >
> > > > > > > But things get interesting in two places and related to short
> (whether
> > > > > 5
> > > > > > > minutes or few days) validity of JWT tokens) - and I didn't
> implement
> > > > > > > anything final:
> > > > > > >
> > > > > > > 4.1. === JMS Connection pool handling at client side
> > > > > > >
> > > > > > > When creating a connection pool with underlying factory
> > > > > > > (like org.apache.qpid.jms.JmsConnectionFactory which has
> "passowrd
> > > > > override
> > > > > > > extension") the pooled object (JMS Connection) should be
> "associated"
> > > > > with
> > > > > > > the JWT token (its credentials).
> > > > > > > commons-pool2 (used in pooled-jms) should be configured to
> > > > > > > set
> org.messaginghub.pooled.jms.pool.PooledConnection#hasExpired when
> > > > > the
> > > > > > > related token has expired.
> > > > > > > I'm just experimenting on that.
> > > > > > >
> > > > > > > 4.2. === AMQP connection expiration at server side
> > > > > > >
> > > > > > > Even if the client-side pool can expire connections, there
> should be a
> > > > > > > server side expiration too
> > > > > > > (org.apache.qpid.proton.amqp.messaging.TerminusExpiryPolicy?)
> I still
> > > > > don't
> > > > > > > know how to approach this and I'd appreciate any comments.
> > > > > > >
> > > > > > > 5. == Summary
> > > > > > >
> > > > > > > I keep working on ARTEMIS-5200, but please check if I'm not
> going too
> > > > > far
> > > > > > > with that.
> > > > > > >
> > > > > > > kind regards
> > > > > > > Grzegorz Grzybek
> > > > > > >
> > > > >
> > > > >
> ---------------------------------------------------------------------
> > > > > To unsubscribe, e-mail: [email protected]
> > > > > For additional commands, e-mail: [email protected]
> > > > >
> > > > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: [email protected]
> > > For additional commands, e-mail: [email protected]
> > >
> >
> >
> > --
> > Clebert Suconic
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [email protected]
> > For additional commands, e-mail: [email protected]
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>

Reply via email to