AlexaCRM / php-crm-toolkit

Dynamics CRM Toolkit for PHP
GNU Lesser General Public License v3.0
107 stars 42 forks source link

Error when authenticating: Ws-Trust #118

Closed ojoven closed 2 years ago

ojoven commented 2 years ago

Hi,

I wanted to inform you that the SDK is not working anymore.

When trying to connect via

$options = [
    'serverUrl' => 'https://' . $domain . '.crm3.dynamics.com',
    'username' => $username,
    'password' => $password,
    'authMode' => 'OnlineFederation',
];

$serviceSettings = new Settings($options);
$service = new OrganizationService($serviceSettings);

The client throws an error with the following message:

An error occurred when processing the security tokens in the message:You are using Ws-Trust authentication which has been deprecated and no longer supported in your environment. Please use OAuth2.0 authentication and refer https://aka.ms/dvwsdep.

Microsoft offers some documentation on how to fix this: https://docs.microsoft.com/en-us/power-apps/developer/data-platform/authenticate-office365-deprecation

Is this something you already fixed in your premium package? I don't see it in the Premium Features, but I'd understand that this was already fixed on it. Could you please confirm?

Thanks

georged commented 2 years ago

@ojoven toolkit does support OAuth as of commit 6dd4acab20d7d9a3c83fa5f283aab833e9d851dc

$options = [
    'serverUrl' => 'https://' . $domain . '.crm3.dynamics.com',
    'applicationId' => $applicationId,
    'clientSecret' => $secret,
    'authMode' => 'OnlineFederation',
    'authMethod' => 'sharedSecretAuth',
        'cache' => new AlexaCRM\CRMToolkit\NullCache(),
];
$serviceSettings = new OnlineS2SSecretAuthenticationSettings($options);
ojoven commented 2 years ago

Hey @georged

That's great, I saw that there was a change some months ago to adapt the SDK to OAuth.

I was going to ask you how to build the settings with the new data but I saw that you edited the comment with the solution.

I'm having some issues yet with OnlineS2SAuth.php Uncaught Error: Call to a member function get() on null in /alexacrm/php-crm-toolkit/src/Auth/OnlineS2SAuth.php:49

But it may be cache related. Please let me test a bit further and I'll get back to you with the outcome.

Thanks again.

georged commented 2 years ago

@ojoven you do need cache instance. You could use NullCache I suppose but then you'll be facing token request every time so it'd be better if you use a proper one. I updated sample with the null cache - try it.

ojoven commented 2 years ago

Hey @georged

After adding the NullCache, the connection was successfully made.

However, when retrieving doing a request to retrieve data:

$registryResult = $service->retrieveMultiple($query, false);

We're getting an error:

Uncaught Exception: Could not find RetrieveMultipleResponse node in XML provided in /alexacrm/php-crm-toolkit/src/Client.php:1620

After investigating, the XML was returning:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcode>s:Client</faultcode><faultstring xml:lang="en-US">Principal user (Id=XXXXXXXXXXXXXXXX, type=8, roleCount=1, privilegeCount=793, accessMode=4), is missing prvReadadoxio_licencetype privilege (Id=XXXXXXXXXXXXXXXX) on OTC=XXXXXXXXXXXX for entity 'adoxio_licencetype' (LocalizedName='Licence Type'). context.Caller=XXXXXXXXXXXXXXXXXXXX</faultstring><detail>...

So for this, it looks like we need to check with our client so they give the necessary permissions to that user.

I just want to ask you a final thing.

Instead of using NullCache, I assume that we need to implement our own Cache, is that correct?

Thanks so much for all your support.

georged commented 2 years ago

The message is about insufficient privileges for the app user. If you have working code when username was used, assign the same roles to the app user.

You most certainly don't need to roll out your own cache implementation. We expect PSR-16 compliant cache (https://www.php-fig.org/psr/psr-16/) - there are plenty of those around.

georged commented 2 years ago

Last but not least @ojoven. Take a look at https://github.com/AlexaCRM/dynamics-webapi-toolkit - it's web api based and much more robust than the current SOAP based toolkit. That's the recommended way forward.

