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

oAuth connection doesn't seem to be finished or does not give proper exception #151

Open
Pondake opened this issue Jul 9, 2019 · 4 comments

Comments

@Pondake
Copy link

Pondake commented Jul 9, 2019

Got error 'PHP message: PHP Notice: Undefined index: twf.clusterUrl in /home/siwontwi/domains/{{DOMAIN}}/public_html/wp-content/themes/{{DOMAIN}}/twinfield/php-twinfield/twinfield/src/Secure/OpenIdConnectAuthentication.php on line 99\nPHP message: PHP Fatal error: Uncaught SoapFault: SOAP-ERROR: Parsing WSDL: Couldn't load from '/webservices/processxml.asmx?wsdl' : failed to load external entity "/webservices/processxml.asmx?wsdl"\n in /home/siwontwi/domains/{{DOMAIN}}/public_html/wp-content/themes/{{DOMAIN}}/twinfield/php-twinfield/twinfield/src/Services/BaseService.php:42\nStack trace:\n#0 /home/siwontwi/domains/{{DOMAIN}}/public_html/wp-content/themes/{{DOMAIN}}/twinfield/php-twinfield/twinfield/src/Services/BaseService.php(42): SoapClient->SoapClient('/webservices/pr...', Array)\n#1 /home/siwontwi/domains/{{DOMAIN}}/public_html/wp-content/themes/{{DOMAIN}}/twinfield/php-twinfield/twinfield/src/Secure/AuthenticatedConnection.php(57): PhpTwinfield\\Services\\BaseService->__construct('/webservices/pr...', Array)\n#2 /home/siwontwi/domains/{{DOMAIN}}/public_html/wp-content/themes/{{DOMAIN}}/twinfield/php-twinfield/twinfield/src/ApiConnectors/BaseApiConnector.php

Did it by the book, code is exactly like the guide.

@iranl
Copy link
Contributor

iranl commented Jul 9, 2019

What guide? What code?
Posting just an error message is not going to be enough to help you troubleshoot your problem

Consider testing you code outside of other libraries and applications (e.g. Wordpress) before trying to implement the code in those applications and further complicate things.

@Pondake
Copy link
Author

Pondake commented Jul 9, 2019

Your guide, your code. (https://github.com/php-twinfield/twinfield)
It's no use to show the same code, but I'm happy to share it anyway if really necessary.
The error message has nothing to do with WordPress or other libraries.

I only changed a core file in the oAuth library to make it receive a refresh token.

@iranl
Copy link
Contributor

iranl commented Jul 9, 2019

Your guide, your code. (https://github.com/php-twinfield/twinfield)

I'm not a part of the php-twinfield team.

The error message has nothing to do with WordPress or other libraries.

Error might not have anything to do with the application you're including it in, but in initial testing my advice is always to keep it as simple as possible, get the desired result and implement it from there

I only changed a core file in the oAuth library to make it receive a refresh token.

I would advice against modifying core files, as it is difficult to reproduce your errors when we are working with different versions of the library.

It's no use to show the same code, but I'm happy to share it anyway if really necessary.

Showing your code helps to figure out what exactly is going wrong and hopefully make your problem reproducible. Especially considering the current README/guide you are referring to is very sparse I don't know exactly what you have done.

I've written a more extensive explanation of OAuth2 usage (including what to select when requesting your API ID/Secret) and some complete examples which you can find below:
-https://github.com/iranl/twinfield/blob/extend-all/usage.md#oauth2
-https://github.com/iranl/twinfield/blob/extend-all/examples/Authorization.php
-https://github.com/iranl/twinfield/blob/extend-all/examples/Connection.php

Consider the following all-in-one example that redirects you to Twinfield to requests the right authorization to retrieve a refresh token and when it returns connects using that token and lists all offices. This should work on unmodified versions of the current library.

// Provide the path to composer autoload.php
require_once('vendor/autoload.php');

// The client ID assigned to you by Twinfield.
$twin_client_id = 'SomeClientId';
// The client secret assigned to you by Twinfield.
$twin_client_secret = 'SomeClientSecret';

/* The FQDN URI where this script can be called from when Twinfield redirects back to after the user logs in.
 * Must be filled out on the form (Redirect URL) when requesting the client ID/Secret from Twinfield.
 */
$twin_redirect_uri = 'https://example.org/twinfield/Authorization.php';

// Your default office code.
$officeCode = "SomeOfficeCode";

$office = \PhpTwinfield\Office::fromCode($officeCode);

$provider = new \PhpTwinfield\Secure\Provider\OAuthProvider([
    'clientId'                => $twin_client_id,
    'clientSecret'            => $twin_client_secret,
    'redirectUri'             => $twin_redirect_uri,
]);

if (!isset($_GET['code'])) {
    $options = [
        'scope' => ['twf.user','twf.organisation','twf.organisationUser','offline_access','openid']
    ];
    $authorizationUrl = $provider->getAuthorizationUrl($options);
    $_SESSION['oauth2state'] = $provider->getState();
    header('Location: ' . $authorizationUrl);
    exit;
} elseif (empty($_GET['state']) || (isset($_SESSION['oauth2state']) && $_GET['state'] !== $_SESSION['oauth2state'])) {
    if (isset($_SESSION['oauth2state'])) {
        unset($_SESSION['oauth2state']);
    }
    exit('Invalid state');
} else {
    try {
        $accessToken = $provider->getAccessToken('authorization_code', [
            'code' => $_GET['code']
        ]);
     
        $connection  = new \PhpTwinfield\Secure\OpenIdConnectAuthentication($provider, $accessToken->getRefreshToken(), $office);

        $offices = $officeApiConnector->listAllWithoutOfficeCode();

        echo "<pre>";
        print_r($offices);
        echo "</pre>";
    } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
        // Failed to get the access token or user details.
        exit($e->getMessage());
    }
}

@TomRoskam
Copy link

Great example! Works almost perfectly for me.

The only problem I have is that I get an invalid_grant error on reload. I believe this has something to do because 'code' (authorization_code) is initiated only when 'code' is not set. When it is set, it is 'pushed' towards the header which is constructed in the URL. But on a reload the URL stays the same, but the accesToken gets renewed. And when this happens the 'code' does not 'match' the accessToken...
I believe this will throw the invalid_grant error. Do you (or someone else) have any suggestion on how to set the authorization_code every time the page is loaded?

Thanks already for any help!

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

3 participants