Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Micorosft Azure XOAUTH2 issues #2988

Closed
At0kir opened this issue Nov 28, 2023 · 10 comments
Closed

Micorosft Azure XOAUTH2 issues #2988

At0kir opened this issue Nov 28, 2023 · 10 comments

Comments

@At0kir
Copy link

At0kir commented Nov 28, 2023

Hi everyone,

I followed the guide below and setup everything on Active Directory. I got the client ID, client secret and tenant ID. Then I got the refresh token and for some reason I keep getting the CLIENT: 535 5.7.3 Authentication unsuccessful.

https://github.com/PHPMailer/PHPMailer/wiki/Microsoft-Azure-and-XOAUTH2-setup-guide

In the app permissions I have SMTP.Send and offline_access as delegated permissions.
The app has also been authorized using the get_oauth_token.php with admin credentials to get the refresh token.
The account that I am trying to send emails from has SMTP AUTH enabled on it as well.

Here is the code that I have to test if it works.

<?php

/**
 * This example shows how to send via Microsoft Outlook's servers using XOAUTH2 authentication
 * using the league/oauth2-client to provide the OAuth2 token.
 * To use a different OAuth2 library create a wrapper class that implements OAuthTokenProvider and
 * pass that wrapper class to PHPMailer::setOAuth().
 */

//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\OAuth;
//Alias the League Google OAuth2 provider class
use Greew\OAuth2\Client\Provider\Azure;

//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');

//Load dependencies from composer
//If this causes an error, run 'composer install'
require '../../libs/php_mailer/vendor/autoload.php';

//Create a new PHPMailer instance
$mail = new PHPMailer();

//Tell PHPMailer to use SMTP
$mail->isSMTP();

//Enable SMTP debugging
//SMTP::DEBUG_OFF = off (for production use)
//SMTP::DEBUG_CLIENT = client messages
//SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_SERVER;

//Set the hostname of the mail server
$mail->Host = 'smtp.office365.com';

//Set the SMTP port number:
// - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
// - 587 for SMTP+STARTTLS
$mail->Port = 587;

//Set the encryption mechanism to use:
// - SMTPS (implicit TLS on port 465) or
// - STARTTLS (explicit TLS on port 587)
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;

//Whether to use SMTP authentication
$mail->SMTPAuth = true;

//Set AuthType to use XOAUTH2
$mail->AuthType = 'XOAUTH2';

//Start Option 1: Use league/oauth2-client as OAuth2 token provider
//Fill in authentication details here
//Either the microsoft account owner, or the user that gave consent
$email = '[email protected]';
$clientId = 'aae3-------';
$clientSecret = 'ouP8-----';
$tenantId = '23be-------';

//Obtained by configuring and running get_oauth_token.php
//after setting up an app in Google Developer Console.
$refreshToken = '0.ATcADV6-I7----';

//Create a new OAuth2 provider instance
$provider = new Azure(
    [
        'clientId' => $clientId,
        'clientSecret' => $clientSecret,
        'tenantId' => $tenantId,
    ]
);

//Pass the OAuth provider instance to PHPMailer
$mail->setOAuth(
    new OAuth(
        [
            'provider' => $provider,
            'clientId' => $clientId,
            'clientSecret' => $clientSecret,
            'refreshToken' => $refreshToken,
            'userName' => $email,
        ]
    )
);
//End Option 1

//Set who the message is to be sent from
//For Outlook, this generally needs to be the same as the user you logged in as
$mail->setFrom($email, 'DoNotReply');

//Set who the message is to be sent to
$mail->addAddress('[email protected]', 'User User');

//Set the subject line
$mail->Subject = 'PHPMailer Outlook XOAUTH2 SMTP test';

//Replace the plain text body with one created manually
$mail->Body = 'This is a plain-text message body';

//send the message, check for errors
if (!$mail->send()) {
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'Message sent!';
}

I get this error and I removed some part of the AUTH XOAUTH2 response as I'm not sure if it contains anything sensitive since its quite larger(let me know if I should include the whole thing).

2023-11-28 20:06:51 SERVER -> CLIENT: 220 CH5P222CA0004.outlook.office365.com Microsoft ESMTP MAIL Service ready at Tue, 28 Nov 2023 20:06:50 +0000
2023-11-28 20:06:51 CLIENT -> SERVER: EHLO website.com
2023-11-28 20:06:51 SERVER -> CLIENT: 250-CH5P222CA0004.outlook.office365.com Hello [IP of server]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-STARTTLS250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8
2023-11-28 20:06:51 CLIENT -> SERVER: STARTTLS
2023-11-28 20:06:51 SERVER -> CLIENT: 220 2.0.0 SMTP server ready
2023-11-28 20:06:51 CLIENT -> SERVER: EHLO website.com
2023-11-28 20:06:51 SERVER -> CLIENT: 250-CH5P222CA0004.outlook.office365.com Hello [IP of server]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-AUTH LOGIN XOAUTH2250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8

