diff --git a/src/Services/InfoProviderSystem/Providers/BuerklinProvider.php b/src/Services/InfoProviderSystem/Providers/BuerklinProvider.php index 610e2ac5..5006f6f5 100644 --- a/src/Services/InfoProviderSystem/Providers/BuerklinProvider.php +++ b/src/Services/InfoProviderSystem/Providers/BuerklinProvider.php @@ -62,52 +62,16 @@ class BuerklinProvider implements BatchInfoProviderInterface */ private function getToken(): string { - // Cache token to avoid hammering the auth server on every request - $cacheKey = 'buerklin.oauth.token'; - $item = $this->partInfoCache->getItem($cacheKey); - - if ($item->isHit()) { - $token = $item->get(); - if (is_string($token) && $token !== '') { - return $token; - } + //Check if we already have a token saved for this app, otherwise we have to retrieve one via OAuth + if (!$this->authTokenManager->hasToken(self::OAUTH_APP_NAME)) { + $this->authTokenManager->retrieveROPCToken(self::OAUTH_APP_NAME, $this->settings->username, $this->settings->password); } - // Buerklin OAuth2 password grant (ROPC) - $resp = $this->client->request('POST', 'https://www.buerklin.com/authorizationserver/oauth/token/', [ - 'headers' => [ - 'Accept' => 'application/json', - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => [ - 'grant_type' => 'password', - 'client_id' => $this->settings->clientId, - 'client_secret' => $this->settings->secret, - 'username' => $this->settings->username, - 'password' => $this->settings->password, - ], - ]); - - $data = $resp->toArray(false); - - if (!isset($data['access_token'])) { - throw new \RuntimeException( - 'Invalid token response from Buerklin: HTTP ' . $resp->getStatusCode() . ' body=' . $resp->getContent(false) - ); + $token = $this->authTokenManager->getAlwaysValidTokenString(self::OAUTH_APP_NAME); + if ($token === null) { + throw new \RuntimeException('Could not retrieve OAuth token for Buerklin API.'); } - $token = (string) $data['access_token']; - - // Cache for (expires_in - 30s) if available - $ttl = 300; - if (isset($data['expires_in']) && is_numeric($data['expires_in'])) { - $ttl = max(60, (int) $data['expires_in'] - 30); - } - - $item->set($token); - $item->expiresAfter($ttl); - $this->partInfoCache->save($item); - return $token; } diff --git a/src/Services/OAuth/OAuthTokenManager.php b/src/Services/OAuth/OAuthTokenManager.php index 9c22503b..7f092e24 100644 --- a/src/Services/OAuth/OAuthTokenManager.php +++ b/src/Services/OAuth/OAuthTokenManager.php @@ -159,4 +159,21 @@ final class OAuthTokenManager return $this->saveToken($app_name, $access_token); } + + /** + * Retrieves an access token for the given app name using the client ROPC grant (so no user flow is needed) + * The app_name must be registered in the knpu_oauth2_client.yaml + * The token is saved to the database, and afterwards can be used as usual + * @param string $app_name + * @return OAuthToken + */ + public function retrieveROPCToken(string $app_name, string $user, string $password): OAuthToken + { + $client = $this->clientRegistry->getClient($app_name); + $access_token = $client->getOAuth2Provider()->getAccessToken('password', [ + 'username' => $user, + 'password' => $password + ]; + return $this->saveToken($app_name, $access_token); + } } \ No newline at end of file