ayles-software / xero-laravel

Laravel 6/7 wrapper for Xero and OAuth2 authorization
MIT License
2 stars 1 forks source link

Help with completing auth flow #2

Closed Duncan-dev1 closed 3 years ago

Duncan-dev1 commented 3 years ago

Hi there,i am currently using this package to integrate xero,which i am new to with laravel. i am stuck at the auth flow though,directing users to choose the tenant works fine and i get a redirect with a code and matching status as the the one in the request.The request has %26state%3D44e732003592baea709dd2e85f94d3a4% and the redirect has &state=44e732003592baea709dd2e85f94d3a4& which i suppose i fine.I have a problem with the exchange of code for access token though.i thought of calling the generate function inside the flow function that is invoked at the XeroAuthController as per the docs .`<?php

namespace AylesSoftware\XeroLaravel;

use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use AylesSoftware\XeroLaravel\Entities\XeroAccess; use Calcinai\OAuth2\Client\Provider\Xero as XeroOAuthClient;

class XeroOAuth { public $request;

public $token;

public $tenants;

public $credentials;

protected $provider;

public function __construct(Request $request)
{
    $this->request = $request;
    $this->credentials = XeroAccess::latest();

    $this->provider = new XeroOAuthClient([
        'clientId' => config('xero-laravel.client_id'),
        'clientSecret' => config('xero-laravel.client_secret'),
        'redirectUri' => config('xero-laravel.redirect_url'),
    ]);

    $this->refresh();
}

public function flow()
{
    if ($this->request->has('code')) {
        $this->generate('authorization_code', ['code' => $this->request->input('code')]);

        return redirect(config('xero-laravel.redirect_after_authorization_url'));
    }

    return redirect(
        $this->provider->getAuthorizationUrl([
            'scope' => [config('xero-laravel.scope')],
        ])
    );
    $this->generate();  //where i think might be good place to call this to get scredentials and save to db
}

public function refresh()
{
    if ($this->credentials && $this->credentials->has_expired) {
        $this->generate('refresh_token', ['refresh_token' => $this->credentials->refresh_token]);
    }
}

protected function generate($type, $data)
{
    $this->token = $this->provider->getAccessToken($type, $data);

    $this->tenants = $this->provider->getTenants($this->token);

    $this->saveCredentials();
}

protected function saveCredentials()
{
    DB::transaction(function () {
        XeroAccess::setAllObsolete();

        $this->credentials = XeroAccess::create([
            'refresh_token' => $this->token->getRefreshToken(),
            'token' => $this->token->getToken(),
            'tenant_id' => collect($this->tenants)->pluck('tenantId')->first(),
            'expires_at' => now()->addMinutes(29),
        ]);
    });
}

} ` What am i missing and how should i go about generating and storing the credentials in the db

parkourben99 commented 3 years ago

To generate the oauth credentials all you need is a controller like this.

<?php

namespace App\Http\Controllers;

use AylesSoftware\XeroLaravel\XeroOAuth;

class XeroOAuthController extends Controller
{
    public function __invoke(XeroOAuth $xeroOAuth)
    {
        return $xeroOAuth->flow();
    }
}

You can then create a route. Route::get('xero-oauth', 'XeroOAuthController');

Then you can navigate to /xero-oauth this will redirect you to xero for authentication. After Xero will redirect back.

Make sure you have XERO_REDIRECT_URL= set to /xero-oauth

Duncan-dev1 commented 3 years ago

Thank you for the prompt response,i didnt have my XERO_REDIRECT_URL same as my route,after doing that i know get an error Calcinai\OAuth2\Client\Provider\Exception\XeroProviderException Forbidden where could this be coming from

parkourben99 commented 3 years ago

Do you have these .env vars set?

XERO_CLIENT_ID=
XERO_CLIENT_SECRET=

Have you registered the app with Xero?

Duncan-dev1 commented 3 years ago

Yes i have those,also my xero app's redirect is same as my XERO_REDIRECT_URL ,i am serving my app using php artisan serve for my localhost

parkourben99 commented 3 years ago

What is the exception message?

Duncan-dev1 commented 3 years ago