2023-11-28 20:06:52 CLIENT -> SERVER: AUTH XOAUTH2 dXNlcj1kb25vdHJlcGx5QGVudGVyYS5jYQFhdXRoPUJlYXJlciBleUowZVhBaU9pSktWMVFpTENKdWIyNWpaU0k2SW1WclFrbGpjamhJUWxoaFFWOVBaVkJXU------------------------------------------------------------

2023-11-28 20:06:59 SERVER -> CLIENT: 535 5.7.3 Authentication unsuccessful [CH5P222CA0004.NAMP222.PROD.OUTLOOK.COM 2023-11-28T20:06:58.989Z 08DBF000432DD736]
2023-11-28 20:06:59 SMTP ERROR: AUTH command failed: 535 5.7.3 Authentication unsuccessful [CH5P222CA0004.NAMP222.PROD.OUTLOOK.COM 2023-11-28T20:06:58.989Z 08DBF000432DD736]
SMTP Error: Could not authenticate.
2023-11-28 20:06:59 CLIENT -> SERVER: QUIT
2023-11-28 20:06:59 SERVER -> CLIENT: 221 2.0.0 Service closing transmission channel
SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting
Mailer Error: SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

@decomplexity
Copy link
Contributor

Have a look at the AAD sign-in logs to see if there is anything of interest there. After you have signed in once, the MSFT authorization-code server should think that it has already passed you an authorization code when it calls the redirectURI (the code is suffixed to the URI).
Try:
• sign in to AAD
• select Enterprise Applications
• select your app
• select Sign-in Logs (near the bottom of the vertical list)
• select User-sign-ins (non-interactive)
• select Refresh
• select the Request ID ‘Aggregate’ item for today’s date and for Resource ‘Office 365 Exchange Online’, 'Graph' or other request you wish to check
• select the event for the time of your last failed event (or any other event in which you are interested)
This may have some useful information.

Then also:
• select the ‘…’ on the RHS of the title
• see the Oauth Scope Info field in the Additional Details tab

Failing this, note that access tokens expire quickly and are thus quickly invalid for anyone else to use, although inevitably they contain some application specific information that you may regard as sensitive. If you are happy with this, please post the entire token (the one starting dXN in your diagnostics).

The two most common reasons for your problem are:

  • wrong or no client scope (permissions)
  • wrong audience (the AUD claim in the token)

@At0kir
Copy link
Author

At0kir commented Nov 28, 2023

My app is not registered under the Enterprise Applications but under App Registrations. From what I saw the app doesn't show up under Enterprise Applications

Also what what would I do if its wrong audience (the AUD claim in the token)?

Here is the dXN:

