|  | 
|  | 1 | +<?php | 
|  | 2 | +/** | 
|  | 3 | + * Trait ClientCredentialsTrait | 
|  | 4 | + * | 
|  | 5 | + * @created      19.09.2024 | 
|  | 6 | + * @author       smiley <[email protected]> | 
|  | 7 | + * @copyright    2024 smiley | 
|  | 8 | + * @license      MIT | 
|  | 9 | + */ | 
|  | 10 | +declare(strict_types=1); | 
|  | 11 | + | 
|  | 12 | +namespace chillerlan\OAuth\Core; | 
|  | 13 | + | 
|  | 14 | +use chillerlan\HTTP\Utils\QueryUtil; | 
|  | 15 | +use Psr\Http\Message\ResponseInterface; | 
|  | 16 | +use function implode; | 
|  | 17 | +use const PHP_QUERY_RFC1738; | 
|  | 18 | + | 
|  | 19 | +/** | 
|  | 20 | + * Implements Client Credentials functionality | 
|  | 21 | + * | 
|  | 22 | + * @see \chillerlan\OAuth\Core\ClientCredentials | 
|  | 23 | + */ | 
|  | 24 | +trait ClientCredentialsTrait{ | 
|  | 25 | + | 
|  | 26 | +	/** | 
|  | 27 | +	 * implements ClientCredentials::getClientCredentialsToken() | 
|  | 28 | +	 * | 
|  | 29 | +	 * @see \chillerlan\OAuth\Core\ClientCredentials::getClientCredentialsToken() | 
|  | 30 | +	 * | 
|  | 31 | +	 * @param string[]|null $scopes | 
|  | 32 | +	 * @throws \chillerlan\OAuth\Providers\ProviderException | 
|  | 33 | +	 */ | 
|  | 34 | +	public function getClientCredentialsToken(array|null $scopes = null):AccessToken{ | 
|  | 35 | +		$body     = $this->getClientCredentialsTokenRequestBodyParams($scopes); | 
|  | 36 | +		$response = $this->sendClientCredentialsTokenRequest(($this->clientCredentialsTokenURL ?? $this->accessTokenURL), $body); | 
|  | 37 | +		$token    = $this->parseTokenResponse($response); | 
|  | 38 | + | 
|  | 39 | +		// provider didn't send a set of scopes with the token response, so add the given ones manually | 
|  | 40 | +		if(empty($token->scopes)){ | 
|  | 41 | +			$token->scopes = ($scopes ?? []); | 
|  | 42 | +		} | 
|  | 43 | + | 
|  | 44 | +		$this->storage->storeAccessToken($token, $this->name); | 
|  | 45 | + | 
|  | 46 | +		return $token; | 
|  | 47 | +	} | 
|  | 48 | + | 
|  | 49 | +	/** | 
|  | 50 | +	 * prepares the request body parameters for the client credentials token request | 
|  | 51 | +	 * | 
|  | 52 | +	 * @see \chillerlan\OAuth\Core\OAuth2Provider::getClientCredentialsToken() | 
|  | 53 | +	 * | 
|  | 54 | +	 * @param string[]|null $scopes | 
|  | 55 | +	 * @return array<string, string> | 
|  | 56 | +	 */ | 
|  | 57 | +	protected function getClientCredentialsTokenRequestBodyParams(array|null $scopes):array{ | 
|  | 58 | +		$body = ['grant_type' => 'client_credentials']; | 
|  | 59 | + | 
|  | 60 | +		if(!empty($scopes)){ | 
|  | 61 | +			$body['scope'] = implode($this::SCOPES_DELIMITER, $scopes); | 
|  | 62 | +		} | 
|  | 63 | + | 
|  | 64 | +		return $body; | 
|  | 65 | +	} | 
|  | 66 | + | 
|  | 67 | +	/** | 
|  | 68 | +	 * sends a request to the client credentials endpoint, using basic authentication | 
|  | 69 | +	 * | 
|  | 70 | +	 * @see \chillerlan\OAuth\Core\OAuth2Provider::getClientCredentialsToken() | 
|  | 71 | +	 * | 
|  | 72 | +	 * @param array<string, scalar> $body | 
|  | 73 | +	 */ | 
|  | 74 | +	protected function sendClientCredentialsTokenRequest(string $url, array $body):ResponseInterface{ | 
|  | 75 | + | 
|  | 76 | +		$request = $this->requestFactory | 
|  | 77 | +			->createRequest('POST', $url) | 
|  | 78 | +			->withHeader('Accept', 'application/json') | 
|  | 79 | +			->withHeader('Accept-Encoding', 'identity') | 
|  | 80 | +			->withHeader('Content-Type', 'application/x-www-form-urlencoded') | 
|  | 81 | +			->withBody($this->streamFactory->createStream(QueryUtil::build($body, PHP_QUERY_RFC1738))) | 
|  | 82 | +		; | 
|  | 83 | + | 
|  | 84 | +		foreach($this::HEADERS_AUTH as $header => $value){ | 
|  | 85 | +			$request = $request->withHeader($header, $value); | 
|  | 86 | +		} | 
|  | 87 | + | 
|  | 88 | +		$request = $this->addBasicAuthHeader($request); | 
|  | 89 | + | 
|  | 90 | +		return $this->http->sendRequest($request); | 
|  | 91 | +	} | 
|  | 92 | + | 
|  | 93 | +} | 
0 commit comments