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