dXNlcj1kb25vdHJlcGx5QGVudGVyYS5jYQFhdXRoPUJlYXJlciBleUowZVhBaU9pSktWMVFpTENKdWIyNWpaU0k2SWxsM1ZESkNVRTVRY2tJMVVrTnVWVlJuTXpGb2RuRklWelJVU2toeVJHWnplRlpWUTJsSlYxa3pRV2NpTENKaGJHY2lPaUpTVXpJMU5pSXNJbmcxZENJNklsUXhVM1F0WkV4VWRubFhVbWQ0UWw4Mk56WjFPR3R5V0ZNdFNTSXNJbXRwWkNJNklsUXhVM1F0WkV4VWRubFhVbWQ0UWw4Mk56WjFPR3R5V0ZNdFNTSjkuZXlKaGRXUWlPaUpvZEhSd2N6b3ZMMjkxZEd4dmIyc3ViMlptYVdObExtTnZiU0lzSW1semN5STZJbWgwZEhCek9pOHZjM1J6TG5kcGJtUnZkM011Ym1WMEx6SXpZbVUxWlRCa0xXVTJZbVl0TkRNd09DMWhObU0yTFRObVl6WmhPVGxsWlRkaE1pOGlMQ0pwWVhRaU9qRTNNREV5TURjMk9EVXNJbTVpWmlJNk1UY3dNVEl3TnpZNE5Td2laWGh3SWpveE56QXhNakV5TmpBd0xDSmhZMk4wSWpvd0xDSmhZM0lpT2lJeElpd2lZV2x2SWpvaVFWWlJRWEV2T0ZaQlFVRkJjM1JYVldwV01VTldkMVY1WVZWWlIzUTNOVUp5ZWxsd2Jrc3pRemhzTml0dWVFZFRZekJHVlcxNk9HdExkbXRrYjFOQlFYWTNLMEpOUzI5Mll6WnFlVTVOTDI1TllVTTFOVmd3UzBvNE5FOVhVMW8yWmtORFJIUmFSSE5xWjJaQ1EySk5Sa2RGUmpndmVXTTlJaXdpWVcxeUlqcGJJbkIzWkNJc0ltMW1ZU0pkTENKaGNIQmZaR2x6Y0d4aGVXNWhiV1VpT2lKRmJuUmxjbUVnVjJWaUlITmxjblpwWTJWeklpd2lZWEJ3YVdRaU9pSmhZV1V6TTJJMU5DMHhNbUV5TFRRNU1XVXRPR1ZtT0MwMU1tWTRNV0ppT0RSak5XTWlMQ0poY0hCcFpHRmpjaUk2SWpFaUxDSmxibVp3YjJ4cFpITWlPbHRkTENKbVlXMXBiSGxmYm1GdFpTSTZJbGRsYVc1emRHOWpheUlzSW1kcGRtVnVYMjVoYldVaU9pSkNaVzV1ZVNJc0ltbHdZV1JrY2lJNklqRTNOQzQ1TUM0Mk1DNHhNemdpTENKc2IyZHBibDlvYVc1MElqb2lUeTVEYVZFeVdWUmpNazFVV1RST1V6RnNUVVJLYVV4VVVUTlphbEYwV1dwak5FMURNSGxPYlVab1RucFZORnBFUm0xT1ZHdFRTa1JKZWxsdFZURmFWRUpyVEZkVk1sbHRXWFJPUkUxM1QwTXhhRTV0VFRKTVZFNXRXWHBhYUU5VWJHeGFWR1JvVFdodlkxRlhVblJoVnpSMFdXMVdkV0p1YkVGamJVcDZZakl4YkdOdVduQmlSM2hzVEcxT2RtSlRRV0VpTENKdVlXMWxJam9pUVdSdGFXNHRRbVZ1Ym5raUxDSnZhV1FpT2lJMllUYzJNVFk0TlMxbE1ESmlMVFEzWWpRdFlqYzRNQzB5Tm1GaE56VTRaREZtTlRraUxDSndkV2xrSWpvaU1UQXdNekl3TURNd016VkJSRFV5UmlJc0luSm9Jam9pTUM1QlZHTkJSRlkyTFVrM1gyMURSVTl0ZUdwZlIzRmFOMjV2WjBsQlFVRkJRVUZRUlZCNlowRkJRVUZCUVVGQlFUTkJTMnN1SWl3aWMyTndJam9pVTAxVVVDNVRaVzVrSWl3aWMybGtJam9pT1daaU1EaG1NV0V0TXpObU5TMDBZMkV6TFdKa01tVXRPR1UwWldRMU1EYzBaRGRsSWl3aWMzVmlJam9pVUhrNWR5MUZSME5TUTJab2FTMWtSMUIwUzBVd2NXZ3hVMk55Ym5sTGRFMU9WalJSVmsxd1h6Sm5RU0lzSW5ScFpDSTZJakl6WW1VMVpUQmtMV1UyWW1ZdE5ETXdPQzFoTm1NMkxUTm1ZelpoT1RsbFpUZGhNaUlzSW5WdWFYRjFaVjl1WVcxbElqb2lRV1J0YVc0dFltVnVibmxBY21KemIyMWxjblpwYkd4bExtTnZiU0lzSW5Wd2JpSTZJa0ZrYldsdUxXSmxibTU1UUhKaWMyOXRaWEoyYVd4c1pTNWpiMjBpTENKMWRHa2lPaUpHVFd0VVVURXpVWFpWVTFOeFVVb3RjSEpoTUVGbklpd2lkbVZ5SWpvaU1TNHdJaXdpZDJsa2N5STZXeUkyT1RBNU1USTBOaTB5TUdVNExUUmhOVFl0WVdFMFpDMHdOall3TnpWaU1tRTNZVGdpTENKbVpUa3pNR0psTnkwMVpUWXlMVFEzWkdJdE9URmhaaTA1T0dNellUUTVZVE00WWpFaUxDSXlPVEl6TW1Oa1ppMDVNekl6TFRReVptUXRZV1JsTWkweFpEQTVOMkZtTTJVMFpHVWlMQ0kyTW1VNU1ETTVOQzAyT1dZMUxUUXlNemN0T1RFNU1DMHdNVEl4TnpjeE5EVmxNVEFpTENKbU1qaGhNV1kxTUMxbU5tVTNMVFExTnpFdE9ERTRZaTAyWVRFeVpqSmhaalppTm1NaUxDSmlOemxtWW1ZMFpDMHpaV1k1TFRRMk9Ea3RPREUwTXkwM05tSXhPVFJsT0RVMU1Ea2lYWDAua09hNk9fYWpMekRoZjQ1MUVmX0Y2bFpUYVM0UVFwLWM1aS1QcGhhR3RpRDhoUGJFOXEwbU1mNXlDOG8xUW9KZk5kM3FTWEZSVUo2Y3Y5RVl6dnBic25uV01HMzN2eWgzRUsxVXg5ODd5a2d3WndjdGh2cUZRZEVicmZtcXF2NkZHUVFpemd5eFdMSndyUnA5TG56ZWJXclVZbGxhQkVnWWRVRGZHWVk0S0JPVmcteWtKTnRFRDhxOW52eVRzTV9QbVppRzRvWGx5Vmc3bTJ2NzRZMk1yOTBtTUxmc0pEQTNtb2Fxd0U1SUhLY055NEVVY1prY3B4VzFPLUQyS2pXTDdPWTgwQW9EbXE1SVFoczVyVy1NNkdiR2VQZWFSWXI1YUhWNzYtRnAycVlPU1FjWjZQX1F4T29SRzBqX0MwWFdvRk5jVEI2WU1Sd3l5ZV9yOTNMdG5RAQE=

