We are developing a limited-input printer. The printer does not have a web browser, so we use Microsoft OAuth 2.0 Device Code Flow.
Our targets are:
- Obtain an access token that can be used to send email through SMTP AUTH XOAUTH2.
- Obtain the correct user name that should be used in the user= field of the SMTP AUTH XOAUTH2 SASL string.
- Require the end user to complete consent only one time in a web browser.
The SMTP AUTH XOAUTH2 SASL string format is:
base64("user=" + userName + "^Aauth=Bearer " + accessToken + "^A^A")
The main problem is how to reliably obtain the correct userName value.
We already tested following 4 methods, but all methods failed to achieve the above three targets at the same time.
Method 1:
Method 1 - Step 1:
HTTP
POST /common/oauth2/v2.0/devicecode HTTP/1.1
Host: login.microsoftonline.com
User-Agent: curl/8.13.0
Accept: */*
Content-Length: 127
Content-Type: application/x-www-form-urlencoded
client_id=3caf90da-c45a-4a78-9fd1-f7aa22fca3b6&scope=https://graph.microsoft.com/User.Read https://outlook.office.com/SMTP.Send
HTTP/1.1 200 OK
Cache-Control: no-store, no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
x-ms-request-id: dc87aafd-b992-48ca-80db-91b062770d00
x-ms-ests-server: 2.1.24503.7 - JPWLR1 ProdSlices
x-ms-srs: 1.P
{"user_code":"OTD8DLVHP","device_code":"OBgABIQEAAAAdDD...","verification_uri":"https://login.microsoft.com/device","expires_in":900,"interval":5,"message":"To sign in, use a..."}
Method 1 - Step 2:
HTTP
POST /common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
User-Agent: curl/8.13.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 1096
client_id=3caf90da-c45a-4a78-9fd1-f7aa22fca3b6&device_code=OBgABIQEAAAAdDD...&grant_type=urn:ietf:params:oauth:grant-type:device_code
HTTP/1.1 400 Bad Request
Cache-Control: no-store, no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
x-ms-clientdata: e|28000||microsoftonline.com|none
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
x-ms-request-id: d4132094-5c4e-4431-98bc-59a1a96a1600
x-ms-ests-server: 2.1.24503.7 - SEASLR1 ProdSlices
x-ms-srs: 1.P
{"error":"invalid_request","error_description":"AADSTS28000: Provided value for the input parameter scope is not valid because it contains more than one resource. Scope https://graph.microsoft.com/User.Read https://outlook.office.com/SMTP.Send is not valid. Trace ID: d4132094-5c4e-4431-98bc-59a1a96a1600 Correlation ID: c785b83b-aa5d-4721-abe6-16ea5eec257e Timestamp: 2026-06-09 01:57:26Z","error_codes":[28000],"timestamp":"2026-06-09 01:57:26Z","trace_id":"d4132094-5c4e-4431-98bc-59a1a96a1600","correlation_id":"c785b83b-aa5d-4721-abe6-16ea5eec257e"}
Method 1 cannot achieve the three targets at the same time.
Method 2:
HTTP
POST /common/oauth2/v2.0/devicecode HTTP/1.1
Host: login.microsoftonline.com
User-Agent: curl/8.13.0
Accept: */*
Content-Length: 127
Content-Type: application/x-www-form-urlencoded
client_id=3caf90da-c45a-4a78-9fd1-f7aa22fca3b6&scope=openid profile email offline_access https://outlook.office.com/SMTP.Send
Then decode the id_token and use preferred_username as the SMTP XOAUTH2 username.
According to Microsoft documentation, preferred_username is mutable and suitable for display or username hints. Therefore we cannot safely use preferred_username as the user= value in SMTP AUTH XOAUTH2.
Method 3:
Method 3 Step 1:
HTTP
POST /common/oauth2/v2.0/devicecode HTTP/1.1
Host: login.microsoftonline.com
User-Agent: curl/7.83.1
Accept: */*
Content-Length: 114
Content-Type: application/x-www-form-urlencoded
Connection: close
client_id=3caf90da-c45a-4a78-9fd1-f7aa22fca3b6&scope=offline_access%20https%3A%2F%2Foutlook.office.com%2FSMTP.Send
HTTP/1.1 200 OK
Cache-Control: no-store, no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 1271
{"user_code":"NJKJHTJZP","device_code":"NBgABIQ...","verification_uri":"https://login.microsoft.com/device","expires_in":900,"interval":5}
Method 3 Step 2:
HTTP
POST /common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
User-Agent: curl/7.83.1
Accept: */*
Content-Length: 1118
Content-Type: application/x-www-form-urlencoded
Connection: close
client_id=3caf90da-c45a-4a78-9fd1-f7aa22fca3b6&device_code=NBgABIQ...&grant_type=urn:ietf:params:oauth:grant-type:device_code
HTTP/1.1 200 OK
Cache-Control: no-store, no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 1940
{"token_type":"Bearer","scope":"https://outlook.office.com/SMTP.Send","expires_in":3599,"ext_expires_in":3599,"access_token":"EwAIBOl...","refresh_token":"M.C554_BL..."}
Method 3 Step 3:
HTTP
POST /common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
User-Agent: curl/7.83.1
Accept: */*
Content-Length: 555
Content-Type: application/x-www-form-urlencoded
Connection: close
client_id=3caf90da-c45a-4a78-9fd1-f7aa22fca3b6&grant_type=refresh_token&refresh_token=M.C554_BL..&scope=https%3A%2F%2Fgraph.microsoft.com%2FUser.Read
HTTP/1.1 400 Bad Request
Cache-Control: no-store, no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 601
{"error":"invalid_grant","error_description":"AADSTS70000: The request was denied because one or more scopes requested are unauthorized or expired. The user must first sign in and grant the client application access to the requested scope. Trace ID: 2867f178-e432-4702-afbe-fef568191e00 Correlation ID: c13dbba2-e84e-4019-b3e3-4824126fe498 Timestamp: 2026-06-27 08:55:30Z","error_codes":[70000],"timestamp":"2026-06-27 08:55:30Z","trace_id":"2867f178-e432-4702-afbe-fef568191e00","correlation_id":"c13dbba2-e84e-4019-b3e3-4824126fe498","error_uri":"https://login.microsoftonline.com/error?code=70000"}
Method 3 also cannot achieve the three targets at the same time.
Method 4:
Method 4 - Step 1:
HTTP
POST /common/oauth2/v2.0/devicecode HTTP/1.1
Host: login.microsoftonline.com
User-Agent: curl/7.83.1
Accept: */*
Content-Length: 162
Content-Type: application/x-www-form-urlencoded
Connection: close
client_id=8523e5e3-dcd1-4e56-8d32-15cdf1cb458d&scope=offline_access%20https%3A%2F%2Fgraph.microsoft.com%2FUser.Read%20https%3A%2F%2Foutlook.office.com%2FSMTP.Send
HTTP/1.1 200 OK
Cache-Control: no-store, no-cache
Pragma: no-cache
Connection: close
Content-Length: 1271
{"user_code":"HA43XWQT8","device_code":"HBgABIQ...","verification_uri":"https://login.microsoft.com/device","expires_in":900,"interval":5}
Method 4 - Step 2:
HTTP
POST /common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
User-Agent: curl/7.83.1
Accept: */*
Content-Length: 1169
Content-Type: application/x-www-form-urlencoded
Connection: close
grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=HBgABIQ...&client_id=8523e5e3-dcd1-4e56-8d32-15cdf1cb458d&scope=https%3A%2F%2Foutlook.office.com%2FSMTP.Send
HTTP/1.1 400 Bad Request
Cache-Control: no-store, no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 570
{"error":"invalid_scope","error_description":"AADSTS70011: The provided value for the input parameter 'scope' is not valid. One or more scopes in 'offline_access https://graph.microsoft.com/User.Read https://outlook.office.com/SMTP.Send' are not compatible with each other. Trace ID: e57c0b2a-3207-4bc6-a0f1-ff4d58b00c00 Correlation ID: c3384118-f3d8-47eb-8777-2b9c767584ab Timestamp: 2026-06-29 03:42:18Z","error_codes":[70011],"timestamp":"2026-06-29 03:42:18Z","trace_id":"e57c0b2a-3207-4bc6-a0f1-ff4d58b00c00","correlation_id":"c3384118-f3d8-47eb-8777-2b9c767584ab"}
So Method 4 also failed.
Summary:
All three suggested methods failed to achieve the following three targets at the same time:
Targets 1: Obtain an access token that can be used to send email through SMTP AUTH XOAUTH2.
Targets 2: Obtain the correct user name that should be used in the user= field of the SMTP AUTH XOAUTH2 SASL string.
Targets 3: Require the end user to complete consent only one time in a web browser.
Questions:
- Does Microsoft officially support achieving these three targets at the same time for a limited-input device using OAuth 2.0 Device Code Flow?
- If yes, please provide the exact official HTTP request sequence.
- If the three targets cannot be achieved at the same time, please clearly confirm that limitation and provide the Microsoft-recommended product design for a limited-input printer that supports SMTP AUTH XOAUTH2 and POP3 AUTH XOAUTH2.