mscdex / node-imap

An IMAP client module for node.js.
MIT License
2.17k stars 382 forks source link

Authentication failed for microsoft account #865

Closed azamsolix closed 2 years ago

azamsolix commented 2 years ago

Hi, I am trying to base64 encode token and pass it to imap .Below is the sample code .However,I am getting accessToken and i am passing it to imap and it is returning authentication failed. scopes scope:[ 'openid', 'offline_access', 'https://graph.microsoft.com/mail.read', "https://graph.microsoft.com/IMAP.AccessAsUser.All" ]

//here i am getting access and refresh token const accessToken = await client.getToken(tokenParams); console.log('accesstoken', accessToken, accessToken.token.access_token); let USER = 'userrrrr@hotmail.com'; let token=Buffer.from("user=ssfsfbfs2021@hotmail.com" + "^Aauth=Bearer " + accessToken.token.access_token + "^A^A").toString('base64'); console.log('ans', token) let Imap = require('imap');

         var imap = new Imap({
        xoauth2 :token,
    host: 'outlook.office365.com',
    port: 993,
    tls: true,
    authTimeout: 3000,
tlsOptions: { rejectUnauthorized: false }

}); imap.connect(); imap.once('ready', function() {

//   }
});     

imap.once('end', function() { console.log('Connection ended'); // res.redirect('/name'); }); But still it is returning authentication failed Please,help me with this.Waiting for your reply Thanks Azam

mscdex commented 2 years ago

The ^A is not supposed to be used literally, it should be replaced with the associated value which has a hex value of 1. To insert that character you will need to use the escape sequence \x01 inside a JavaScript string.

mscdex commented 2 years ago

Also on an unrelated note, you should never use rejectUnauthorized: false as it is a security issue that opens you up to MITM attacks.

azamsolix commented 2 years ago

Thank you for your quick response sir. I have tried replacing^A with \x01 Buffer.from("user=sathyakrishna2021@hotmail.com" + "\x01Aauth=Bearer " + accessToken.token.access_token + "\x01\x01").toString('base64');

But still i am getting same error. Below is the error.

[connection] Connected to host <= ' OK The Microsoft Exchange IMAP4 service is ready. [QgBNADEAUABSADAAMQBDAEEAMAAwADkAMwAuAEkATgBEAFAAUgBEADAAMQAuAFAAUgBPAEQALgBPAFUAVABMAE8ATwBLAC4AQwBPAE0A]' => '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 dXNlcj1zYXRoeOHMENZL3c4NlE0VG5OY3VOVSs5a2s5cHNkQ2pTbnBZdkZCb3VkeldCMmVxbFFHWjE0Ujh4c2lYcFZ5VmpRRWFpZkRzQkxSUURoZnF6Sll5NEtQYkhITFFUYVN6aWE5SE9HWkROYnBIN3Q0SGVvVDRjU2plYmpoRTZHRGhHSmYxSnVMVEhjbXo2TGQvbWdyb21WRS9NQldmb3dsQy9xWG1pTFA5UHRTT29MU0MrS3BvZnZ1Mmlqa1kzaGpDdFJMT0tNUUY4MWRtNGZQbGwxeElLc1cxakN3UVV0anJpTnpHTWtOMTdOUU4wU2M5a1FvNms2dEFLcXBhUHY4WDRtUDU5Rk9aYlhNbWMxanQwWGthRlc3eDdhYmFoRW40M2tBekw5R1ZERWl1azZ5aEJuL3E5dUxUQXhNT2lNdE1JRkJ3eFU0TTFQWWFOdk5NMGdQSmxVR1hWRzI3S2dYUlE0SEdDa3BWRjJJQ2l2RWdkSll0S1JRenNscDBhYmRzaE1qVFJ2VlFiZVlQb1lPWG5uREhzMklxRkNTTUw4SlN4TUVpUk9OdGxidE9UMWFkVWE4QWJTdVF3TUI3cFJoSTJYSExJYW5KNkF1UkNqSU9keVpVU0F3b2gvb01aWmVwYUU2OHNPVE1kMWJLTTRTVEExeWZYOFA1aGkrVDJPSll1dmdIcW5jV0ZnekhJNDliWU1LQ2t3aFBLQnY3ajdwUkYvend2aXgycHlFcmEwZldRRWpiaHp2RmFzVVBVTkdrMUVlaDFNLy9oVVplU1I5aTYxaTZnRXlCUmxIY3BoYzk4MS9acyttRENQWjdqcHJqbGlQVUFRcjFuVFJDM3JTL25wZ3pYQVBDRDRjM1JSTTVWN3Z0RWZoQUk9AQE=' <= 'A1 NO AUTHENTICATE failed.' events.js:377 throw er; // Unhandled 'error' event ^

Thanks Azam Ahmed

mscdex commented 2 years ago

You still have a typo: \x01Aauth should be \x01auth

azamsolix commented 2 years ago

This is the complete source code sample for you reference sir.

const app = require('express')();
var cors = require('cors');
var bodyParser = require('body-parser');
app.use(cors());
app.use(bodyParser.json());

const { ClientCredentials, ResourceOwnerPassword, AuthorizationCode } = require('simple-oauth2');
const { Base64Encode } = require('base64-stream');
app.get('/callback', async function (req, res) {
     let credentials = {
  client: {
     id: "id",
      secret: "secret",   
  },
    auth: {
        tokenHost: 'https://login.live.com',
        tokenPath: '/oauth20_token.srf',
        authorizePath: '/oauth20_authorize.srf',
      }
    };
    const client = new AuthorizationCode(credentials);
    console.log('code', req.query);
     const tokenParams = {
    code: req.query.code,
    redirect_uri: 'http://localhost:3000/callback',
    scope:[
    'openid',
    'offline_access',
        'https://graph.microsoft.com/mail.read',
    "https://graph.microsoft.com/IMAP.AccessAsUser.All"
  ],
  };

  try {
      const accessToken = await client.getToken(tokenParams);
      console.log('accesstoken', accessToken, accessToken.token.access_token);
      let USER = 'email@hotmail.com';
            let token=Buffer.from("user=sathyakrishna2021@hotmail.com" + "\x01Aauth=Bearer " + accessToken.token.access_token + "\x01\x01").toString('base64');

      console.log('ans', token)
      let Imap = require('imap');

             var imap = new Imap({
            xoauth2 :token,
        host: 'outlook.office365.com',
        port: 993,
        tls: true,
        authTimeout: 3000,
    tlsOptions: { rejectUnauthorized: false }
});
imap.connect();
imap.once('ready', function() {

    //   }
    });     
   imap.once('end', function() {
            console.log('Connection ended');
            // res.redirect('/name');
});          
  } catch (error) {
    console.log('Access Token Error', error);
  }
});
app.get('/auth', async function (req, res) {

    let credentials = {
  client: {
     id: "id",
      secret: "secret",   
  },
    auth: {
        tokenHost: 'https://login.live.com',
        tokenPath: '/oauth20_token.srf',
        authorizePath: '/oauth20_authorize.srf',
      },
      options: {
      authorizationMethod: 'body',
    }
    };
    const client = new AuthorizationCode(credentials);

   const authorizationUri = client.authorizeURL({
    redirect_uri: 'http://localhost:3000/callback',
    scope:  [
    'openid',
    'offline_access',
        'https://graph.microsoft.com/mail.read',
        'profile',
    "https://graph.microsoft.com/IMAP.AccessAsUser.All"
  ],
    state: 'sfgsf'
  });
    console.log('aaaa,', authorizationUri);
    res.redirect(authorizationUri)
})

app.listen(3000, function() {
  console.log(`Express server started on  http://localhost:3000`);
});
azamsolix commented 2 years ago

Sir, i fixed the typo and tested but still returning same authentication issue Connected to host <= ' OK The Microsoft Exchange IMAP4 service is ready. [QgBNAFgAUABSADAAMQBDAEEAMAAwADAANAAuAEkATgBEAFAAUgBEADAAMQAuAFAAUgBPAEQALgBPAFUAVABMAE8ATwBLAC4AQwBPAE0A]' => '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 dXNlcj1zYXRoeWFrcmlzaG5hMjAyMUBob3RtYWlsLmNvbQFhdXRoPUJlYXJlciBFd0JvQThsNkJBQVV3aWhyckNybVE0d3VJSlg1bWJqN3JRbGE2VFVBQWVwbStzbGNUV3JJdFE3MWtRVWo3L0xtNEhPMmdmd25oMWxBME1ySjZ1M0ZRWC9YTmlFSEhNZzNkUW8xc0ZQdk42MUNCMHFka2pvQzJuMVgwUkRsYklyWXZnZ1Y4LzI5SzhtbGpUZ3VnUUdrRG95cUtFV3JDdGRHMU5XWFJzY29SYW5FZ2t4S0gyOGFrSTRDNFhxRHA5a1lVZ1h3WFhMK3gva0o5OENiZ0hNcGZrVnJDK1VrSlBUSzQrR1AremNsTXBpQzdRbmFzTkh2WHNwUTdSVEwzdTBMakhaYmRwWVVXYjNrbzhnZ0NQaU1weGJyTCtQYjM0azlRN1JYUTkxME1XSzVyV1hHMmM5d3BFV3ZxSWFGYldGMlJIVjhWcE9YNVZKZUN0WFVRNlROczhGUnVVMWxKekFYWk95dUNzWVh3Uml3ZEpSV1FwdzU0Zm5pTkZiMm4zVURaZ0FBQ0pwVUtoSWZ2eEJsT0FLT3A0dGtyendrRmZYR0ZJYjlkd2IxUGZnaUt3djRibFNXdUhGWjRhU1FnNjZYWk9VbENoMUJHdU1mb2dJY0lxV3ZmR25EaUhkb2lsWm9Ccm9UWnZnZnlwREw0OW8yN0ZleloyMVhFNHE4SUNsMTdNSmlWNk1zK2laRGVMa3BDU1VORER6dlAxMkRNaHRCMTNaUEp1Qm9TOHlwYUJlU2R6YmJsWm5XZFFPUkNFY010enArUmdlSyt1YlNpUmJhdU5yT244V0tKeUJnZUMwM0xYdDNNUHJXTkZ6SU5rVXdFRU1weTBQYUNGUkx5QitCdmFTbzd1RkJEQUFzNjkxRVJKRjJzWUlIMTZ4eWF0elRBWEpPQklmSW43R3JLbzR6NEFSZ3ZPSG1HdTNRZUc5NWlmSUZjNnVMMlJETi9uek1WWnJvM3luWXRxOXRIU3Q2UmdIUTV1ZnZXZW1GN0V0WE9weGQ2dkJybTZmQldpdWxOaE13NGV3Ni83T2VPRGZuR1krdEc2YldXQUZGZWJpeGl5S2FrUWdsa25oaVBWa1JteTBybm5Ca1VVOU8xNndxZy9NdTkyN3FUVU13Q042T0VyRSt0UWg2bEZHb1c1WVFSRUdkbjA5SUlqdnB0ZkhFcHltQkdkTE5IVGpPc0lCa0VoeDBxTDZlOG9LUURUYTc0NnRSaXNOUmVuenpDUlI3enJobVhwM0pXYitDTW5EQlJiT2RXdzNEdXhnd0NuSXNoTU5RRTJQNFhuVE54QTF5clc2aHpqaVFTK29hT0YwSjZTWGN4bk8wclZzOURrajlTNk9hOTdBcEZ2RGNHekE4enhXa3B5YVFIdFpsU1hSL28wWTZzaml3MUcybndiWnA1TDZJT0kwLzFYMU1kQUgvUm5oSVZQTENsYUtmc2YzYlB2UEw1UUpMU1p4MmhRWmc0UUZlUU5wK2prdmNUODdlY2Q0L3NDTmcxeHI3d3hPL3JsMlk0LzZoY0Z5MjJiWFJJeHczbWo0Z2hBST0BAQ==' <= 'A1 NO AUTHENTICATE failed.' events.js:377 throw er; // Unhandled 'error' event ^

Error: AUTHENTICATE failed. Thanks for helping, Azam

mscdex commented 2 years ago

I would double check your scopes as a brief google search (and Microsoft's own documentation) reveals they should be using outlook.office.com and not graph.microsoft.com, at least for IMAP scopes.

azamsolix commented 2 years ago

Sir,I have checked and found outlook.office.com is depreaceated https://docs.microsoft.com/en-us/previous-versions/office/office-365-api/api/version-2.0/use-outlook-rest-api and sir there is no outlook.office.com scope available. for you reference check this link sir. it shows how to register app in microsoft and add scopes to it. https://docs.emailengine.app/setting-up-oauth2-with-outlook/ Thanks Azam

mscdex commented 2 years ago

I don't know what to tell you then as this issue is beyond the scope of this module. You just have to figure out what is wrong with the token or account you're trying to use. Your passing of the token value to imap is correct though, so once you get the token sorted out, you should be able to log in properly.

andris9 commented 2 years ago

If anyone ends up here looking for a solution for Outlook OAuth2 scopes, then first (as the author of EmailEngine) I'd suggest using EmailEngine for your IMAP needs 😉 but if do want to handle generating access tokens yourself, then the scopes that EmailEngine uses for the grant_type=authorization_code and grant_type=refresh_token calls are the following (space separated): https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send offline_access openid profile

That is after generating the application credentials as described in the blog post.