401 error when trying to connect to EWS with Oauth2 access token

Hello,

I’m trying to download e-mails from ews using the Java EWSClient and Oauth2. I implemented the ROPCTokenProvider with authenticates against Microsoft Graph using a certificate. The TokenProvider runs without an exception and returns and oAuthToken. But as soon as EWSClient.getEWSClient is called, I receive an 401 not authorized error.

Here is a simplified snippet:

ITokenProvider tokenProvider = new AzureROPCTokenProviderCertificate(“tenant-id”, “client-id”, “path_to_cert”, “cert_pw”);
OAuthNetworkCredential credentials = new OAuthNetworkCredential(tokenProvider);
EWSClient.useSAAJAPI(true);
IEWSClient client = EWSClient.getEWSClient(“https://outlook.office365.com/EWS/Exchange.asmx”,credentials);

My TokenProvider-Class:
import com.aspose.email.<em>;
import com.microsoft.aad.msal4j.</em>;
import [java.io](http://java.io/).*;
import java.util.Collections;
import java.util.Set;

public class AzureROPCTokenProviderCertificate implements ITokenProvider
{
private String _authrority = “”;
private String _tenant = “”;
private String _clientId = “”;
private String _certificateFullPath = “”;
private String _certPassword = “”;
private Set _scopes = Collections.singleton(“https://outlook.office365.com/.default”);
private OAuthToken _token = null;


   public AzureROPCTokenProviderCertificate(String tenant, String clientId, String certificateFullPath, String certPassword)
{
    this._tenant = tenant;
    this._clientId = clientId;
    this._authrority = "https://login.microsoftonline.com/" + this._tenant + "";
    this._certificateFullPath = certificateFullPath;
    this._certPassword = certPassword;    	
}

public OAuthToken acquireToken() throws Exception {

	if(this._token == null) {
    	IClientCredential credential = ClientCredentialFactory.createFromCertificate(new FileInputStream(this._certificateFullPath), this._certPassword);
        ConfidentialClientApplication cca =
                ConfidentialClientApplication
                        .builder(this._clientId, credential)
                        .authority(this._authrority)
                        .build();	                        
          
        IAuthenticationResult result;	        
		ClientCredentialParameters parameters =
		ClientCredentialParameters
						 .builder(this._scopes)	                             
						 .build();
		result = cca.acquireToken(parameters).join();
       
        System.out.println(result.accessToken());			
		this._token = new OAuthToken(
		    	result.accessToken(),
		        TokenType.AccessToken,
		        result.expiresOnDate());	        
	}
	return this._token;	 
}    

@Override
public void dispose() {
	// TODO Auto-generated method stub		
}

@Override
public OAuthToken getAccessToken(){
	try{
		return this.acquireToken();
	} 
	catch (Exception e) {
		e.printStackTrace();
        return null;
    }
}

@Override
public OAuthToken getAccessToken(boolean arg0) {
	try{
		return this.acquireToken();
	} 
	catch (Exception e) {
		e.printStackTrace();
        return null;
    }
}
}

The application has the following permissions (of the type application) in Azure:
Mail.ReadWrite
Mail.Send
User.Read.All

I’m using the Aspose Java E-Mail Library 21.1 (unlicensed for testing puroses).

What could be the cause for the 401 error?

@Stephan_Klinkert,
Welcome to our community! Thank you for the issue description. To my regret, we cannot reproduce the problem. Could you please share a comprehensive standalone project for investigation?

@ Andrey_Potapov
Thank you for your help! I attached a simple project, but I can’t include the certificate or any other credentials and ID due to our company’s security policies.AsposeAzureEWSWithCert.zip (3.5 MB)

@Stephan_Klinkert,
Thank you for the project sample. I have logged the issue in our tracking system with ID EMAILJAVA-34837 for further investigation. I will notify you about any progress.

@Stephan_Klinkert,
Our development team investigated the issue. The problem is related to Azure administration.

You should enable full_access_as_app permission the next way:

  • Navigate to Application/Manage/API permissions in Azure and click on Add a permission.
  • Select “APIs my organization uses” tab and search for “Office 365 Exchange Online” image1.png (24.1 KB).
  • Select “Application permissions” and enable “full_access_as_app” image2.png (46.7 KB).

Also, you should specify impersonation for your application as below:

OAuthNetworkCredential credentials = new OAuthNetworkCredential(tokenProvider);
credentials.setUserName("yourImpersonationSmtpAddress");

More details:
Authenticate an EWS application by using OAuth
Exchange API permissions missing

Thank you for help. As soon as my customer has made the changes in Azure, I 'm going to test it again and give you feedback.

image.png (39.4 KB)

@ Andrey_Potapov
Hello,

sadly, I still receive the response 401 from Azure. I attached a screenshot with the settings my client made in Azure. Is there something missing? Thank you!

@Stephan_Klinkert,
Thank you for your feedback. Our development team will continue to investigate this case.

@Stephan_Klinkert,
You should add the “Office 365 Exchange Online”/full_access_as_app permission as described in my answer above.

@ Andrey_Potapov

The permission have been finally set and everything is working now. Thank you for your support!