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

Cannot access to Microsoft mailboxes via OAuth2 - Please help me #262

Closed
francescodiperna opened this issue Aug 23, 2022 · 8 comments
Closed
Labels
Outlook Related to Outlook question

Comments

@francescodiperna
Copy link

francescodiperna commented Aug 23, 2022

Hi, I'm trying to read mailboxes using this library, obtaining the correct access token, but when I try to use the token I got the error "NO AUTHENTICATE failed".
I have configured the app in AD as the guide indicated in the link https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow.
Does anyone is able to read mailboxes messages using OAuth authentication?

The access token param are:

'form_params' => [
                'client_id' => GraphHelper::$clientId,
                'client_secret' => GraphHelper::$clientSecret,
                'grant_type' => 'client_credentials',
                'scope' => 'https://graph.microsoft.com/.default',                                               
            ]

and the following request is:

$cm = new ClientManager($options = ["options" => ["debug" => true]]);			
$client = $cm->make([
	'host'          => 'outlook.office365.com',                
	'port'          => 993,
	'encryption'    => 'ssl',
	'validate_cert' => true,
	'username'      => $username,
	'password'      => $access_token,
	'protocol'      => 'imap',
	'authentication' => "oauth"
]);
$client->connect();   

We tried to add many permission to the app registration, as you can see in the attached screenshot.

Do you have any idea to correct the problem?

Kind regard
Schermata del 2022-08-23 11-13-22

@Webklex
Copy link
Owner

Webklex commented Aug 23, 2022

Hi @francescodiperna ,
a few things I can thingk of which could cause this problem:

  • You have to grant these permissions: IMAP.AccessAsUser.All and potentially (email, offline_access, User.Read)
  • You need to add a client secret under "certificates and secrets".
  • You need to have "https://outlook.office365.com/IMAP.AccessAsUser.All" inside your scope while generating the token

I've tested it successfully with a slightly different scope "offline_access%20https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Foutlook.office365.com%2FSMTP.Send" - but I don't believe they are all required. In fact I believe just "https://outlook.office365.com/IMAP.AccessAsUser.All" is required.

I hope this helps you :)

Best regards & happy coding,

@Webklex Webklex added question Outlook Related to Outlook labels Aug 23, 2022
@francescodiperna
Copy link
Author

Thanks for fast replay, we are unable to use your scope because the server complain with the following message