ojoven commented 2 years ago

Hey @georged

This is perfect. Thanks so much.

Yes, some specific requests are made with the WebAPI - that's why we already had the applicationId and secret - but we initially started with SOAP due to some restrictions and migrating may not be straightforward, though we'll totally consider it.

Thanks for your support.

dantedantas commented 2 years ago

Hey @georged

That's great, I saw that there was a change some months ago to adapt the SDK to OAuth.

I was going to ask you how to build the settings with the new data but I saw that you edited the comment with the solution.

I'm having some issues yet with OnlineS2SAuth.php Uncaught Error: Call to a member function get() on null in /alexacrm/php-crm-toolkit/src/Auth/OnlineS2SAuth.php:49

But it may be cache related. Please let me test a bit further and I'll get back to you with the outcome.

Thanks again.

Hi @ojoven , I have the same issue as you. Please, could you help me no how could I solve this issue? Could you share with me which changes have you done and where?

Thank you.

Dante

ojoven commented 2 years ago

Hey @dantedantas

Sorry for the delay in my response.

As georged commented, you need to add a cache to the options array: https://github.com/AlexaCRM/php-crm-toolkit/issues/118#issuecomment-1088367473

'cache' => new AlexaCRM\CRMToolkit\NullCache(),

This NullCache, however, is a dummy cache and won't store your request tokens and so, the requests will be very consuming. However, it can work for an initial approach of checking if this works or not.

Once you check that it works, it's time to use a real cache.

In our case, we used FileSystem: https://github.com/php-cache/filesystem-adapter

