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

Reply via email to