The start of something beautiful
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
<?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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user