117 lines
3.9 KiB
PHP
117 lines
3.9 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the HWIOAuthBundle package.
|
|
*
|
|
* (c) Hardware Info <opensource@hardware.info>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace HWI\Bundle\OAuthBundle\OAuth\ResourceOwner;
|
|
|
|
use HWI\Bundle\OAuthBundle\OAuth\Response\PathUserResponse;
|
|
use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
|
use Symfony\Component\Security\Core\Exception\LazyResponseException;
|
|
|
|
/**
|
|
* @author zorn-v
|
|
*/
|
|
final class TelegramResourceOwner extends GenericOAuth2ResourceOwner
|
|
{
|
|
public const TYPE = 'telegram';
|
|
|
|
protected array $paths = [
|
|
'identifier' => 'id',
|
|
'nickname' => 'username',
|
|
'realname' => 'first_name',
|
|
'firstname' => 'first_name',
|
|
'lastname' => 'last_name',
|
|
'profilepicture' => 'photo_url',
|
|
];
|
|
|
|
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
|
|
{
|
|
[$botId] = explode(':', $this->options['client_secret']);
|
|
$parameters = array_merge([
|
|
'bot_id' => $botId,
|
|
'origin' => $redirectUri,
|
|
'return_to' => $redirectUri,
|
|
], $extraParameters);
|
|
|
|
return $this->normalizeUrl($this->options['authorization_url'], $parameters);
|
|
}
|
|
|
|
public function handles(Request $request)
|
|
{
|
|
if (!$request->query->has('code')) {
|
|
$js = '<script>location.href = "?code=" + new URLSearchParams(location.hash.substring(1)).get("tgAuthResult")</script>';
|
|
throw new LazyResponseException(new Response($js));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function getAccessToken(Request $request, $redirectUri, array $extraParameters = [])
|
|
{
|
|
$token = $request->query->get('code', '');
|
|
$token = str_pad(strtr($token, '-_', '+/'), \strlen($token) % 4, '=', \STR_PAD_RIGHT);
|
|
$authData = json_decode(base64_decode($token), true);
|
|
if (empty($authData['hash'])) {
|
|
throw new AuthenticationException('Invalid Telegram auth data');
|
|
}
|
|
if (empty($authData['auth_date']) || (time() - $authData['auth_date']) > 300) {
|
|
throw new AuthenticationException('Telegram auth data expired');
|
|
}
|
|
$botToken = $this->options['client_secret'];
|
|
$checkHash = $authData['hash'];
|
|
unset($authData['hash']);
|
|
ksort($authData);
|
|
$dataCheckStr = '';
|
|
foreach ($authData as $k => $v) {
|
|
$dataCheckStr .= sprintf("\n%s=%s", $k, $v);
|
|
}
|
|
$dataCheckStr = substr($dataCheckStr, 1);
|
|
$secretKey = hash('sha256', $botToken, true);
|
|
$hash = hash_hmac('sha256', $dataCheckStr, $secretKey);
|
|
if ($hash !== $checkHash) {
|
|
throw new AuthenticationException('Telegram auth data check failed');
|
|
}
|
|
|
|
return ['access_token' => $token];
|
|
}
|
|
|
|
public function getUserInformation(array $accessToken, array $extraParameters = [])
|
|
{
|
|
$data = base64_decode($accessToken['access_token']);
|
|
$response = $this->getUserResponse();
|
|
$response->setData($data);
|
|
$response->setResourceOwner($this);
|
|
$response->setOAuthToken(new OAuthToken($accessToken));
|
|
|
|
return $response;
|
|
}
|
|
|
|
protected function configureOptions(OptionsResolver $resolver)
|
|
{
|
|
$resolver->setRequired([
|
|
'client_id',
|
|
'client_secret',
|
|
'authorization_url',
|
|
]);
|
|
|
|
$resolver->setDefaults([
|
|
'authorization_url' => 'https://oauth.telegram.org/auth',
|
|
'auth_with_one_url' => true,
|
|
'state' => null,
|
|
'csrf' => false,
|
|
'user_response_class' => PathUserResponse::class,
|
|
]);
|
|
}
|
|
}
|