Hello, We have been putting together an ADR on this topic. https://github.com/apache/james-project/pull/778
We have been finding this simple library allowing to easily get the public key out of a JWKS endpoint: https://github.com/auth0/jwks-rsa-java Using it would enable a dynamic management of OIDC public signing keys for IMAP and SMTP. We would replace in the configuration static public keys by the jwks endpoint. As such the xmls would become: [imapserver.xml] ---- <imapserver enabled="true"> <jmxName>imapserver-ssl</jmxName> <bind>0.0.0.0:993</bind> <tls socketTLS="true" startTLS="false"> <privateKey>file://conf/private.key</privateKey> <certificates>file://conf/certs.self-signed.csr</certificates> </tls> <!-- ... --> <authentication> <plainAuthEnabled>true|false</plainAuthEnabled> <!-- defaults to true --> <oauth> <!-- ommiting this block would disable oauth. All fields are compulsory --> <jwksURL>https://example.com/jwks</jwksURL> <oidcConfigurationURL>https://example.com/.well-known/openid-config</oidcConfigurationURL> <claim>mailAddress</claim> </oauth> </authentication> </imapserver> ---- [smtpserver.xml] ---- <smtpserver enabled="true"> <jmxName>smtpserver-ssl</jmxName> <bind>0.0.0.0:465</bind> <tls socketTLS="true" startTLS="false"> <privateKey>file://conf/private.key</privateKey> <certificates>file://conf/certs.self-signed.csr</certificates> </tls> <!--- ... --> <requireAuthForRelay>true|false</requireAuthForRelay> <authentication> <plainAuthEnabled>true|false</plainAuthEnabled> <!-- defaults to true --> <oauth> <!-- ommiting this block would disable oauth. All fields are compulsory --> <jwksURL>https://example.com/jwks</jwksURL> <oidcConfigurationURL>https://example.com/.well-known/openid-config</oidcConfigurationURL> <claim>mailAddress</claim> </oauth> </authentication> </smtpserver> ---- Cheers, Benoit On 02/12/2021 11:56, btell...@linagora.com wrote: > Hopefully rendered correctly in plain text... > > ----------------------------------------- > > Hello Jamers! > > As part of my work at Linagora, we are looking toward > - better integrating James within our product suite and for us this > means support "Single Sign On" and "Single Log Out" for JMAP following > the OpenId connect standard [0]. > - Improving security standards used to opperate James. (We have a > growing activity within the health care market, sensible to security > arguments) > > Regarding security standards we should ideally: > - Be able to NOT advertise AUTH / LOGIN capabilities of unencrypted > channels (Correspond to IMAP plainAuthDissallowed but generalized to > other protocols) > - Be able to require OAUTH/OIDC authentication for all protocols (IMAP, > SMTP, JMAP) - this is what some of the health care providers we spoke to > desired to do. > - For our collaborative suite usage, while OIDC only for JMAP makes > sense, we still wish to maintain PLAIN AUTH for IMAP and SMTP. > - Of course settings for regular users not interested in OIDC should > not change (no breaking changes, OIDC adoption is opt-in only). > > As such we propose ourselves to: > - Contribute IMAP and SMTP SASL OAUTH extension described in [RFC-7628] > - Modularize JMAP authentication mechanisms (letting the admin choose > which one she wishes to use) > - Enable authentication through a header mechanism eg `X-USER: > btell...@apache.org`, which can be used to delegate OIDC authentication > through a third party API gateway. We have Krackend [1] in mind. > - Share documentation and a docker-compose of OIDC setup for IMAP, SMTP > and JMAP in > https://github.com/apache/james-project/tree/master/examples/oidc. This > would include: > - A LDAP still used by James UsersRepository. Provisionned with a > testing user. > - A pre-configured Keycloack [2] OpenID connect provider. > - A pre-configured Krakend API gateway proxying JMAP > - And finally a James server configured to only accept OIDC as an > authentication mechanism for IMAP, SMTP and JMAP. > - Unit tests for existing IMAP `plainAuthDissallowed` configuration > parameter. > > Finally this is a good opportunity to restructure authentication related > settings in imapserver.xml and smtpserver.xml file. > > Here are proposals for both files: > > [imapserver.xml] > ---- > <imapserver enabled="true"> > <jmxName>imapserver-ssl</jmxName> > <bind>0.0.0.0:993</bind> > <tls socketTLS="true" startTLS="false"> > <privateKey>file://conf/private.key</privateKey> > <certificates>file://conf/certs.self-signed.csr</certificates> > </tls> > <!-- ... --> > <authentication> > <plainAuthEnabled>true|false</plainAuthEnabled> <!-- > defaults to true --> > <oauth> <!-- ommiting this block would disable oauth. All > fields are compulsory --> > <publicKey>file://conf/imapJWT.pub</publicKey> > > <oidcConfigurationURL>https://example.com/.well-known/openid-config</oidcConfigurationURL> > <claim>mailAddress</claim> > </oauth> > </authentication> > </imapserver> > ---- > > [smtpserver.xml] > ---- > <smtpserver enabled="true"> > <jmxName>smtpserver-ssl</jmxName> > <bind>0.0.0.0:465</bind> > <tls socketTLS="true" startTLS="false"> > <privateKey>file://conf/private.key</privateKey> > <certificates>file://conf/certs.self-signed.csr</certificates> > </tls> > <!--- ... --> > <requireAuthForRelay>true|false</requireAuthForRelay> > <authentication> > <plainAuthEnabled>true|false</plainAuthEnabled> <!-- > defaults to true --> > <oauth> <!-- ommiting this block would disable oauth. All > fields are compulsory --> > <publicKey>file://conf/imapJWT.pub</publicKey> > > <oidcConfigurationURL>https://example.com/.well-known/openid-config</oidcConfigurationURL> > <claim>mailAddress</claim> > </oauth> > </authentication> > </smtpserver> > ---- > > You can see that: > - The `plainAuthDissallowed` parameter is proposed to be renamed to > `auth.requireSSL`. (of course we should support fallback NOT to have a > breaking change) > - `auth.plainAuthEnabled` enable turning on/off plain auth, which > allows having OIDC only mechanism. > - `auth.requireSSL` will be generalized to SMTP. > - In SMTP `requireAuth` setting is very misleading as it rather is > `requireAuthForRelay`. I propose we rename this configuration option (of > course we should support fallback NOT to have a breaking change). > > Here is the implementation strategies we would follow: > > - For JMAP have Krakend doing all the hard job for us, and use a > dedicated header to carry the information over to James. > - Our code contributions aims at easing such a setup (that would only > require configuration) > - Provide an informative example using krakend. We understand that > this choice is ours, yet sharing it could allow reuse or similar setup > - If some people wishes to write an OIDC authentication strategy > directly in James then they perfectly can! (Reusing the modularization > of JMAP authentication strategies we would provide). > > - For IMAP and SMTP then we proposes to check the bearer payload > against a statically configured public key for these protocols. (Sadly > there is no API gateway for those protocols) > - Drawbacks includes no revocation of access tokens (once it's signed > it is always valid), revocation do not shut down existing connections > authenticated with the revocated token, and key rotation would require > reconfiguration and reboot. > - One alternative would be to systematically ask the OpenID server to > validate the bearer. This might be acceptable as IMAP and SMTP are long > lived protocols that do not often establish new connections. While this > do not change anything regarding already opened connection management, > this solves revocation and public key rotation at the price of exposing > more the identity provider... > - Of course James could expose a back-channel for token invalidation, > stored in some kind of shared storage, but this complexify things a bit. > - Similarily HTTP calls could be made to get the JWKS key (and cache > it) but this also complexify the picture quite a bit... > > I am deeply convinced this efforts would help James admins more control > over exposed authentication mechanisms and ultimately offer state of the > art authentication options. This should help James check a few more > boxes in security reviews and eventually ease adoption! > > Useful links: > > [0] OpenId spec: https://openid.net/specs/openid-connect-core-1_0.html > > > [1] Krakend: https://www.krakend.io/ > [2] Keycloack: https://www.keycloak.org/ > [RFC-7628] SASL OATH mechanism for SMTP and IMAP: > https://datatracker.ietf.org/doc/html/rfc7628 > Krakend configured with keycloack: > https://www.krakend.io/docs/authorization/keycloak/ > Krakend configured with token revocation: > https://www.krakend.io/docs/authorization/revoking-tokens/ > > Best regards, > > Benoit TELLIER > > On 02/12/2021 11:41, btell...@apache.org wrote: >> |Hello Jamers! As part of our work at Linagora, we are looking toward - >> better integrating James within our product suite and for us this means >> support "Single Sign On" and "Single Log Out" for JMAP following the >> OpenId connect standard [0]. - Improving security standards used to >> operate James. (We have a growing activity within the health care >> market, sensible to security arguments) Regarding security standards we >> should ideally: - Be able to NOT advertise AUTH / LOGIN capabilities of >> unencrypted channels (Correspond to IMAP plainAuthDissallowed but >> generalized to other protocols) - Be able to require OAUTH/OIDC >> authentication for all protocols (IMAP, SMTP, JMAP) - this is what some >> of the health care providers we spoke to desired to do. - For our >> collaborative suite usage, while OIDC only for JMAP makes sense, we >> still wish to maintain PLAIN AUTH for IMAP and SMTP. - Of course >> settings for regular users not interested in OIDC should not change (no >> breaking changes, OIDC adoption is opt-in only). As such we propose >> ourselves to: - Contribute IMAP and SMTP SASL OAUTH extension described >> in [RFC-7628] - Modularize JMAP authentication mechanisms (letting the >> admin choose which one she wishes to use) - Enable authentication >> through a header mechanism eg `X-USER: btell...@apache.org`, which can >> be used to delegate OIDC authentication through a third party API >> gateway. We have Krackend [1] in mind. - Share documentation and a >> docker-compose of OIDC setup for IMAP, SMTP and JMAP in >> https://github.com/apache/james-project/tree/master/examples/oidc. This >> would include: - A LDAP still used by James UsersRepository. Provisioned >> with a testing user. - A pre-configured Keycloack [2] OpenID connect >> provider. - A pre-configured Krakend API gateway proxying JMAP - And >> finally a James server configured to only accept OIDC as an >> authentication mechanism for IMAP, SMTP and JMAP. - Unit tests for >> existing IMAP `plainAuthDissallowed` configuration parameter. Finally >> this is a good opportunity to restructure authentication related >> settings in imapserver.xml and smtpserver.xml file. Here are proposals >> for both files: [imapserver.xml] ---- <imapserver enabled="true"> >> <jmxName>imapserver-ssl</jmxName> <bind>0.0.0.0:993</bind> <tls >> socketTLS="true" startTLS="false"> >> <privateKey>file://conf/private.key</privateKey> >> <certificates>file://conf/certs.self-signed.csr</certificates> </tls> >> <!-- ... --> <authentication> >> <plainAuthEnabled>true|false</plainAuthEnabled> <!-- defaults to true >> --> <oauth> <!-- ommiting this block would disable oauth. All fields are >> compulsory --> <publicKey>file://conf/imapJWT.pub</publicKey> >> <oidcConfigurationURL>https://example.com/.well-known/openid-config</oidcConfigurationURL> >> <claim>mailAddress</claim> </oauth> </authentication> </imapserver> ---- >> [smtpserver.xml] ---- <smtpserver enabled="true"> >> <jmxName>smtpserver-ssl</jmxName> <bind>0.0.0.0:465</bind> <tls >> socketTLS="true" startTLS="false"> >> <privateKey>file://conf/private.key</privateKey> >> <certificates>file://conf/certs.self-signed.csr</certificates> </tls> >> <!--- ... --> <requireAuthForRelay>true|false</requireAuthForRelay> >> <authentication> <plainAuthEnabled>true|false</plainAuthEnabled> <!-- >> defaults to true --> <oauth> <!-- ommiting this block would disable >> oauth. All fields are compulsory --> >> <publicKey>file://conf/imapJWT.pub</publicKey> >> <oidcConfigurationURL>https://example.com/.well-known/openid-config</oidcConfigurationURL> >> <claim>mailAddress</claim> </oauth> </authentication> </smtpserver> ---- >> You can see that: - The `plainAuthDissallowed` parameter is proposed to >> be renamed to `auth.requireSSL`. (of course we should support fallback >> NOT to have a breaking change) - `auth.plainAuthEnabled` enable turning >> on/off plain auth, which allows having OIDC only mechanism. - >> `auth.requireSSL` will be generalized to SMTP. - In SMTP `requireAuth` >> setting is very misleading as it rather is `requireAuthForRelay`. I >> propose we rename this configuration option (of course we should support >> fallback NOT to have a breaking change). Here is the implementation >> strategies we would follow: - For JMAP have Krakend doing all the hard >> job for us, and use a dedicated header to carry the information over to >> James. - Our code contributions aims at easing such a setup (that would >> only require configuration) - Provide an informative example using >> krakend. We understand that this choice is ours, yet sharing it could >> allow reuse or similar setup - If some people wishes to write an OIDC >> authentication strategy directly in James then they perfectly can! >> (Reusing the modularization of JMAP authentication strategies we would >> provide). - For IMAP and SMTP then we proposes to check the bearer >> payload against a statically configured public key for these protocols. >> (Sadly there is no API gateway for those protocols) - Drawbacks includes >> no revocation of access tokens (once it's signed it is always valid), >> revocation do not shut down existing connections authenticated with the >> revocated token, and key rotation would require reconfiguration and >> reboot. - One alternative would be to systematically ask the OpenID >> server to validate the bearer. This might be acceptable as IMAP and SMTP >> are long lived protocols that do not often establish new connections. >> While this do not change anything regarding already opened connection >> management, this solves revocation and public key rotation at the price >> of exposing more the identity provider... - Of course James could expose >> a back-channel for token invalidation, stored in some kind of shared >> storage, but this complexify things a bit. - Similarily HTTP calls could >> be made to get the JWKS key (and cache it) but this also complexify the >> picture quite a bit... I am deeply convinced this efforts would help >> James admins more control over exposed authentication mechanisms and >> ultimately offer state of the art authentication options. This should >> help James check a few more boxes in security reviews and eventually >> ease adoption! Useful links: [0] OpenId spec: >> https://openid.net/specs/openid-connect-core-1_0.html [1] Krakend: >> https://www.krakend.io/ [2] Keycloack: https://www.keycloak.org/ >> [RFC-7628] SASL OATH mechanism for SMTP and IMAP: >> https://datatracker.ietf.org/doc/html/rfc7628 Krakend configured with >> keycloack: https://www.krakend.io/docs/authorization/keycloak/ Krakend >> configured with token revocation: >> https://www.krakend.io/docs/authorization/revoking-tokens/ Best regards, >> Benoit TELLIER| >> >> > --------------------------------------------------------------------- > To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org > For additional commands, e-mail: server-dev-h...@james.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org