Webklex / php-imap

PHP-IMAP is a wrapper for common IMAP communication without the need to have the php-imap module installed / enabled. The protocol is completely integrated and therefore supports IMAP IDLE operation and the "new" oAuth authentication process as well.
https://www.php-imap.com
MIT License
314 stars 147 forks source link

Guide / Tutorial to setup Outlook / Azure #264

Open Webklex opened 2 years ago

Webklex commented 2 years ago

Hi Everyone, I'm looking for someone who would like to create a tutorial with a step by step guide on how to setup Azure in order to use Outlook accounts (especially how to create an auth token which can be used to authenticate via IMAP). Please let me know if you know of an tutorial / guide which already exist. I'm more than happy to link to it where ever I can :)

Thanks and happy coding,

MGParisi commented 2 years ago

I'm trying to do this now... it isn't easy. I can write something if I get it working.

But I'm struggling to get it to work... 'microsoft' => [ 'host' => 'outlook.office365.com', 'port' => 993, 'encryption' => 'ssl', // 'tls', 'validate_cert' => FALSE, 'username' => '{redacted email}', 'password' => '{redacted password}', 'protocol' => 'imap', 'authentication' => "oauth", ]

got failure response: NO AUTHENTICATE failed.

PHP Fatal error: Uncaught Webklex\PHPIMAP\Exceptions\AuthFailedException in C:\wamp64\www\imap_receiver\vendor\webklex\php-imap\src\Client.php:385 Stack trace:

0 C:\wamp64\www\imap_receiver\vendor\webklex\php-imap\src\Client.php(371): Webklex\PHPIMAP\Client->authenticate()

1 C:\wamp64\www\imap_receiver\mail_receive2.php(61): Webklex\PHPIMAP\Client->connect()

2 {main}

MGParisi commented 2 years ago

I've created an app password using Azure.... I'd have to write something up on how to do it, next time I'm in the website. But I tried that password and the users password, and neither will connect. Going to try both ssl, tls, or just tls. But my previous attempts to make this work on imap_open have not been successful. I believe oAuth2 is needed, so I ended up here.

knightcott-paul commented 2 years ago

These steps should allow you to connect to IMAP endpoint with authorised client application using oauth authentication to access specified mailboxes.

You’ll need:

<tenantId>   Azure AD tenant ID
<clientId>       This ID identifies your client application
<clientSecret>   This is allows you to request a token
<objectId>       This is the ID of the application registration
<mailboxId>      This user principle name of the target mailbox (email address)

Azure Active Directory

Login to Azure Active Directory with administrative permissons.

Select App registrations, then New registration

Given the app a name and select the support account type (I’ve only used Single tenant)

Click Register

From the Overview page of the app, make a note of the Application (client) ID - this is your \<clientId> and the Directory (tenant) ID - this is your \<tenantId>

Select API permissions, then Add a permission

Select APIs my organization uses.

Select Office 365 Exchange Online (you might need to search for it) then Application Permissions, then select the permission IMAP.AccessAsApp

Tick the box, then click Add permissions

Click Grant admin consent for tenant, then click Yes (as admin you’re allowing the app to be used on the tenant, with poweshell below you will link the app to specific mailboxes)

Select Certificates & Secrets, then New Client Secret

Give it a name and expiration and then click Add

Make a note of the ‘Value’, this is your \<clientSecret>

From the main AzureAD page, select Enterprise applications

Find your new application on the list and make a note of the Object ID – this is your \<objectId> NB this is different from the Object ID which is shown on the app registration page

Powershell (replace bold with your parameters)

Install-Module -Name ExchangeOnlineManagement -allowprerelease Import-module ExchangeOnlineManagement Connect-ExchangeOnline -Organization \<tenantId>

New-ServicePrincipal -AppId \<clientId> -ServiceId \<objectId> Add-mailboxpermission -identity “\<mailboxID>” -user \<objectId> -accessrights FullAccess

Repeat the add-mailboxpermssion for required mailboxes.

Get a token:

// Replace bold with your parameters curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'client_id=\<clientid>&scope=https%3A%2F%2Foutlook.office365.com%2F.default&client_secret=\<clientSecret>&grant_type=client_credentials' 'https://login.microsoftonline.com/\<tenantId>/oauth2/v2.0/token'

This will return a json message with the token

Use the token as the password when making your ClientManager instance, and set the authentication parameter to oauth

The token is only valid for an hour. Apparently, it can be renewed but I’m yet to try that.

Credit goes Ricci Gian Maria at https://www.codewrecks.com/post/security/accessing-office-365-imap-with-oauth2/ for doing the hard work. This above is bear essentials that I've used from his write-up and videos

peinfant54 commented 2 years ago

Hi @knightcott-paul. After doing all the step you described, then what?

How to correct set up laravel-imap?

Thanks

knightcott-paul commented 2 years ago

Hi, After doing the steps above you can use the token as the password when creating your ClientManager instance. Like this example

If you're using Laravel, you can install the package with composer require webklex/php-imap

peinfant54 commented 2 years ago

Hi @knightcott-paul thank you for answer me. The problem is that after doing all that, I'm still can't connect:

<< TAG1 NO AUTHENTICATE failed. got failure response: NO AUTHENTICATE failed.

"connection setup failed"

TAG2 LOGOUT << * BYE Microsoft Exchange Server IMAP4 server signing off. << TAG2 OK LOGOUT completed.

vielhuber commented 2 years ago

Same problem here.

I have a plain exchange online instance and followed all the steps, but did not succeed.

vielhuber commented 2 years ago

ok, got it:

This checkbox was missing:

image

peinfant54 commented 2 years ago

@vielhuber That was the clue!! Thank you!!

And all this process has to be done, with a user, who has the "GLOBAL ADMINISTRATOR" Role

peinfant54 commented 1 year ago

Here is a Script for the getting the Token

public function getOfficeToken3652($tenantID, $clientid, $clientSecret) { $url = "https://login.microsoftonline.com/".$tenantID."/oauth2/v2.0/token"; $curl = curl_init($url); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $headers = array( "Content-Type: application/x-www-form-urlencoded", ); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); $data = 'client_id='.$clientid.'&scope=https%3A%2F%2Foutlook.office365.com%2F.default&client_secret='.$clientSecret.'&grant_type=client_credentials'; curl_setopt($curl, CURLOPT_POSTFIELDS, $data); //for debug only! curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); $resp = json_decode(curl_exec($curl)); curl_close($curl); echo $resp->access_token; }

juliansiebert commented 1 year ago

Hi, as a note for anyone else copy and pasting stuff together:

The "object id" used with the PowerShell Cmdlet "New-ServicePrincipal" has to be the one from "ENTERPRISE APPLICATIONS", not from the "APPLICATION REGISTRATIONS".

As perfectly shown in a screenshot on the following blog post: https://www.limilabs.com/blog/oauth2-client-credential-flow-office365-exchange-imap-pop3-smtp