i am always getting authentication failed error while i am logging my outlook account through imap in nodejs but i am getting bearer token from @azure/msal-node package and i am using scopes: ['https://graph.microsoft.com/.default']

Madhvi Bansal 0 Reputation points
2023-03-02T11:20:27.6066667+00:00
This is my code for fetching access token and set to header

const msal = require('@azure/msal-node');

const msalConfig = {
  auth: {
    clientId: '2f6cbac9################881595',
    authority:
      'https://login.microsoftonline.com/f8cdef3#######################91255a', //tenantID
    clientSecret: 'fk####################'
  }
};
const tokenRequest = {
 scopes: ['https://graph.microsoft.com/.default']
};

async function getToken(tokenRequest) {
  const cca = await new msal.ConfidentialClientApplication(msalConfig);
  const authResponse = await cca.acquireTokenByClientCredential(tokenRequest);
  return authResponse;
}

exports.main = async (req, res, next) => {
  try {
    const authResponse = await getToken(tokenRequest);
    req.headers['auth'] = authResponse.accessToken
    console.log(authResponse.accessToken)
    next();
  } catch (error) {
    console.log('Error getting token:', error);
  }
};

And below is my code for access token in my imap server

const Imap = require('imap'); inspect = require('util').inspect; const {simpleParser} = require('mailparser');

function connectToImapServer(auth2) { const imap = new Imap({

user: 'm####@gmail.com',
xoauth2:auth2,
host: 'outlook.office365.com',
port: 993,
tls: true,
debug: console.log,
authTimeout: 25000,
connTimeout: 30000,
tlsOptions: {
  rejectUnauthorized: false
}});
 function openInbox(cb) {
imap.openBox('INBOX', true, cb);
}
imap.once('ready', () => {
imap.openBox('INBOX', false, () => {
imap.search(['ALL'], (err, results) => {
const f = imap.fetch(results, {bodies: ''});
f.on('message', msg => {
msg.on('body', stream => {
simpleParser(stream, async (err, parsed) => {
  console.log("html======================================",parsed.text,parsed.subject,parsed.to.text,parsed.from.text)
        });
       });
msg.once('attributes', attrs => {
const {uid} = attrs;
imap.addFlags(uid, ['\\Seen'], () => {
console.log('Marked as read!');
});
});
});
f.once('error', ex => {
return Promise.reject(ex);
});
f.once('end', () => {
console.log('Done fetching all messages!');
imap.end();
});
});
});
});
imap.once('error', function (err) 
console.log(err);
 })
imap.once('end', function () 
console.log('Connection ended');
 });
 imap.connect();
}
exports.getAttachments = async (req, res) => {

  const mailId = 'm#######@gmail.com';

  const token = req.header['auth'] // get token from headers

  const auth2 = Buffer.from([user=${mailId}, accessToken=${token}]).toString('base64');

  connectToImapServer(auth2);

}

I am always getting authentication failed even i enabled mail.read in azure portal
now i am getting error

= '* OK The Microsoft Exchange IMAP4 service is ready. [UABOADMAUABSADAAMQBDAEEAMAAxADIANAAuAEkATgBEAFAAUgBEADAAMQAuAFAAUgBPAEQALgBPAFUAVABMAE8ATwBLAC4AQwBPAE0A]'
=> 'A0 CAPABILITY'
<= '* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+'
<= 'A0 OK CAPABILITY completed.'
=> 'A1 AUTHENTICATE XOAUTH2 AAA='
<= 'A1 NO AUTHENTICATE failed.'
Error: AUTHENTICATE failed.
    at Connection._resTagged (C:\toxsl\node_modules\imap\lib\Connection.js:1502:11)
    at Parser.
Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
10,522 questions
Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
19,392 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Shweta Mathur 27,216 Reputation points Microsoft Employee
    2023-03-03T08:39:38.9866667+00:00

    Hi @Madhvi Bansal ,

    Thanks for reaching out.

    As you are using client credential flow to authenticate an IMAP connection using OAuth, then you need to add application permissions under Office 365 Exchange Online

    [enter image description here

    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: [enter image description here

    2.Get-ServicePrincipal | fl

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

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

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

    Reference: https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#use-client-credentials-grant-flow-to-authenticate-imap-and-pop-connections

    Hope this will help.

    Thanks,

    Shweta

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

    0 comments No comments