AADSTS1002012: The provided value for scope XXXXXXXXXXXXXXXXX is not valid. Client credential flows must have a scope value with /.default suffixed to the resource identifier (application ID URI).
(we cannot use multiple scope in the parameter, the server doesn't recognize the scope).

We are using "OAuth 2.0 Client Credentials flow", maybe you are using a different one?
Kind regards

@Webklex
Copy link
Owner

Webklex commented Aug 23, 2022

Hi @francescodiperna ,
I'm using this method to generate an auth token:

#!/bin/bash

CLIENT_ID="redacted"
CLIENT_SECRET="redacted"
TENANT="redacted"

SCOPE="offline_access%20https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
STATE="12345"
REDIRECT_URI="http%3A%2F%2Flocalhost"

echo "Open this url inside your browser:"
echo ""
echo "https://login.microsoftonline.com/${TENANT}/oauth2/v2.0/authorize?client_id=${CLIENT_ID}&response_type=code&redirect_uri=${REDIRECT_URI}&response_mode=query&scope=${SCOPE}&state=${STATE}"

echo ""
echo "..you'll get redirected to ${REDIRECT_URI} with the required code & session_state attached within the uri."
echo "Edit this file and update the CODE and SESSION variable and remove the first 'exit 0'."

# Remove this line, if you've acquired the code and session state values
exit 0
echo ""

# -> http://localhost/
# ?code=redacted
# &state=12345
# &session_state=aa88c.....#

CODE="0.AWcAfY9hQ-vwo0y1eqaPE....."
SESSION="aa88c12b-3e...."
REFRESH_TOKEN=""

echo "Trying to authenticate the session.."
RESPONSE=$( curl -XPOST https://login.microsoftonline.com/${TENANT}/oauth2/v2.0/token -d "client_id=${CLIENT_ID}&scope=${SCOPE}&code=${CODE}&state=${STATE}&session_state=${SESSION}&redirect_uri=${REDIRECT_URI}&client_secret=${CLIENT_SECRET}&refresh_token=${REFRESH_TOKEN}&grant_type=authorization_code" )

# {
#       "token_type":"Bearer",
#       "scope":"https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send",
#       "expires_in":3955,
#       "ext_expires_in":3955,
#       "access_token":"redacted",
#       "refresh_token":"redacted"
# }

echo ""
echo "Auth response.."
echo "$RESPONSE"

ACCESS_TOKEN=$( echo "$RESPONSE" | jq -r .access_token  )
REFRESH_TOKEN=$( echo "$RESPONSE" | jq -r .refresh_token )

echo ""
echo "Access token: ${ACCESS_TOKEN}"
echo ""
echo "Refresh token: ${REFRESH_TOKEN}"
echo ""
echo ""

@eisolutions
Copy link

eisolutions commented Aug 23, 2022

My working example

//https://github.com/jumbojett/OpenID-Connect-PHP
$oidc = new \Jumbojett\OpenIDConnectClient('https://login.microsoftonline.com/{tenantId}/v2.0/',
'{clientId}',
'{clientSecret');
//v2.0 in URL is important!!!

$oidc->addScope(['profile','openid','email','offline_access','https://outlook.office.com/IMAP.AccessAsUser.All','User.Read']);

$oidc->authenticate();

$username = $oidc->requestUserInfo('preferred_username');
//or use static $username='some@yourdomain.com';
$token = $oidc->getAccessToken();

$cm = new ClientManager();
$client = $cm->make([
	'host' => 'outlook.office365.com',
	'port' => 993,
	'encryption' => 'ssl', // 'tls',
	'validate_cert' => true,
	'username' => $username,
	'password' => $token,
	'protocol' => 'imap',
	'authentication' => "oauth",
]);
$client->connect();

$folders = $client->getFolders();
var_dump($folders);

@francescodiperna
Copy link
Author

francescodiperna commented Aug 24, 2022

Webklex

Hi @Webklex,
we are working in a deamon application and we cannot use the browser for the autenthication.
The access token got using your code has an expiration time of 1 hour only.

Using your procedure I got this error:

BAD User is authenticated but not connected.

Kind regards

@Webklex
Copy link
Owner

Webklex commented Aug 24, 2022

Hi @francescodiperna ,
you can refresh the token with a call like this:

curl -XPOST https://login.microsoftonline.com/${TENANT}/oauth2/v2.0/token -d "client_id=${CLIENT_ID}&scope=${SCOPE}&refresh_token=${REFRESH_TOKEN}&grant_type=refresh_token&client_secret=${CLIENT_SECRET}"

If you can't authenticate the user via browser, perhaps @eisolutions suggestion works better for your use case.
Checkout the mentioned repository: https://github.com/jumbojett/OpenID-Connect-PHP

I'm not familiar with the error message BAD User is authenticated but not connected.. I suggest you enable the debug mode inside your config file, to see whats being send and received. This might give some insight into whats happening :)

https://github.com/Webklex/php-imap/blob/master/src/config/imap.php#L152

If you are using the laravel wrapper, the imap.php file should be inside the config folder if you've published the package.

@eisolutions
Copy link

You can authorize user in browser, then save access token and refresh token eg. in database and transfer to your daemon app.
Daemon app can refresh access token when it expires, using refresh token (there is method refreshToken in OpenID-Connect-PHP)

@roylanceb
Copy link

Webklex

Hi @Webklex, we are working in a deamon application and we cannot use the browser for the autenthication. The access token got using your code has an expiration time of 1 hour only.

Using your procedure I got this error:

BAD User is authenticated but not connected.

Kind regards

I was getting the same error. It looks to have been because IMAP was disabled on the account

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Outlook Related to Outlook question
Projects
None yet
Development

No branches or pull requests

4 participants