Azure AD / Entra Id OAuth2 issue, username not recognized
Dovecot version 2.3.16
Trying to use Azure AD / Entra Id with OAuth2 authentication, I have most of it working but somehow Dovecot fails to map / recognize the username, hopefully somebody can point out what I'm doing wrong?
Excerpt from log: Jan 26 09:13:20 localhost dovecot: auth: Debug: http-client: conn [2603:1026:3000:108::4]:443 [1]: Got 200 response for request [Req1: POST https://login.microsoftonline.com/79b065d9-761f-4b79-a5cb-71a452f452af/oauth...]: OK (took 220 ms + 82 ms in queue) Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Password grant succeeded Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field token_type Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field scope Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field expires_in Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field ext_expires_in Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field access_token Jan 26 09:13:20 localhost dovecot: auth: Error: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): oauth2 failed: Password grant failed: No username returned
I'm using Resource Owner Password Grant flow. I have the following configured in conf.d/auth-oauth.conf.ext:
passdb { driver = oauth2 mechanisms = plain args = /etc/dovecot/dovecot-oauth2.plain.conf.ext }
I have the following configured in dovecot-oauth2.plain.conf.ext:
grant_url = https://login.microsoftonline.com/<redacted>/oauth2/v2.0/token client_id = <redacted> client_secret = <redacted> username_attribute = email use_grant_password = yes scope = api://<redacted>/mail-relay debug = yes rawlog_dir = /tmp/oauth2
I have the following response from the oauth raw logs:
out: 1706256800.309971 POST /<redacted>/oauth2/v2.0/token HTTP/1.1 1706256800.309971 Host: login.microsoftonline.com 1706256800.309971 Date: Fri, 26 Jan 2024 08:13:20 GMT 1706256800.309971 User-Agent: dovecot-oauth2-passdb/2.3.16 1706256800.309971 Content-Length: 255 1706256800.309971 Connection: Keep-Alive 1706256800.310013 Content-Type: application/x-www-form-urlencoded 1706256800.310018 1706256800.310056 grant_type=password&username=test-external@example.org&password=<redacted>&client_id=<redacted>&client_secret=<redacted>&scope=api:%2f%2f<redacted>%2fmail-relay
in: 1706256800.530754 HTTP/1.1 200 OK 1706256800.530754 Cache-Control: no-store, no-cache 1706256800.530754 Pragma: no-cache 1706256800.530754 Content-Type: application/json; charset=utf-8 1706256800.530754 Expires: -1 1706256800.530754 Strict-Transport-Security: max-age=31536000; includeSubDomains 1706256800.530754 X-Content-Type-Options: nosniff 1706256800.530754 P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" 1706256800.530754 x-ms-request-id: 629ce7bf-a5e9-4655-9019-83690c8b4400 1706256800.530754 x-ms-ests-server: 2.1.17122.2 - SEC ProdSlices 1706256800.530754 X-XSS-Protection: 0 1706256800.530754 Set-Cookie: fpc=Am8EyNTmX2ZOkMLj2MB82W4gKLwwAQAAAJ9gRd0OAAAA; expires=Sun, 25-Feb-2024 08:13:20 GMT; path=/; secure; HttpOnly; SameSite=None 1706256800.530754 Set-Cookie: x-ms-gateway-slice=estsfd; path=/; secure; samesite=none; httponly 1706256800.530754 Set-Cookie: stsservicecookie=estsfd; path=/; secure; samesite=none; httponly 1706256800.530754 Date: Fri, 26 Jan 2024 08:13:20 GMT 1706256800.530754 Content-Length: 1979 1706256800.530754 1706256800.530754 {"token_type":"Bearer","scope":"api://<redacted>/mail-relay","expires_in":5296,"ext_expires_in":5296,"access_token":"eyJ0eX ...<redacted>"}
If I inspect the access token I'm getting: { "aud": "<redacted>", "iss": "<redacted>", "iat": 1706256500, "nbf": 1706256500, "exp": 1706262097, "acr": "1", "aio": "ATQAy/8VAAAANgbkS6NmHL3yGyROhLM28ooLX57pCjHjp0TGtd7EjwgVZy/i2aEqfV6sxiHeGZ0N", "amr": [ "pwd" ], "appid": "<redacted>", "appidacr": "1", "email": "test-external@example.org", "ipaddr": "<redacted>", "login_hint": "<redacted>", "name": "test-external", "oid": "657401f0-c9f0-402c-af6f-9ef063e7a281", "preferred_username": "test-external@example.org", "rh": "0.ATEA2WWweR92eUuly3GkUvRSr08CZ45J3dRLnCQJZCVUYBcxAKo.", "scp": "mail-relay", "sub": "ST9owcQQN2e0tBsHiVjvR8SCdlfUR_114tJk4C2bRxg", "tid": "79b065d9-761f-4b79-a5cb-71a452f452af", "unique_name": "test-external@sexample.org", "upn": "test-external@example.org", "uti": "v-ecYumlVUaQGYNpDItEAA", "ver": "1.0" }
The email attribute is present in the access token yet Dovecot doesnt appear to recognize it. What am I doing wrong?
I have a suspicion its not working because the scp attribute doesnt contain "email", can anybody confirm that this might be the issue?
Your problem is that the access_token field actually contains the token. so you need use either local validation or introspection. I would recommend setting up local validation.
Aki
On 26/01/2024 10:33 EET meint@meint.net wrote:
Dovecot version 2.3.16
Trying to use Azure AD / Entra Id with OAuth2 authentication, I have most of it working but somehow Dovecot fails to map / recognize the username, hopefully somebody can point out what I'm doing wrong?
Excerpt from log: Jan 26 09:13:20 localhost dovecot: auth: Debug: http-client: conn [2603:1026:3000:108::4]:443 [1]: Got 200 response for request [Req1: POST https://login.microsoftonline.com/79b065d9-761f-4b79-a5cb-71a452f452af/oauth...]: OK (took 220 ms + 82 ms in queue) Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Password grant succeeded Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field token_type Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field scope Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field expires_in Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field ext_expires_in Jan 26 09:13:20 localhost dovecot: auth: Debug: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): Processing field access_token Jan 26 09:13:20 localhost dovecot: auth: Error: oauth2(test-external@secumailer.com,2a05:d018:ebe:d005:22b6:dc4b:41c6:7fec): oauth2 failed: Password grant failed: No username returned
I'm using Resource Owner Password Grant flow. I have the following configured in conf.d/auth-oauth.conf.ext:
passdb { driver = oauth2 mechanisms = plain args = /etc/dovecot/dovecot-oauth2.plain.conf.ext }
I have the following configured in dovecot-oauth2.plain.conf.ext:
grant_url = https://login.microsoftonline.com/<redacted>/oauth2/v2.0/token client_id = <redacted> client_secret = <redacted> username_attribute = email use_grant_password = yes scope = api://<redacted>/mail-relay debug = yes rawlog_dir = /tmp/oauth2
I have the following response from the oauth raw logs:
out: 1706256800.309971 POST /<redacted>/oauth2/v2.0/token HTTP/1.1 1706256800.309971 Host: login.microsoftonline.com 1706256800.309971 Date: Fri, 26 Jan 2024 08:13:20 GMT 1706256800.309971 User-Agent: dovecot-oauth2-passdb/2.3.16 1706256800.309971 Content-Length: 255 1706256800.309971 Connection: Keep-Alive 1706256800.310013 Content-Type: application/x-www-form-urlencoded 1706256800.310018 1706256800.310056 grant_type=password&username=test-external@example.org&password=<redacted>&client_id=<redacted>&client_secret=<redacted>&scope=api:%2f%2f<redacted>%2fmail-relay
in: 1706256800.530754 HTTP/1.1 200 OK 1706256800.530754 Cache-Control: no-store, no-cache 1706256800.530754 Pragma: no-cache 1706256800.530754 Content-Type: application/json; charset=utf-8 1706256800.530754 Expires: -1 1706256800.530754 Strict-Transport-Security: max-age=31536000; includeSubDomains 1706256800.530754 X-Content-Type-Options: nosniff 1706256800.530754 P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" 1706256800.530754 x-ms-request-id: 629ce7bf-a5e9-4655-9019-83690c8b4400 1706256800.530754 x-ms-ests-server: 2.1.17122.2 - SEC ProdSlices 1706256800.530754 X-XSS-Protection: 0 1706256800.530754 Set-Cookie: fpc=Am8EyNTmX2ZOkMLj2MB82W4gKLwwAQAAAJ9gRd0OAAAA; expires=Sun, 25-Feb-2024 08:13:20 GMT; path=/; secure; HttpOnly; SameSite=None 1706256800.530754 Set-Cookie: x-ms-gateway-slice=estsfd; path=/; secure; samesite=none; httponly 1706256800.530754 Set-Cookie: stsservicecookie=estsfd; path=/; secure; samesite=none; httponly 1706256800.530754 Date: Fri, 26 Jan 2024 08:13:20 GMT 1706256800.530754 Content-Length: 1979 1706256800.530754 1706256800.530754 {"token_type":"Bearer","scope":"api://<redacted>/mail-relay","expires_in":5296,"ext_expires_in":5296,"access_token":"eyJ0eX ...<redacted>"}
If I inspect the access token I'm getting: { "aud": "<redacted>", "iss": "<redacted>", "iat": 1706256500, "nbf": 1706256500, "exp": 1706262097, "acr": "1", "aio": "ATQAy/8VAAAANgbkS6NmHL3yGyROhLM28ooLX57pCjHjp0TGtd7EjwgVZy/i2aEqfV6sxiHeGZ0N", "amr": [ "pwd" ], "appid": "<redacted>", "appidacr": "1", "email": "test-external@example.org", "ipaddr": "<redacted>", "login_hint": "<redacted>", "name": "test-external", "oid": "657401f0-c9f0-402c-af6f-9ef063e7a281", "preferred_username": "test-external@example.org", "rh": "0.ATEA2WWweR92eUuly3GkUvRSr08CZ45J3dRLnCQJZCVUYBcxAKo.", "scp": "mail-relay", "sub": "ST9owcQQN2e0tBsHiVjvR8SCdlfUR_114tJk4C2bRxg", "tid": "79b065d9-761f-4b79-a5cb-71a452f452af", "unique_name": "test-external@sexample.org", "upn": "test-external@example.org", "uti": "v-ecYumlVUaQGYNpDItEAA", "ver": "1.0" }
The email attribute is present in the access token yet Dovecot doesnt appear to recognize it. What am I doing wrong?
dovecot mailing list -- dovecot@dovecot.org To unsubscribe send an email to dovecot-leave@dovecot.org
Hi Aki,
Thank you for taking the time to answer my question, I greatly appreciate your effort.
With a little bit of experimentation and reading the documentation I was able to setup local introspection validation and the OAuth2 authentication is now succeeding. Thank you!
For those of you experiencing a similar situation this is the dovecot-oauth2.plain.conf.ext conf file after applying Aki's advice:
grant_url = https://login.microsoftonline.com/<tenant id>/oauth2/v2.0/token client_id = <client id> client_secret = <client secret> username_attribute = email use_grant_password = yes introspection_mode = local scope = api://<client id>/mail-relay local_validation_key_dict = fs:posix:prefix=/etc/dovecot/keys/
I retrieved the local validation keys from Azure AD / Entra ID via this url: https://login.microsoftonline.com/<tenant id>/discovery/keys?appid=<client id>
This yields a json array which needs to be stored in /etc/dovecot/keys which the following folder structure: /etc/dovecot/keys/default/RS256
in the RS256 folder you need to create a file per kid. The Azure AD endpoint provided me with an array containing 2 items. I created a file for item 1 and copied in the individual key item and did the same for the other key item (identified by the kid attribute). Each file is named after its kid attribute.
Kind regards Meint
participants (2)
-
Aki Tuomi
-
meint@meint.net