You have others (Memcached, Redis, etc. here: https://github.com/php-cache)

So our code looked like this:

$filesystemAdapter = new Local(__DIR__ . '/'); $filesystem = new Filesystem($filesystemAdapter);

$options = [ ...your options here 'cache' => new Cache\Adapter\Filesystem\FilesystemCachePool($filesystem) ];

Hope this helps!

Cheers, Mikel

dantedantas commented 2 years ago

Hola @ojoven , buenas tardes. Thank you for your feedback.

I have no idea why I am not able to implement the changes. I am getting am error.

`Notice: Undefined property: AlexaCRM\CRMToolkit\Settings::$applicationId in C:\Tools\xampp\htdocs\incidentreport\vendor\alexacrm\php-crm-toolkit\src\Client.php on line 1467

AlexaCRM\CRMToolkit\Client requires Application ID and Client Secret`

image

Maybe the AppID was created wrong?

Thank you/Gracias, Dante

georged commented 2 years ago

@dantedantas what object you're instantiating for settings? It should be OnlineS2SSecretAuthenticationSettings not Settings. Also, username and password are obviously no longer used and not required. The code should be like this:

$options = [
    'serverUrl' => 'https://instance.crmN.dynamics.com',
    'applicationId' => $applicationId,
    'clientSecret' => $secret,
    'authMode' => 'OnlineFederation',
    'authMethod' => 'sharedSecretAuth',
        'cache' => new AlexaCRM\CRMToolkit\NullCache(),
];
$serviceSettings = new OnlineS2SSecretAuthenticationSettings($options);
Nasiralijames commented 2 years ago

Hey @dantedantas

Sorry for the delay in my response.

As georged commented, you need to add a cache to the options array: #118 (comment)

'cache' => new AlexaCRM\CRMToolkit\NullCache(),

This NullCache, however, is a dummy cache and won't store your request tokens and so, the requests will be very consuming. However, it can work for an initial approach of checking if this works or not.

Once you check that it works, it's time to use a real cache.

In our case, we used FileSystem: https://github.com/php-cache/filesystem-adapter

You have others (Memcached, Redis, etc. here: https://github.com/php-cache)

So our code looked like this:

$filesystemAdapter = new Local(DIR . '/'); $filesystem = new Filesystem($filesystemAdapter);

$options = [ ...your options here 'cache' => new Cache\Adapter\Filesystem\FilesystemCachePool($filesystem) ];

Hope this helps!

Cheers, Mikel

Hi @ojoven, We have followed the given procedure for using the Filesystem from the GitHub - https://github.com/php-cache/filesystem-adapter

But we are getting the below Fatal error.

Could you please check and guide us for the same.

Fatal error: Uncaught Error: Class 'League\Flysystem\Adapter\Local' not found in C:\xampp\htdocs\sdg\wp-content\themes\edubiz_child\functions\synchronize-wordpress-dynamics\syn_contact_enquiry.php:112

By using NullCache we can able to create a successful connection. But while using the Filesystem facing the above error. We have placed all the folders and files at proper place.

Thanks!

ojoven commented 2 years ago

Hey @Nasiralijames

Do you have the following in your code:

require_once __DIR__ . '/../vendor/autoload.php';

and

use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;

at the top of your file?

It looks like you may be missing the vendor autoload? Or that you have it in some way that it's not retrieving correctly the classes from those files.

Without seeing the full file I can't say.

Cheers

Nasiralijames commented 2 years ago

Hey @Nasiralijames

Do you have the following in your code:

require_once __DIR__ . '/../vendor/autoload.php';

and

use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;

at the top of your file?

It looks like you may be missing the vendor autoload? Or that you have it in some way that it's not retrieving correctly the classes from those files.

Without seeing the full file I can't say.

Cheers

Hi @ojoven,

Sorry for the delay in my response.

Thanks for the help I have added the above given line of code now and it is working fine.

Thanks a lot for your guidance and help.

Regards, Nasir

janeliasprague commented 2 years ago

Hi guys!

What did I do wrongly if I'm getting this notice "Undefined index: WWW-Authenticate"? (see screenshot bellow)

I created single tenant application at admin.microsoft.com according to this article https://docs.microsoft.com/en-us/power-apps/developer/data-platform/use-single-tenant-server-server-authentication#register-your-application-on-azure-ad

I am using application ID and client secret in my code.

Snímek obrazovky 2022-07-10 v 16 06 16

georged commented 2 years ago

Check your instance URL - does not look it's a valid one. Also, drop /api/data/v9.0/ part, just use https://yourorg.crm4.dynamics.com

janeliasprague commented 2 years ago

This is my service settings

$this->options = [
            'serverUrl' => "https://myorg.crm4.dynamics.com",
            'applicationId' => self::APPID,
            'clientSecret' => self::CLIENTSECRET,
            'authMode' => 'OnlineFederation',
            'authMethod' => 'sharedSecretAuth',
            'cache' => new \AlexaCRM\CRMToolkit\NullCache(),
];

$serviceSettings = new OnlineS2SSecretAuthenticationSettings($this->options);

That part /api/data/v9.0/ was added automatically.

georged commented 2 years ago

@janeliasprague try again because yesterday the url was not valid (perhaps transient provisioning issue). If you're still getting an error, add a logger to get more information about what's coming back.

janeliasprague commented 2 years ago

I'm still getting a notice (it is not an error). I can skip this notice and I get cURL error. Snímek obrazovky 2022-07-11 v 12 26 40

What do you mean by "add a logger"? How can I do it? Thanks

georged commented 2 years ago

AbstractSettings class contains $logger member that you can set to a PSR-3 compliant logger and get extended error details.

use Monolog\Logger;
...
$client = new OrganizationService($clientSettings);
$client->logger = new \Monolog\Logger( 'whatever' );
janeliasprague commented 2 years ago

function detectTenantID() returns array $headers and then is looking for "WWW-Authenticate" field. But the field is called "www-authenticate".

The question is - do I have the right version of the library?

I've installed it using composer update alexacrm/php-crm-toolkit:dev-master#6dd4aca --with-dependencies

Snímek obrazovky 2022-07-11 v 14 04 52

Snímek obrazovky 2022-07-11 v 14 09 13

georged commented 2 years ago

If you just started I really recommend you switch to https://github.com/AlexaCRM/dynamics-webapi-toolkit instead. Latter is based on Web API and is the primary toolkit moving forward.

As per Readme

This toolkit supports only Dynamics 365 SOAP interface. For PHP implementation of the Dynamics 365 Web API, see dynamics-webapi-toolkit project.