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] > >
