-
Notifications
You must be signed in to change notification settings - Fork 31
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
I have stored CLIENT ID and CLIENT SECRET in database. Can we connect it based from the database? #45
Comments
The client id and secret identify the application not the user, in the apps i have built, the the xero auth token is stored per user |
Hi @farisiskandar7, @bumperbox is correct, you should only need to store a single set of client credentails as they specify how your application talks to xero, they don't authenticate the user. For more information about the credential storage which identifies the user see here https://github.com/webfox/laravel-xero-oauth2#credential-storage An example UserStorageProvider (assuming you have a nullable json column called <?php
namespace App\Xero;
use App\Models\User;
use Illuminate\Session\Store;
use League\OAuth2\Client\Token\AccessTokenInterface;
use Webfox\Xero\Oauth2Provider;
use Webfox\Xero\OauthCredentialManager;
class UserStorageProvider implements OauthCredentialManager
{
/** @var Oauth2Provider */
protected $oauthProvider;
/** @var Store */
protected $session;
/** @var User */
protected $user;
public function __construct(User $user, Store $session, Oauth2Provider $oauthProvider)
{
$this->use = $user;
$this->oauthProvider = $oauthProvider;
$this->session = $session;
}
public function getAccessToken(): string
{
return $this->data('token');
}
public function getRefreshToken(): string
{
return $this->data('refresh_token');
}
public function getTenantId(): string
{
return $this->data('tenant_id');
}
public function getExpires(): int
{
return $this->data('expires');
}
public function getState(): string
{
return $this->session->get('xero_oauth2_state');
}
public function getAuthorizationUrl(): string
{
$redirectUrl = $this->oauthProvider->getAuthorizationUrl(['scope' => config('xero.oauth.scopes')]);
$this->session->put('xero_oauth2_state', $this->oauthProvider->getState());
return $redirectUrl;
}
public function getData(): array
{
return $this->data();
}
public function exists(): bool
{
return !!$this->user->xero_oauth;
}
public function isExpired(): bool
{
return time() >= $this->data('expires');
}
public function refresh(): void
{
$newAccessToken = $this->oauthProvider->getAccessToken('refresh_token', [
'refresh_token' => $this->getRefreshToken(),
]);
$this->store($newAccessToken);
}
public function store(AccessTokenInterface $token, string $tenantId = null): void
{
$this->user->xero_oauth = [
'token' => $token->getToken(),
'refresh_token' => $token->getRefreshToken(),
'id_token' => $token->getValues()['id_token'],
'expires' => $token->getExpires(),
'tenant_id' => $tenantId ?? $this->getTenantId()
];
$this->user->saveOrFail();
}
public function delete(): void
{
$this->user->xero_oauth = null;
$this->user->saveOrFail();
}
public function getUser(): ?array
{
try {
$jwt = new \XeroAPI\XeroPHP\JWTClaims();
$jwt->setTokenId($this->data('id_token'));
$decodedToken = $jwt->decode();
return [
'given_name' => $decodedToken->getGivenName(),
'family_name' => $decodedToken->getFamilyName(),
'email' => $decodedToken->getEmail(),
'user_id' => $decodedToken->getXeroUserId(),
'username' => $decodedToken->getPreferredUsername(),
'session_id' => $decodedToken->getGlobalSessionId()
];
} catch (\Throwable $e) {
return null;
}
}
protected function data($key = null)
{
if (!$this->exists()) {
throw new \Exception('Xero oauth credentials are missing');
}
$cacheData = $this->user->xero_oauth;
return empty($key) ? $cacheData : ($cacheData[$key] ?? null);
}
}
|
@hailwood - I may be an idiot, but I have tried to implement this unsuccessfully. I have done everything as instructed and I'm referencing this created file that I have put in |
I missed this part in the documentation: |
PS. In the data method, I had to change my $cacheData call to:
to interpret the string correctly. Hope that helps someone. |
Thanks for the feedback @gbrits, |
Not even errors, just one typo, pretty amazing for untested! You sir, are a gentleman and a scholar 🤓 |
Cheers, Side note, if you add a json cast to your User model for |
Oh cool I have never used casts for anything other than dates before. So, as in:
and then I can just do:
? |
I believe so yeah :) |
Change & update line 26: |
I'm trying to implement something like this, but I'm not using User Model, I use another Model to save the credentials, |
@wijaksanapanji just swap out passing in a User model for your custom model, and then replace all instances of |
Do I need to rebind in |
Yes. You'll need to rebind it so you can pass in whatever parameters your custom credential store needs to be instantiated. |
@hailwood I'm using your StorageProvider example for a "Website" class I'm using since my site uses Tenancy (https://tenancy.dev/) for Laravel. In my AppServiceProvider I'm passing through the current website using the Everything seems to work fine until I add an organization. Instead of using the current Website (which is retrieved in the AppServiceProvider) it creates a new record in my websites table and inserts the xero_oauth there. Would you happen to know why this is happening? |
Hi @SamKani92, If I had to guess I'd say that rather than resolving the current Website, it's resolving an empty model which then gets created in the database when we save the xero details. |
I've been trying to use this provider class and can't get it to fully work. It is storing the token json in the db on the user ok but throws an error after clicking 'allow' The class wouldn't work at all unless I added getTenants() to match the implemented OauthCredentialManager: public function getTenants(): ?array
{
return $this->data('tenants');
} Also I had to change the $tenantId to array type on the store method. Any ideas where I might be going wrong? |
Hi everyone! I have a question regarding Laravel-Xero-OAuth2. Is it possible to set the credentials "XERO_CLIENT_ID" and "XERO_CLIENT_SECRET" to be fetched from the user table in the database after authentication? I'm looking forward to your suggestions and solutions. Thanks in advance! |
You can take a look at the config file and check which are variables available or add which one do you prefer: |
Currently, we retrieve the CLIENT ID and CLIENT SECRET from env. This means can I make this package dynamically. I have stored CLIENT ID and CLIENT SECRET in my database so it will connect per user. For a different user, they will have a different CLIENT ID and CLIENT SECRET.
Thank you,
The text was updated successfully, but these errors were encountered: