javax.mail.AuthenticationFailedException: AUTHENTICATE failed.

Samir Dridi 0 Reputation points
2023-09-12T11:09:33.28+00:00

I´m trying to connect to my mailbox thru a java app but get AUTHENTICATE failed. i have setup the app registriation and also ran the powershell commands to set up service principal and mailbox permission.

What am i missing?

see code below

package app.comflow.interchange.mail.applobj;

	import java.io.IOException;
	import java.io.InputStream;
	import java.security.GeneralSecurityException;
	import java.text.ParseException;
	import java.text.SimpleDateFormat;
	import java.util.Date;
	import java.util.Map;
	import java.util.Properties;

	import javax.mail.Folder;
	import javax.mail.MessagingException;
	import javax.mail.NoSuchProviderException;
	import javax.mail.Session;
	import javax.mail.Store;

	import org.apache.commons.io.IOUtils;
	import org.apache.http.client.methods.CloseableHttpResponse;
	import org.apache.http.client.methods.HttpPost;
	import org.apache.http.entity.StringEntity;
	import org.apache.http.impl.client.CloseableHttpClient;
	import org.apache.http.impl.client.HttpClients;
	import org.apache.http.message.BasicHeader;

	import com.fasterxml.jackson.databind.JavaType;
	import com.fasterxml.jackson.databind.ObjectMapper;
	import com.sun.mail.util.MailSSLSocketFactory;

	public class Oauth2MailTest {

		public static void main(String[] args) {

// Ikea			String tenantId = "hidden";
			String tenantId = "hidden";
						
// Ikea			String clientId = "hidden";
			String clientId = "hidden";
			
// Ikea			String client_secret = "hidden";
			String client_secret = "Hidden";
// Ikea			String username = "hidden";
			String username = "Hidden";
// ikea		String password = "Hidden";
			String password = "";
//			String host = "login.microsoftonline.com";
			String host = "outlook.office365.com";
//			String mailHost = "inter-ikea-com.mail.protection.outlook.com";
			String mailHost = "outlook.office365.com";
// ikea			String mailAddress = "hidden";
			String mailAddress = "hidden";
			CloseableHttpClient client = HttpClients.createDefault();
			HttpPost loginPost = new HttpPost("https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token");
			String scopes = "https://outlook.office365.com/.default";		
//			String scopes = "https://outlook.office365.com/IMAP.AccessAsUser.All";
			
//			String scopes = "https://outlook.office.com/IMAP.AccessAsUser.All";
//			String scopes = "https://outlook.office.com/IMAP.AccessAsApp";
			String encodedBody =  "grant_type=client_credentials&client_id=" + clientId + "&client_secret=" + client_secret + "&scope=" + scopes;
			loginPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
			loginPost.setEntity(new StringEntity(encodedBody, "UTF-8"));
			loginPost.addHeader("Accept-Encoding", "UTF-8");
			loginPost.addHeader(new BasicHeader("cache-control", "no-cache"));

			try {
			CloseableHttpResponse loginResponse = client.execute(loginPost);
			
			InputStream inputStream = loginResponse.getEntity().getContent();
			byte[] response = IOUtils.toByteArray(inputStream);
			System.out.println(new String(response));
			ObjectMapper objectMapper = new ObjectMapper();
			JavaType type = objectMapper.constructType(objectMapper.getTypeFactory().constructParametricType(Map.class, String.class, String.class));
			
			Map
Exchange Online
Exchange Online
A Microsoft email and calendaring hosted service.
6,171 questions
Microsoft 365 and Office Office Online Server
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Shweta Mathur 30,296 Reputation points Microsoft Employee Moderator
    2023-09-12T12:53:58.4133333+00:00

    Hi @Samir Dridi ,

    Thanks for reaching out.

    For client credentials flow, you need to add application permissions under Office 365 Exchange Online

    User's image

    Make sure to grant admin consent for all the application permissions.

    Once consent has been provided, the admin must register your AAD application's service principal in Exchange using powerShell by following commands:

    Install ExchangeOnlineManagement

    Install-Module -Name ExchangeOnlineManagement -allowprerelease Import-module ExchangeOnlineManagement Connect-ExchangeOnline -Organization

    Register Service Principal in Exchange:

    1.New-ServicePrincipal -AppId <APPLICATION_ID> -ServiceId <OBJECT_ID> [-Organization <ORGANIZATION_ID>]

    Make sure to use ObjectId from enterprise applications rather than object id of application registration**.**
    For the same application you registered in Application Registration. A corresponding application has been created in Enterprise Application as well. You need to pass object id from there while registering service principal in Exchange:

    User's image

    2.Get-ServicePrincipal | fl

    3.Add-MailboxPermission -Identity "******@contoso.com" -User <SERVICE_PRINCIPAL_ID> -AccessRights FullAccess

    In the application, you need to use scope = 'https://outlook.office365.com/.default '

    Once you will get the access token, you can create and open a Java Mail connection to read mails.

    Properties props = new Properties();
    
    props.put("mail.store.protocol", "imap");
    props.put("mail.imap.host", "outlook.office365.com");
    props.put("mail.imap.port", "993");
    props.put("mail.imap.ssl.enable", "true");
    props.put("mail.imap.starttls.enable", "true");
    props.put("mail.imap.auth", "true");
    props.put("mail.imap.auth.mechanisms", "XOAUTH2");
    props.put("mail.imap.user", mailAddress);
    props.put("mail.debug", "true");
    props.put("mail.debug.auth", "true");
    
    // open mailbox....
    String token = getAuthToken(tanantId,clientId,client_secret);
    Session session = Session.getInstance(props);
    session.setDebug(true);
    Store store = session.getStore("imap");
    store.connect("outlook.office365.com", mailAddress, token);
    
    
    

    Hope this will help.

    Thanks,

    Shweta


    Please remember to "Accept Answer" if answer helped you.


  2. Samir Dridi 0 Reputation points
    2023-09-13T12:07:00.16+00:00

    Yes, object id is from Enterprise applications and not app registration.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.