Below is my log `[2021-05-08 06:44:57] local.ERROR: Forbidden {"userId":1,"exception":"[object] (Calcinai\OAuth2\Client\Provider\Exception\XeroProviderException(code: 403): Forbidden at C:\xampp\htdocs\laravuex\vendor\calcinai\oauth2-xero\src\Provider\Xero.php:132) [stacktrace]

0 C:\xampp\htdocs\laravuex\vendor\league\oauth2-client\src\Provider\AbstractProvider.php(628): Calcinai\OAuth2\Client\Provider\Xero->checkResponse(Object(GuzzleHttp\Psr7\Response), '\

<T...')

1 C:\xampp\htdocs\laravuex\vendor\league\oauth2-client\src\Provider\AbstractProvider.php(537): League\OAuth2\Client\Provider\AbstractProvider->getParsedResponse(Object(GuzzleHttp\Psr7\Request))

2 C:\xampp\htdocs\laravuex\vendor\ayles-software\xero-laravel\src\XeroOAuth.php(61): League\OAuth2\Client\Provider\AbstractProvider->getAccessToken(Object(League\OAuth2\Client\Grant\AuthorizationCode), Array)

3 C:\xampp\htdocs\laravuex\vendor\ayles-software\xero-laravel\src\XeroOAuth.php(39): AylesSoftware\XeroLaravel\XeroOAuth->generate('authorization_c...', Array)

4 C:\xampp\htdocs\laravuex\app\Http\Controllers\XeroAuthController.php(11): AylesSoftware\XeroLaravel\XeroOAuth->flow()

5 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\Controller.php(54): App\Http\Controllers\XeroAuthController->__invoke(Object(AylesSoftware\XeroLaravel\XeroOAuth))

6 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\ControllerDispatcher.php(45): Illuminate\Routing\Controller->callAction('__invoke', Array)

7 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\Route.php(239): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(App\Http\Controllers\XeroAuthController), '__invoke')

8 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\Route.php(196): Illuminate\Routing\Route->runController()

9 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\Router.php(685): Illuminate\Routing\Route->run()

10 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(128): Illuminate\Routing\Router->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))

11 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\Middleware\SubstituteBindings.php(41): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

12 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))

13 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken.php(78): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

14 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))

15 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\View\Middleware\ShareErrorsFromSession.php(49): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

16 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))

17 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Session\Middleware\StartSession.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

18 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Session\Middleware\StartSession.php(62): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\Store), Object(Closure))

19 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))

20 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

21 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))

22 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Cookie\Middleware\EncryptCookies.php(67): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

23 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))

24 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

25 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\Router.php(687): Illuminate\Pipeline\Pipeline->then(Object(Closure))

26 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\Router.php(662): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))

27 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\Router.php(628): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))

28 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Routing\Router.php(617): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))

29 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(165): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))

30 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(128): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))

31 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

32 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))

33 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

34 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))

35 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

36 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle(Object(Illuminate\Http\Request), Object(Closure))

37 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode.php(63): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

38 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))

39 C:\xampp\htdocs\laravuex\vendor\fruitcake\laravel-cors\src\HandleCors.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

40 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Fruitcake\Cors\HandleCors->handle(Object(Illuminate\Http\Request), Object(Closure))

41 C:\xampp\htdocs\laravuex\vendor\fideloper\proxy\src\TrustProxies.php(57): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

42 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(167): Fideloper\Proxy\TrustProxies->handle(Object(Illuminate\Http\Request), Object(Closure))

43 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))

44 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(140): Illuminate\Pipeline\Pipeline->then(Object(Closure))

45 C:\xampp\htdocs\laravuex\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(109): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))

46 C:\xampp\htdocs\laravuex\public\index.php(55): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))

47 C:\xampp\htdocs\laravuex\server.php(21): require_once('C:\\xampp\\htdocs...')

48 {main}

"} `

parkourben99 commented 3 years ago

Checkout the scopes in the config. Looks like you don't have access to something.

You can publish the config by using php artisan vendor:publish --provider="AylesSoftware\XeroLaravel\ServiceProvider"

image

Duncan-dev1 commented 3 years ago

Sorry to bother you this much,i have those already ` <?php

return [ // https://developer.xero.com/documentation/oauth2/scopes 'scope' => 'openid email profile accounting.settings accounting.transactions offline_access',

'redirect_after_authorization_url' => '/home',
'redirect_url' => env('XERO_REDIRECT_URL'),
'client_id' => env('XERO_CLIENT_ID'),
'client_secret' => env('XERO_CLIENT_SECRET'),

]; `

Duncan-dev1 commented 3 years ago

This would be an overkill but could you have 3 or 4 mins so that i can show you what i have in my comp,maybe through google meet?I desperately need some help

parkourben99 commented 3 years ago

If you can get exception message coming back from Xero, that is being thrown by XeroProviderException, that will point you in the right direction.

parkourben99 commented 3 years ago

The exception message might even come back in the url.

Duncan-dev1 commented 3 years ago

yes i am getting this Calcinai\OAuth2\Client\Provider\Exception\XeroProviderException Forbidden means at least the authflow is going all the way.i am also using a demo company,which i suppose should not be a problem

parkourben99 commented 3 years ago

What is the full url when you get that exception?

Duncan-dev1 commented 3 years ago

my url http://127.0.0.1:8000/xero-oauth?code=c25a6e2f866075db04c4c65d62f927be75725c876c352eb6a02344925c64a2e6&scope=openid%20email%20profile%20accounting.settings%20accounting.transactions&state=ab72416c432a371113ce1b948466d1ee&session_state=rO13lSIifv-exe77WRwIYCjG9TcYqyXEQyiQr5j1f9E.88b6fd12b6036d5116070659e8f9348e

Duncan-dev1 commented 3 years ago

To generate the oauth credentials all you need is a controller like this.

<?php

namespace App\Http\Controllers;

use AylesSoftware\XeroLaravel\XeroOAuth;

class XeroOAuthController extends Controller
{
    public function __invoke(XeroOAuth $xeroOAuth)
    {
        return $xeroOAuth->flow();
    }
}

You can then create a route. Route::get('xero-oauth', 'XeroOAuthController');

Then you can navigate to /xero-oauth this will redirect you to xero for authentication. After Xero will redirect back.

Make sure you have XERO_REDIRECT_URL= set to /xero-oauth

Just for clarification,the XERO_REDIRECT_URL= should be to the route that started the oauth process,in this case xero-oauth?

parkourben99 commented 3 years ago

For example

XERO_REDIRECT_URL=https://website.test/xero-oauth
Duncan-dev1 commented 3 years ago

Yes i have it like that,would uninstall and then reinstalling the package help?

Duncan-dev1 commented 3 years ago

I can give you my anydesk you see whats going on my end,if you have a minute

Duncan-dev1 commented 3 years ago

The issue was that xero requires you to use https instead of http.thank you