Ahoj vyvíjím aplikaci v mergadu, která bude získavat přes api URL adresy produktů z feedu. Pročítal jsme dokumentaci tak se chci zeptat jestli jsem to správně pochopil. Nejprve uživatel klikne a přes hook mi dá oprávnění abych mohl pracovat s jeho aplikací. Pak ale abych mohl přistupovat k api potřebuju offline oauth? Přes něj bych měl token se kterým bych se měl připojovat k api? Existuje nějaká ukázka již hotové aplikace, kde by byl tento postup vidět.
Ahoj, chápeš to naprosto správně. Aplikace by měla pracovat v tzv. offline režimu, tedy bude vyžadovat OAuth2 refresh_token grant type. Máme ukázku aplikace, která pracuje v online režimu (authorization_code grant type), viz logbook, bohužel zatím nikde nemáme příklad aplikace, která používá refresh_token. Ale snad zvládneme kostru nebo ukázku takové aplikace do konce týdne někde vystavit (díky @michalwiglasz), dáme pak vědět.
Taky teď pracujeme na vylepšení dokumentace, tutoriálu apod., takže by snad začátkem příštího měsíce mohly být některé věci z dokumentace jasnější.
Zkusím to stručně popsat:
Aplikace se načte uživateli v rozhraní Mergada přes iframe, jako první krok by měla aplikace přes OAuth požádat o online token, tj. přesměrovat uživatele na URL v dokumentaci:
Ta stránka authorize udělá nějaká ověření a nakonec přesměruje prohlížeč na redirect_uri. Tam by aplikace měla udělat jen to, že na základě code, které dostane v URL pošle POST požadavek o token na https://app.mergado.com/oauth2/token/. Zpátky dostane JSON s tokenem a expirací, ten si uloží do session a přesměruje uživatele kamkoliv potřebuje (ideálně na stránku, kterou si původně otevřel, v Nette se hodí dvojice metod presenteru storeRequest a restoreRequest.
A to je celé, uživatel je autorizovaný, aplikace má validní access token. Pokud vyprší, lze toto kolečko zopakovat, ale já to dělám tak, že si požádám o offline token. Tam je to velmi jednoduché, stačí jeden GET, netřeba žádného přesměrování.
Nicméně, pokud jde o nějaký úkol na pozadí spouštěný cronem, je správná cesta offline token - ostatně to ani neběží v prohlížeči, takže není co kam přesměrovávat. Na to stačí tenhle kousek kódu (využívá tu zmíněnou knihovnu):
<?php
use \League\OAuth2\Client\Provider\AbstractProvider;
class OfflineAuthenticator extends BaseOauthAuthenticator
{
public function authenticate($storeRequestCallback = NULL)
{
if (!$this->entityId) {
throw new \Exception("Entity ID must be set before authenticating.");
}
$this->token = $this->tokenStorage->getToken($this->entityId, ITokenStorage::OFFLINE);
if (!$this->token) {
$this->token = $this->oauthProvider->getAccessToken('refresh_token', [
'refresh_token' => base64_encode($this->entityId),
]);
$this->tokenStorage->storeToken($this->token, ITokenStorage::OFFLINE);
}
}
public function refresh()
{
$this->token = NULL;
$this->tokenStorage->deleteToken($this->entityId, ITokenStorage::OFFLINE);
$this->authenticate();
}
public function getAuthenticatedRequest($method, $url, $params)
{
if (!$this->token) {
throw new \Exception("Cannot create request: client not authenticated");
}
if ($this->token->hasExpired()) {
$this->refresh();
}
return $this->oauthProvider->getAuthenticatedRequest($method, $url, $this->token, $params);
}
}
Není to úplně kompletní příklad, ale je tam vše důležité.