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
