śr., 1 kwi 2026 o 16:39 Clebert Suconic <[email protected]> napisał(a):
>
> > 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.
>
>
> this makes me feel stronger about letting the connection stay after
> the token expired.
> If you need to remake the connection, then it should at that point
> fail with an invalid password.

if you make a new connection with expired token, you'll get auth
failure (in this AMQP / SASL case - a SASL failure).

But even JMS API itself doesn't include concept of "time-constrained
credentials"), so I believe this is not an easy thing to implement (I
mean proper handling of JWTs).

>
>
>
> From my little experience with security, this short timeout is good to
> make sure I authenticate within the timeout, but it doesn't mean that
> any given resource should be dropped.

Actually I don't think it's about "how much time you have to complete
auth process.
It's about how long you as a client are treated as "authenticated".

>
>
> like.. think you browsing a webpage.. you connect through google...
> you have X seconds to open the page.. but that doesn't mean my page
> should be closed after the authetication token is expired.. the server
> should allow me to stay connected as it was authenticated within the
> initial timeout.. just what I think.

In olden times you had servlet sessions, which were kept alive only
because you were sending JSESSIONID cookie.
When you stop sending it, the session will get expired at the server side.

With messaging protocols it's a bit more problematic - for AMQP you
can't send interleaved SASL frames with a challenge from the server
"please reauthenticate"..

With OAuth2 / OpenID Connection in the browser, you have access tokens
and refresh tokens which should be used to handle this scenario
transparently for the user...

I simply wouldn't even consider "initial timeout", only a concept of
"you're authenticated until ...".

If someone wants to use JWTs and treat them as passwords it's kind of
a bad architecture. Not saying that JWTs are always helpful, but I
think it's a good way to implement this Zero-Trust Architecture.

~Grzegorz Grzybek

>
> On Wed, Apr 1, 2026 at 10:27 AM 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]
> >
>
>
> --
> 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