mailcow / mailcow-dockerized

mailcow: dockerized - 🐮 + 🐋 = 💕
https://mailcow.email
GNU General Public License v3.0
9.02k stars 1.18k forks source link

External authentication (LDAP Support) #2316

Open ciroiriarte opened 5 years ago

ciroiriarte commented 5 years ago

Hi!, I see there are several requests for external authentation but no solution for any of them.

I would like to know what's the best approach to introduce mailcow to an ecosystem where an authentication platform is already inplace and used for all the application (LDAP/SAML/OAuth).

I usually see AD/OpenLDAP/LemonLDAP/Gluu in the wild as authentication source and would be nice to be able to do it by domain (I'm just thinking out loud).

Any thoughts on this?.

Ref:

1483

706

684

Akhun-Delar commented 1 year ago

Since the last message here is already nearly half a year old: is there any update? I would still like to crowdfund this. Maybe @andryyy or @DerLinkman can give a feedback about @guyguy333 's comment?

https://github.com/mailcow/mailcow-dockerized/issues/2316#issuecomment-1232523614

For me, it would be not even relevant if it's LDAP, SAML or any other process. Just to get Keycloak or Authentik connected to it... Creating mailboxes can be done manually or via script anyway, even if some automatization would be great.

DerLinkman commented 1 year ago

Hello everyone! This topic is highly discussed internally. @FreddleSpl0it made some ideas in case of Keycloak but these need to be fletched out.

Maybe he can tell his current idea (as I am not the right person for this "job" 🤫)

hackmybeer commented 1 year ago

Hey, any update on this @DerLinkman?

EDIT: Found this on the mailcow blog. Seems like LDAP is finally coming this year! 🎉🥳

ghost commented 1 year ago

https://mailcow.email/posts/2023/ldap-announcement/

pschiffe commented 1 year ago

This is a great news, looking forward to this feature! :tada: I have a question regarding Keycloak. In the blog post, it's mentioned that "The mailcow is connected to Keycloak via OIDC." I'm wondering if this OIDC connection is limited to Keycloak or if other Identity Providers (IdPs) like Auth0, Okta, or ZITADEL could also be used?

FreddleSpl0it commented 1 year ago

As we wanted to integrate the LDAP feature, we chose Keycloak as our solution. This is because, in addition to the LDAP feature, Keycloak provides other ways to authenticate mailbox users. We connected mailcow to Keycloak via OIDC, but encountered the problem that OIDC is not meant for verifying direct user credentials. However, since we need to verify direct user credentials for IMAP and SMTP, we had mailbox users first log in to the web UI via the new SSO and create an app password. This will also be the only way for other Identity Providers than Keycloak. If the mailbox does not exist, it will be created on the first login. mailcow will call the openid-connect userinfo endpoint with the received access token to find a mailcow_template attribute and create the appropriate mailbox type.

Keycloak-exclusive features:

as the first method is recommended for security purposes, there are also drawbacks to the LDAP feature. So we decided to also leverage the Keycloak REST API to authenticate against a Keycloak attribute named mailcow_password, which holds the hashed password for the user. This way, admins can set the mailcow_password in LDAP and map this attribute in Keycloak. The Keycloak REST API will also be used for the "Periodic Full Sync" and the "Import Users" feature. The "Import Users" feature will check at an interval if there are new users in Keycloak and create them in mailcow. This way, mailboxes can be created directly and not only on the first login. The "Periodic Full Sync" feature will make sure that if the mailcow_template attribute has changed, the mailbox will also be changed accordingly.

will probably look like this. I will also implement a form to add generic-oidc providers.

image

KnudH commented 1 year ago

Have you thought about using SCIM? With this, you can provision users without the need, that they have to log in. It's like a modern and less complex version of LDAP.

pschiffe commented 1 year ago

@FreddleSpl0it this is great, thank you so much. At this stage, will it be possible to use the external auth also for mailcow admins, or is it mailboxes only for now?

MohammedNoureldin commented 1 year ago

Hi, SSO sounds great! I still have a question. According to the link mentioned above. How would the client deal with login to OIDC? I do not mean webclients, but the native clients (Windows Mail, Thunderbird, Android clients, etc.). Will they automatically just pop up a Browser Window to authenticate? I know that this is typical for some other application, but I do not know what about Mail clients on different platforms.

MichaelSasser commented 1 year ago

@MohammedNoureldin You can generate or enter an app password and use it together with your email address as credentials.

MohammedNoureldin commented 1 year ago

@MichaelSasser so it would be only for service client, not human? Or did I get it wrong?

MichaelSasser commented 1 year ago

@MohammedNoureldin I'm not quite sure what you mean but that.

As far, as I understand it, you would log into the Mailcow UI using OIDC. Same for SoGO, but it internally holds an app password to talk to the email services because in the end it is also just a regular email client with a fance frontend, and its own user management. Depending on the OIDC provider, you might need to generate that app password yourself. For all other clients, you would generate one app password per client and use that app password as your password.

So, it is not different from how and when you would use app passwords currently, only that you then have to (which is a good thing).

All of that is because the whole email stuff is ancient and does not support fancy authentication like two (or multi) factor authentication, WebAuthn or OIDC/SAML. So, the fancy authentication thing is built around it, but for the actual email communication, like using IMAP and SMTP, a plain old password is still necessary.

The entire OIDC thing is not to make stuff safer. Don't get me wrong, in most cases it probably does. But the idea is more of having one account or identity that is centrally managed, that creates a session that can be used to authenticate the identity on many services.

razerrazer commented 1 year ago

Is there a specific release date planned for this?

fufroma commented 1 year ago

Is there a specific release date planned for this?

On https://mailcow.email/posts/2023/ldap-announcement/ the target is Q4 2023

ayushin commented 1 year ago

This is awesome. I can also highly recommend https://goauthentik.io as a modern replacement for KeyCloak

MohammedNoureldin commented 1 year ago

Hi @ayushin, what do you mean a "modern alternative"? Both do the same job. So technically they are just different software for the same purpose.

NexZhu commented 1 year ago

How can I test out the LDAP feature with the nightly release as stated in the blog post? Is there an instruction somewhere?

FreddleSpl0it commented 1 year ago

How can I test out the LDAP feature with the nightly release as stated in the blog post? Is there an instruction somewhere?

It is not available in the nightly build yet, but we are hopeful that it will be included sometime this month.

crutch12 commented 1 year ago

@FreddleSpl0it any progress on this?

pkejval commented 1 year ago

I'm desperately waiting for LDAP/Keycloak implementation as it's only thing stopping me from using this great product. Is there any news/progress already on this? I can help with future testing.

DerLinkman commented 1 year ago

I'm desperately waiting for LDAP/Keycloak implementation as it's only thing stopping me from using this great product. Is there any news/progress already on this? I can help with future testing.

Very very very very soon™️

pkejval commented 1 year ago

@DerLinkman

I'm just hoping for it not being Blizzard Soon™ https://wowwiki-archive.fandom.com/wiki/Soon or in Valve time https://developer.valvesoftware.com/wiki/Valve_Time

🤣

FreddleSpl0it commented 1 year ago

the feature is in the nightly build now. https://mailcow.email/posts/2023/mailcow-idp/ If someone wants to include keycloak into the mailcow stack:

create docker-compose.override.yml

version: '2.1'
services:

  keycloak-mailcow:
    image: quay.io/keycloak/keycloak:latest
    dns:
      - ${IPV4_NETWORK:-172.22.1}.244
    command:
      - start
      - --import-realm
      - --proxy edge
      - --hostname=${MAILCOW_HOSTNAME}
      - --http-enabled=true
      - --http-relative-path=/auth
      - --hostname-strict-https=false
      - --db=mariadb
      - --db-url=jdbc:mariadb://mysql/mailcow
      - --db-username=${DBUSER}
      - --db-password=${DBPASS}
      - --spi-x509cert-lookup-provider=nginx
    environment:
      - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
      # only initial
      - KEYCLOAK_ADMIN=admin
      - KEYCLOAK_ADMIN_PASSWORD=moohoo
      - KEYCLOAK_LOGLEVEL=TRACE
    restart: always
    tty: true
    networks:
      mailcow-network:
        ipv4_address: ${IPV4_NETWORK:-172.22.1}.247
        aliases:
          - keycloak

create data/conf/nginx/site.keycloak.custom

  location /auth/ {
    proxy_hide_header X-Frame-Options;
    proxy_pass "http://keycloak:8080/auth/";
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;   
    proxy_buffer_size 128k;
    proxy_buffers 64 512k;
    proxy_busy_buffers_size 512k;
    proxy_send_timeout 3600;
    proxy_read_timeout 3600;
    client_body_buffer_size 128k; 
  }
  location /auth/admin {
    proxy_hide_header X-Frame-Options;
    proxy_pass "http://keycloak:8080/auth/admin";
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;   
    proxy_buffer_size 128k;
    proxy_buffers 64 512k;
    proxy_busy_buffers_size 512k;
    proxy_send_timeout 3600;
    proxy_read_timeout 3600;
    client_body_buffer_size 128k; 
  }
NexZhu commented 1 year ago

@FreddleSpl0it Is the LDAP support limited to Keycloak? I'm running an OpenLDAP instance and want to use it as the authentication source.

pkejval commented 1 year ago

@NexZhu Mailcow should connect to Keycloak and your Keycloak to any user DB. It was announced there: https://mailcow.email/posts/2023/ldap-announcement/

FreddleSpl0it commented 1 year ago

@NexZhu It's limited to OIDC Identity Providers and Keycloak is the most supported one with more features like automatic user provisioning. The hardest Part was to change the way authentication works especially the Dovecot authentication. But this is now so universal designed, that we could basically add a direct LDAP support in the future.

But for now, it's only OIDC and especially Keycloak. Keycloak has so many features, such as LDAP or Kerberos Providers, and even the ability to log in with social platforms like GitLab, Twitter, and so on. We didn't want to reinvent the wheel, so we chose this path.

How to connect Keycloak to LDAP: https://mailcow.email/posts/2023/mailcow-idp/#ldap

mstilkerich commented 1 year ago

Hello, does this also allow oauth authentication at the SoGo CardDAV and CalDAV interfaces?

FreddleSpl0it commented 1 year ago

@mstilkerich No, it only permits users to utilize the external IdP to log in to the mailcow UI. Within the mailcow UI, users can proceed to the SOGo Webmail or generate App Passwords for use with other applications.

Could you tell me which application you use that can utilize OAuth for logging in to CardDAV and CalDAV? Perhaps I can implement this.

mstilkerich commented 1 year ago

My interest is on Roundcube. I tried to setup a SSO mailcow setup with Roundcube using the builtin oauth2 provider in mailcow a while ago. I got it working with dovecot and postfix (configuration changes for both needed) if I recall correctly but failed with SoGo's carddav interface.

But I am just interested in this for educational purposes / having a test env for roundcube carddav plugin with oauth authentication, for my small family server I have no need for a central authentication solution.

Btw I did have a working OIDC SSO setup with roundcube, keycloak, dovecot, postfix and nextcloud (for contacts/carddav), so I know from the roundcube side this would be supported.

MichaelSasser commented 1 year ago

First off, Great work. Thank you very much for implementing this feature!

I have a few questions about how this would look in the future.

  1. Will we be able to authenticate using multiple realms against the same instance of mailcow?

    In other projects, this is done by allowing to configure multiple identity providers of the same kind/type and giving them a display name, which is shown on the login page. Some of them even allow HTML display names, which enable administrators to display an <img> in front, so users find their provider faster.

    The scenario is that I have two realms on my keycloak instance. One personal, for me and my family, and one for our moderators of our public community project. The realms are differently configured in keycloak have a different set of services they access. Both realms are served on a different domain (still, the same instance of keycloak) and all users (in both realms) use only their realm-specific domain in their email address with their preferred_username as local part. The same happens on the mailcow side. For example:

    • Family Realm
      • user foofoo@family.com; keycloak: login.family.com; mailcow: mail.family.com
      • user barbar@family.com; keycloak: login.family.com; mailcow: mail.family.com
    • Community Realm:
      • user foofoo@community.com; keycloak: login.community.com; mailcow: mail.community.com
      • user bazbaz@community.com; keycloak: login.community.com; mailcow: mail.community.com
  2. Is mailcow using x509 client certificate lookup (as shown in @FreddleSpl0it example above)? The reason for the question is that keycloak's support for this feature is limited to some reverse proxies I'm not using.

  3. Will we be able to disable all other kinds of authentication (besides app-passwords, of course) or block the endpoints in the reverse proxy, so users can only authenticate through OIDC?

  4. Will we be able to configure this using a config file (or environment variables)?

  5. How will we be able to migrate existing mailcow users (with their data and their app-passwords to the OIDC flow)?

MohammedNoureldin commented 1 year ago

Will this OIDC feature be usable with Desktop / Mobile clients? Or is it exclusive for Webmails?

In case it can be used in Desktop clients, how will the client prompt / redirect to the IdP login page? Or let us say, which clients are supported?

FreddleSpl0it commented 1 year ago

@MichaelSasser

  1. That's a good point. At the moment only one Realm for Keycloak is supported. If you have configured a IdP, there will be a SSO dropdown button that redirects users to the Realm Login. I don't know yet how we could redirect users to the right Realm login if multiples could be configured. The only way we could do that, as you say, is to allow multiple IdP's and then display each IdP as a separate login button (maybe as an app button)
  2. I should say that the example i posted, was the setup i used in our tests. This will include Keycloak into the mailcow Stack behind the nginx container. I wouldn't run it in production. Preferably, you already have a running Keycloak instance or you set one up yourself separately. mailcow will not use x509 client certificate lookups. Also in production you should limit the access to the /admin endpoint somehow. But keep in mind that mailcow needs to access this endpoint, if you use the Mailpassword Flow, Periodic Full Sync or Import users feature.
  3. For each user there is a authsource, that defines how this user should be authenticated. If the users authsource is keycloak or generic-oidc than there is no other way for this user to authenticate besides app passwords. This is also the reason why IdP users need to login to mailcow UI in order to get into the SOGo Webmail.
  4. Do you mean the IdP configuration? It is configurable by admins via mailcow UI.
  5. This should be easy. See https://mailcow.email/posts/2023/mailcow-idp/#change-idp-for-existing-mailbox-users
FreddleSpl0it commented 1 year ago

Will this OIDC feature be usable with Desktop / Mobile clients? Or is it exclusive for Webmails?

@MohammedNoureldin Currently it is not supported and I don't know yet of any Client that allows the configuration of a custom oAuth provider. The client would need to be able to open a Browser and redirect the user to the IdP login. On success, it would receive a oAuth token and uses this for further authentication via IMAP or EAS

mkuron commented 1 year ago

I don't know yet of any Client that allows the configuration of a custom oAuth provider

There is RFC 7628: A Set of Simple Authentication and Security Layer (SASL) Mechanisms for OAuth, which allows the client to retrieve the provider information from the server. It is supported by the Dovecot server. There are several clients (Thunderbird, Apple Mail, Evolution, emClient, Outlook) that support OAuth with Google, Microsoft and/or Yahoo, but as of 2021 these were using static lists of OAuth providers. At least for Thunderbolt and Evolution, that still seems to be the case.

MohammedNoureldin commented 1 year ago

Thank you for the info, @mkuron and @FreddleSpl0it,

There is RFC 7628: A Set of Simple Authentication and Security Layer (SASL) Mechanisms for OAuth, which allows the client to retrieve the provider information from the server. It is supported by the Dovecot server. There are several clients (Thunderbird, Apple Mail, Evolution, emClient, Outlook) that support OAuth with Google, Microsoft and/or Yahoo, but as of 2021 these were using static lists of OAuth providers. At least for Thunderbolt and Evolution, that still seems to be the case.

So for the these clients it should be technically a matter of giving the end-user the ability to configure his IdP on the client? Is there anything we can do, except extending the code of these software, to allow the mail clients to login using our custom IdP? In other words, to allow the end-user to configure SASL in the client?

mkuron commented 1 year ago

You could check their bugtrackers for whether any work on that is planned, and file feature requests for RFC 7628 support if it isn't already planned. Also, given the lack of client support, I don't know whether Dovecot's Oauth support is well-tested and stable, so you could do some online research about whether anyone has successfully deployed it.

Thunderbird has several feature requests related to various aspects of this:

havi05 commented 1 year ago

Thank you for the great feature! I also have a few questions about it.

  1. Did I understand it correctly that (currently?) only email users (not administrators and domain administrators) can use openid connect? If no, is it planned to add this?

  2. Is currently only one alias (mailcow_template) possible at keycloak, or is there a list with all possibilities? (For example mailcow_quota to change the limit for one user, mailcow_role to change the permissions of one user or mailcow_email_alias_enabled to allow the use of email aliases by the user)

  3. Is it possible to change for example the quota of a user which uses mailcow_template or will it be changed back when updating via keycloak?

privnote42 commented 1 year ago

@FreddleSpl0it Maybe it's interesting for you, or for others. Here is a docker-compose.yml created to be able to log in to sogo via SSO with the help of keycloak. https://github.com/fsphys/sogo-keycloak-docker-example

Unfortunately, the repo is no longer maintained and it no longer works with the current sogo. When I try to log in, I get a 501 error. (The URL for the sogo repo is no longer up to date in the Dockerfile, just as a hint)

Perhaps this approach can also be integrated directly into the mailcow stack so that the current workaround with the php script can be dispensed with?

dorianim commented 1 year ago

Some time ago, I built a hacky syncer for the linuxmuster project, which enables automatic user and mailing list provisioning and authentication from LDAP in mailcow. I'd love to get rid of it in the favor of this new implementation. However, there is one thing, that does not seem possible yet: Mailing-Lists. In Linuxmuster, users can create projects and add users to them. The syncer then creates a mailbox for each project and adds a sieve filter to forward incoming mail to all members. Is there any plan to implement something similar for oidc?

MohammedNoureldin commented 1 year ago

In this case, if I want to use any centralized user management (e.g., federated users in KeyCloak) you will only be able to use web interface, but not any native client for desktop or mobile, to login to your email. Right?

davidus05 commented 1 year ago

As mentioned in that issue https://github.com/mailcow/mailcow-dockerized/issues/5445 it seems that OIDC is not fully generic/not fully working. Only the KeyCloak integration seems to be working currently.

palukku commented 12 months ago

Maybe you should do a third option or change the default oidc option for the identity provider. At the moment you require to set the urls for auth/token etc. myself. But instead you could get all these informations from a link which keycloak and authentik etc. are providing: keycloak.tld/realms/REALMNAME/.well-known/openid-configuration authentik.tld/application/o/PROVIDERNAME/.well-known/openid-configuration

If you would get the informations for the endpoints from this file, it would be much easier to configure for example Authentik or other openid connect services.

Maybe you could use this also to implement a custom link for getting all the users like it is there for keycloak, so it would be much easier to do a full sync with other providers than keycloak.

Fly7113 commented 1 week ago

Are there any news about the status of this feature? Has it reached an only testing stage or are there plans to expand it before it makes its way to production (relative to its actual state in the nightly build)?