@decomplexity
Copy link
Contributor

Your token appears OK: the two usual reasons for authentication failure are the AUD field (which in your token is correctly https://outlook.office.com) and the scope (which in your case is correctly SMTP.Send).
It is worth checking that the tenant ID of your app is indeed 23be5e0d-e6bf-4308-a6c6-3fc6a99ee7a2
Finally, re my comments in my previous reply, your app is registered in App Registrations but should also appear in Enterprise Applications. If we ignore MSFT's own applications that appear there, the difference between the two types is roughly that the App Registration is like an OOP CLASS and the its Enterprise Application version is a tenant-specific OBJECT based on the CLASS (Enterprise Applications are actually Service Principals that share the same permissions etc - all the stuff in its Manifest - from the App Registration but can otherwise differ with the different tenants they are defined in.
I'd double check that your app is not somewhere in Enterprise Applications.

@At0kir
Copy link
Author

At0kir commented Dec 5, 2023

The sing in logs say success with no error code and the tenant, secret id and client id are correct. I have no idea as to why the error is happening

The permissions are offline.access, smtp.send and user.read.

The logs are showing the date then Request ID is Aggregate, the user name is the admin, application is the name of my app, Status is Success, Resource is Office 365 Exchange.

It says MFA requirement satisfied by claim in the token.
The Additional details says OAuthScope Info ["SMTP.Send", "User.Read"]
Root Key Type Unknown

@decomplexity
Copy link
Contributor

Since your token looks fine, scope is fine and resource ('audience') is fine, 365 SMTP may (may...) be saying it doesn't like the token user ([email protected]) trying to send with an envelope From address that is different from that of the account.

@At0kir
Copy link
Author

At0kir commented Dec 5, 2023

I have changed the $email to multiple different emails and the same error is happening.
Does it have to do with anything from the admin account? I authorized the app from the oauth token page with the admin account and I'm trying to use a regular user.
I'm lost at this point on what to do.

@decomplexity
Copy link
Contributor

OK. The 'acid test' for this is whether the token's user address [email protected] is the same as the tenant's user principal email address. It is acceptable to use another licensed address in the same tenant but you know the user principal address is valid because it was used to register the app.
One obvious thing to check is whether SMTP is enabled for that user - see Admin Center=>Active users=>[select the user]=>Mail tab=>Email apps=>Manage email apps=>[Authenticated SMTP ticked]

@At0kir
Copy link
Author

At0kir commented Dec 5, 2023

I have verified that the user has SMTP ticked. The account that authorized the application has full admin permissions over the whole active directory so I should be able to send emails using the [email protected] user address.

@decomplexity
Copy link
Contributor

Yes you should.
But since it was 365 SMTP that had been presented with an apparently valid access token that it would then check for audience*, scope*, user and expiry time - things that are relevant to 365 SMTP authentication but less relevant to token issue - this is where it is best to look for things amiss
Since you have found the app registration under Enterprise applications as well as App registrations, what Permissions are listed for that app (in Enterprise applications) in both the Admin consent and User consent tabs? These should be OK as the token was issued and looks good, but I am fishing for clues!

    • both of which look OK

@At0kir
Copy link
Author

At0kir commented Dec 6, 2023

So I remade the refresh token but I signed in using the dotnoreply account instead of the admin account and I put the refresh token from that account and everything is working properly now. So I guess you have to authorize the app using the admin account and after that re do the refresh token using the user account.

Thank you for your help.

@At0kir At0kir closed this as completed Dec 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants