Sending Email using Azure EWS with OAuth2.0 Client Credential - oauth-2.0

I have question 'bout using EWS with Oauth2.0 Client Credential.
In our directory, there're users with member type and guest type, however, all of our administrators are from Microsoft directory(using v-xxx#microsoft.com) and they are under guest.
My question is if it's possible to use credential client grant type, and use EWS to send email behalf of these guest users?
For now, I tried to use EASendMail sdk to achieve this task. However, whenever I use account within our directory(member type) I get "There is no SMTP email associated" which is what I expected, 'cause we do not have email address associated with these users. But when I tried using (v-xxx#microsoft.com) , "Mailbox does not exist" error is raised.
Thank you.

You can do as long as the app has been granted impersonation permissions. OAuth is supported for the client credential flow(app permissions) & impersonation to do so.

Related

How can I access mails from Shared mailbox using Mailkit

Recently Microsoft has started to authenticate user with OAuth 2.0 protocol. I have implemented it in Asp.net Core C# and got token.
Now I am able to access mails from main mail Inbox using Mailkit from Microsoft exchange server using OAuth 2.0. But how can I be able to access mails from shared mailbox?
In my code I have mentioned shared mailbox account id.
My code is as follows
Code
Getting exception as "Autheticated but not connected". Please guide
The "Authenticated but not connected" error is unique to Microsoft Exchange IMAP servers and means that your account is not authorized to connect via IMAP.
You will need to be granted permissions for IMAP access by the admin of your tenant.
Need to give shared mailbox permissions to OAuth app as well and shared mailbox will be accessible.

How to configure an app in azure portal for multiple email addresses, from the same O365 tenant, to use OAuth with SMTP without user interaction?

We use in our company email addresses for each employee and for 3 departments (service, support and reports) - for example <employee_name>#<company_name>.de or support#<company_name>.de ("<..._name>" is just a placholder for posting here). Our programs use PHPMailer for sending Emails from the 3 departments via SMTP without user interaction (Host: smtp.office365.com), that means the PHPMailer is called by programs/scripts that are started by the Microsoft Task Scheduler on a computer where none of our Microsoft-Users is logged in. Now we want to switch from Basic SMTP Auth to Oauth2.
So we registered in the main tenant (<boss_name>#<company_name>.de) in the azure portal a web app "PHPMailer" and received the refresh token with the file "get_oauth_token.php", which is included in PHPMailer. The mail order via OAuth is working now, but only when <boss_name>#<company_name>.de is the username and the email sender (From).
It's not working when both are for example reports#<company_name>.de (prefered way)
SMTP INBOUND: "535 5.7.3 Authentication unsuccessful [AM6PR10CA0036.EURPRD10.PROD.OUTLOOK.COM]"
And it's not working when <boss_name>#<company_name>.de is the username and From is for example reports#<company_name>.de (willy-nilly compromise)
SMTP INBOUND: "554 5.2.252 SendAsDenied; <boss_name>#<company_name>.de not allowed to send as reports#<company_name>.de
We tried to change the configuration for <boss_name>#<company_name>.de ("SendAs" parameter) and of the app in the azure portal (for example defining the department email addresses as owner of the app or adding Mail.Send in the Micrsoft Graph API as application permission) and waited 24 hours (synchronization delay) - but no change.
So i've read in the past weeks countless tutorials from Microsoft, PHPMailer and others, and forums like stackoverflow. But nowhere i could find the necessary information, how to change the configuration.
Examples:
Microsoft
Give mailbox permissions to another Microsoft 365 user - Admin help
Authenticate an IMAP, POP or SMTP connection using OAuth
Get access on behalf of a user
PHPMailer
Using Gmail with XOAUTH2 (unfortunately no explanation for Microsoft)
Basic Usage of the OAuth 2.0 Client from the PHP League
Microsoft Provider for OAuth 2.0 Client Microsoft OAuth 2.0 support for PHPMailer from Steven Maguire
But in this answer to my older question #ADyson wrote that the app just needs the appropriate permissions in the Graph API - so it must be possible. Unfortunately he didn't write, how to set the permissions...
So, how can i achieve my goal?
(Because the PHPMailer is working and i think it's just a configuration problem, i omitted code snippets. If you although need code or more information, please tell me...)
Update:
PHPMailer
Thanks to #greew i found a well made explanation with helpfull screenshots for delegated permissions:
Microsoft Azure and XOAUTH2 setup guide
Unfortunately it doesn't help for my case with application permissions, because it is made for the case, that the Microsoft user is logged in on the compauter where PHPMailer is working.
Not supported?
I found in the Microsoft page Authenticate an IMAP, POP or SMTP connection using OAuth the following hint:
Note As per the current test with SMTP Oauth 2.0 client credential flow with non-interactive sign in is not supported.
Does this mean, that i'm trying it for nothing, because it is not supported???
#biberman
I just tried setting up a new mailer with the correct permissions and also clicking the "Grant admin consent.." button.
This resulted in me being able to both get the refresh token and also send mail without user interaction on my behalf.
Note: I'm using the single tenant option in the App.
After i found in the Microsoft page Authenticate an IMAP, POP or SMTP connection using OAuth the following hint:
Note As per the current test with SMTP Oauth 2.0 client credential flow with non-interactive sign in is not supported.
i asked the same question in the Microsoft Q&A forum. There i received the following answer/comment:
Currently the Client Credentials flow isn't supported with SMTP Auth (it maybe in the future but there isn't a roadmap item that i know of) so you need to grant SendAS permissions to whatever account you trying to send as in the from or switch to using the Graph API eg one example https://katystech.blog/projects/php-graph-mailer that does support the client credentials flow.
I tried to solve the issue by letting the administrator grant the SendAs permission to all necessary mailboxes, but i still get the error SendAsDenied - maybe it doesn't work with modern authentication (OAuth).
At the end i used the graphMailer from the linked katystech.blog, which is a really slim solution compared to the PHPMailer. First i couldn't get it to work, because our administrator refused to grant the necessary Microsoft Graph permission Mail.ReadWrite (he has security concerns). But i changed the code, so that the email is "build" before sending it, instead of building the email step by step on the Microsoft server and then advising the server to send it (like in the original code).
Now the Mail.ReadWrite permission isn't necessary and i can send from different email addresses. To avoid rewriting the whole code, where the PHPMailer is used, i renamed the functions of Katys graphMailer (and adjusted the params), so that they are similar to the PHPMailer and i only need to replace = new PHPMailer( with = new graphMailer(...

Cannot authenticate to IMAP on office365 using JavaMail

We are trying to connect a javamail (1.6) client to our office365 mailbox hosted on office365 using OAUTH2 authentication.
No matter what we do, we keep getting A1 NO AUTHENTICATE failed.
We have registered our application with
API Permission
we followed all instructions stated at
https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth
including running the powershell commands to create the principal using the app id and object id, and we granted the app full access to emailbox we want to access.
For authentication we do an HTTP POST as following which generates an access token
This is a client credentials flow with shared secret as explained here
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
https://login.microsoftonline.com/{our tenant id}/oauth2/v2.0/token
with
client_id=...
client_secret=...
grant_type=client_credentials
scope=https://outlook.office365.com/.default
our javamail configuration
mail.store.protocol="imap"
mail.imap.host="outlook.office365.com"
mail.imap.port="993"
mail.imap.ssl.enable="true"
mail.imap.starttls.enable="true"
mail.imap.auth="true"
mail.imap.auth.mechanisms="XOAUTH2"
mail.imap.user="<email box>"
then in our java code we connect the store with the access token obtained from the above HTTP POST
store.connect(host, user, oauth2_access_token);
We also tried this powershell script, which returns the same error
https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1
I do not believe that problem is specific to JavaMail.
It is extremely difficult to determine if an access token has the correct rights or there is something else that prevents the authentication
What else can we try?
Update 1
If we use the powershell script
https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1
passing only the client id and the redirectUri the script prompts me for approval and it succeeds
but if we use clientsecret authorization fails
Update 2
I can successfully use javamail with the access token generated by the powershell script.
Clearly the token created with the clientsecret does not have enough rights to access IMAP or the mailbox
I start to wonder if token requests using client secret do not work because our Azure Active Directory has "security defaults" enabled.
May be MFA is enforced therefore any non-interactive requests are blocked
Update 3
https://jwt.ms allows to decode access tokens
The token created with just the clientid (code grant flow) is very different from the one created with the client_secret (client credentials flow).
In token from "code grant interactive" there is an attribute called "scp" Set of Scopes, which lists scopes regardless of what I have in my client app API permission ????
"scp": "IMAP.AccessAsUser.All Mail.Read Mail.Read.All Mail.Read.Shared Mail.ReadBasic User.Read"
The second token from the client credentials flow, has an attribute "roles", but does not have scopes
"roles": ["IMAP.AccessAsApp"]
RESOLVED!
looking at the access token we noticed that the client credentials flow subject (sub) was an id that we did not setup.
Here is the catch: when creating the service principal using powershell in exchange online, for serviceid you have to use the objectid of the enterprise application.
New-ServicePrincipal -AppId {clientid} -ServiceId {enterprise application objectid} -Organization {tenantid}
When creating an app registration Azure AD, you also create an enterprise application
The application object id is different from enterprise application object id.
The client credentials flow uses the enterprise application object id as the user asking for authorization.
The same for granting access to the mailbox using powershell
Add-MailboxPermission -Identity {email} -User -ServiceId {enterprise application objectid} -AccessRights FullAccess
it is unfortunate that the authentication process is so cumbersome
My two cents on this , if you are still facing authentication failure from javamail trying to connect to mailbox and read emails, First and foremost make sure the application setup in azure active directory has below permissions.
IMAP.AccessAsApp
Mail.Read
Mail.Send (For Sending)
Secondly, Create service principal with the enterprise application id as mentioned in the original post.
Once done check here if your generated token has all the roles you have assigned.
Even if you assigned necessary roles and you can able to connect to mailbox via powershell still you might get AUTHENTICATE failed from javamail because you might be using this property (mail.imap.auth.mechanisms) wrongly , replace mail.imap with mail.imaps and it should solve the problem.
"mail.imaps.auth.mechanisms"="XOAUTH2"
"mail.imap.host"="outlookoffice365.com"
"mail.smtp.port"=993
"mail.store.protocol"="imaps"
session.getStore("imaps")
store.connect(host,port,user,token)
Good luck !!

Send mail via Microsoft Graph as Application (Any User)

We recently migrated from on premise exchange to Microsoft 365 and I'm wanting to turn on 2FA for all users (Enable security defaults). However this disables SMTP authentication which we have been using for sending mail from a distribution group address. (Not achievable via EWS as it doesn't have a physical mailbox)
From what I can see, the only method would be to set up a SMTP relay or send via Microsoft Graph.
I've tried going down the Microsoft Graph route, and here's what I've got so far.
Create application in Azure Active Directory > App Registrations
Add Mail.Send and User.Read.All (Application, not delegated) API Permissions and have granted Admin Consent.
Request token using the following
Generate auth code via https://login.microsoftonline.com/{AzureApi.TenantId}/oauth2/v2.0/authorize?response_type=code&client_id={AzureApi.ClientId}&redirect_uri={WebUtility.UrlEncode(RedirectUrl)}&scope=offline_access%20Mail.Send%20User.Read.All [using admin credentials]
Post request to https://login.microsoftonline.com/{AzureApi.TenantId}/oauth2/v2.0/token with the following request body.
{ "grant_type": "authorization_code", "client_id": "AzureApi.ClientId", "client_secret": "AzureApi.ClientSecret", "code": "insert auth code", "redirect_uri": "insert redirect URL" } to get the bearer token
Once I have the token, Now I perform a request to send some mail
https://graph.microsoft.com/v1.0/users/{fromAddress}/sendMail
This works when fromAddress is the email address of the user that requested the token, however when I try to send from a different address it gives this error {"error":{"code":"ErrorAccessDenied","message":"Access is denied. Check credentials and try again."}}
I even tried adding the SendAs permission to the token user for the mailbox I was trying to send as, but this didn't make any difference. Regardless - I want to be able to send as any user without delegating permissions to each mailbox.
Glad of any help. Thanks!!
The behavior you are getting is expected because you are using delegated permissions - authorization code flow. This flow will not allow your app to send email as any user except the user that is signed in/"requested the token".
In your case you can add the permissions as application permissions and then use Client Credentials flow with either secret or certificate(more secure). Your token request will look like the Get Access Token Section. Note that this means two things:
Your app will need to be secured on server side to protect the credentials.
An admin will need to consent to the permissions on Azure AD
Your app will be able to send emails as any user in your tenant so it is very sensitive.
With application permissions you only need Mail.Send

Microsoft Graph API status code 404 not found error

I am new to Azure and Microsoft Graph API.
I am trying to access: https://graph.microsoft.com/v1.0/me/messages
and I am getting a `404 Not Found.
I took the access token and decrypted in JWT and I can see the access token contains my name and credentials and the scopes defined are :
Directory.AccessAsUser.All Directory.Read.All email Files.ReadWrite Group.Read.All Mail.Send offline_access openid profil.Read
Can someone please suggest why I am getting a bad request?
In order to list (read) the mail messages (as described here) you need the Mail.Read or Mail.ReadWrite (if you also want to write messages) permission (scope).
With respect to mailing functionality you only have requested (or granted?) Mail.Send permission which only allows you send message (as described here).
The email claim is OpenID Connect specific claim and provides the logged-in user's email as claim. It has nothing to do with Exchange Online and sending/receiving e-mails.

Resources