I would like to authenticate users that use the PLAIN mechanism
against an oauth2 idp (in this case it's an Azure AD B2C).
I configured dovecot.conf with
auth_mechanisms = plain oauthbearer xoauth2
passdb {
driver = oauth2
mechanisms = plain login
args = /etc/dovecot/dovecot-oauth2.plain.conf.ext
}
and in /etc/dovecot/dovecot-oauth2.plain.conf.ext I have
grant_url =
https://simons0f7b2c.b2clogin.com/simons0f7b2c.onmicrosoft.com/B2C_1_ROPC_Auth/oauth2/v2.0/token?scope=xxxxx-5be3-405a-babb-xxxx
client_id = xxxxx-5be3-405a-babb-xxxx
client_secret = m6xxxxxxxx
username_attribute = extension_PreferredLoginUsername
#introspection_url = http://localhost:8000/introspect
#introspection_mode = post
use_grant_password = yes
debug = yes
pass_attrs = host=127.0.0.1 proxy=y proxy_mech=xoauth2
pass=%{oauth2:access_token}
I can see that dovecot sends a request to simons0f7b2c.b2clogin.com
that looks like this:
POST
/simons0f7b2c.onmicrosoft.com/B2C_1_ROPC_Auth/oauth2/v2.0/token?scope=xxxxx-5be3-405a-babb-xxxx
HTTP/1.1
Host: simons0f7b2c.onmicrosoft.com
Date: Tue, 04 Oct 2022 15:43:42 GMT
User-Agent: dovecot-oauth2-passdb/2.3.16
Content-Length: 169
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=sp12@31337.it&password=<userpass>&client_id=xxxxx-5be3-405a-babb-xxxx&client_secret=m6xxxxxxxx
and the response is something like
HTTP/1.1 200 OK
Cache-Control: no-store, must-revalidate, no-cache
Content-Type: application/json; charset=utf-8
Set-Cookie: x-ms-cpim-trans=; domain=simons0f7b2c.b2clogin.com;
expires=Thu, 04-Oct-2012 15:29:04 GMT; path=/; SameSite=None;
secure; HttpOnly
x-ms-gateway-requestid: 6ce588cf-9e35-491e-8393-18da8ccbe2cd
X-Frame-Options: DENY
Public: OPTIONS,TRACE,GET,HEAD,POST
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Allow: OPTIONS
Allow: TRACE
Allow: GET
Allow: HEAD
Allow: POST
Date: Tue, 04 Oct 2022 15:29:03 GMT
Content-Length: 1003
{"access_token":"eyJ0xxxxx9uIw","token_type":"Bearer","expires_in":"3600"}
Decoding the access_token I can see that there is a field
extension_PreferredLoginUsername:
{
"typ": "JWT",
"alg": "RS256",
"kid": "X5eXk4"
}.{
"iss": "https://simons0f7b2c.b2clogin.com/xxxxx/v2.0/",
"exp": 1664898983,
"nbf": 1664895383,
"aud": "xxxxx-5be3-405a-babb-xxxx",
"idp": "LocalAccount",
"sub": "969xxx7",
"extension_PreferredLoginUsername": "s2",
"tfp": "B2C_1_ROPC_Auth",
"azp": "89xxxc0",
"ver": "1.0",
"iat": 1664895383
}
so the field extension_PreferredLoginUsername is there, but dovecot
says:
dovecot: auth: Debug: http-client: conn
40.126.31.64:443 [1]: Got 200 response for request [Req1: POST
https://simons0f7b2c.b2clogin.com/simons0f7b2c.onmicrosoft.com/B2C_1_ROPC_Auth/oauth2/v2.0/token?scope=xxxxx-5be3-405a-babb-xxxx]:
OK (took 1016 ms + 327 ms in queue)
dovecot: auth: Debug:
oauth2(sp12@31337.it,192.168.0.4,<p0vv9jbq3MrAqAAE>):
Password grant succeeded
dovecot: auth: Debug:
oauth2(sp12@31337.it,192.168.0.4,<p0vv9jbq3MrAqAAE>):
Processing field access_token
dovecot: auth: Debug:
oauth2(sp12@31337.it,192.168.0.4,<p0vv9jbq3MrAqAAE>):
Processing field token_type
dovecot: auth: Debug:
oauth2(sp12@31337.it,192.168.0.4,<p0vv9jbq3MrAqAAE>):
Processing field expires_in
dovecot: auth: Error:
oauth2(sp12@31337.it,192.168.0.4,<p0vv9jbq3MrAqAAE>): oauth2
failed: Password grant failed: No username returned
dovecot: auth: Debug:
oauth2(sp12@31337.it,192.168.0.4,<p0vv9jbq3MrAqAAE>):
Finished passdb lookup
dovecot: auth: Debug:
pam(sp12@31337.it,192.168.0.4,<p0vv9jbq3MrAqAAE>):
Performing passdb lookup
So, why does dovecot say "No username returned"? The username is
there! Do I have to configure something else?