Модуль авторизации для сайта, использующий Wargaming.net Public API

в 19:55, , рубрики: api, wargaming.net

С момента выхода WG P API в бета тест, самым популярным вопросом стал «как сделать авторизацию на сайте».
Так уж сложилось — человек существо ленивое.
Дабы упростить жизнь другим участникам Wargaming Developer Partner Program, хочу поделиться свои опытом создания модуля авторизации для сайта.

Варианта два.
1. Использовать OpenID
Логику процесса авторизации wargaming уже описал, статей об OpenID на хабре так же достаточно.
2. Использование методов API для создания модуля авторизации.
Я не буду описывать плагины для всех популярных CMS — опишу лишь общую схему и приведу пример кода.

Теория

Для аутентификации пользователей, на данный момент, у WG API, есть три метода:
auth/login — метод используется для аутентификации пользователя — получения access_token.
auth/prolongate — с помощью этого метода можно продлить access_token без участия пользователя
auth/logout — метод для уничтожения access_token

access_token используется для получения приватной информации об аккаунте игрока — информация о технике, которая есть в ангаре, идентификаторы аккаунтов друзей игрока и прочее.

Для получения access_token, как уже сказано выше, используется метод auth/login, который отправляет информацию о статусе авторизации по адресу указанному в параметре redirect_uri

Один из разработчиков WG сообщил:

Принято решение расширить возможности метода auth/login и будет введено разделение (при успешно введенных сведениях):
1) На один URL будет сделана переадресация пользователя;
2) На второй будет отправлены сведения по авторизации (методом POST или GET).

Вернемся к теории.

Алгоритм работы

Генерация ссылки для перенаправления пользователя

Прежде всего, нужно обратиться к методу auth/login с просьбой сгенерировать URL для дальнейшего редиректа пользователя.
Для этого шлем запрос к
https://api.worldoftanks.ru/wot/auth/login/?application_id=<application_id>&redirect_uri=<redirect_uri>&nofollow=1
, где <application_id> — application_id приложения, для получения которого нужно зарегистрироваться в кабинете разработчика;
<redirect_uri> — URL скрипта обработчика;
Значение параметра nofollow=1, что бы метод возвратил URL в теле ответа вместо редиректа.

Наш auth.php будет выполнять сразу две задачи: генерировать ссылку и производить редирект по ней, или же производить авторизацию, если пользователь вернулся после редиректа.

Перенаправление пользователя на сайт WG

В примере, скрипт сам делает перенаправление пользователя после генерации ссылки.
Изменив пару строк кода, можно замутить это с помощью javascript, дабы написать «Загрузка...» (или вставить loader.gif) после клика по кнопке «Войти» — это всегда выглядит красиво.
В то время, пока пользователь восхищается надписью (ну или картинкой), js отправит запрос к скрипту, тот отправит запрос к api, api ответит скрипту, скрипт вернет ссылку, и наконец таки js перенаправит пользователя по ней.
Напрямую отправлять запрос к API js-ом нельзя, поскольку правилами WG DPP, запрещено разглашать application_id приложения.

Возврат пользователя

После того как игрок авторизируется на сайте WG и разрешит нашему сайту просматривать его детальную статистику он будет перенаправлен на
<redirect_uri>?&status=ok&access_token=<access_token>&nickname=<_nickname>&account_id=<account_id>&expires_at=<expires_at>
Если не произойдет никаких ошибок…
Таким образом наш скрипт получит данные:
status access_token nickname account_id expires_at
Но пока этим данным нельзя доверять!

Проверка данных, которые получили после возврата пользователя

Если мы планируем делать авторизацию, то должны быть уверенны, что полученные данные правдивы и переданы именно с сайта WG, а не прописаны вручную.
Вот именно из-за этого момента и будет переделана работа метода — на данный момент, мы не можем точно знать, пришел ли игрок, с этими параметрами, с сайта wargaming или сам набрал их в адресной строке.
$_SERVER['HTTP_REFERER'] не дает полной гарантии.

Для того, что бы проверить правдивость данных мы воспользуемся методом auth/prolongate
Это один из вариантов. Кроме пролонга мы можем так же сделать запрос на account/info с полученным токеном — если удастся получить приватные данные, значит все ок.
Воспользовавшись им мы сможем проверить, действительный ли access_token был передан, и кому (account_id) он принадлежит.
Если все в порядке, мы запишем нужные данные в БД, установим пользователю куки — сделаем всё то, что нужно делать при стандартной авторизации с вводом логина/пароля.

Практика

<?
define('URL','http://example.com/WGDPPAuth.php');//адрес по которому доступен данный скрипт
define('APPLICATION_ID','demo');//application_id приложения
if(empty($_GET['status'])){//генерируем ссылку и перенаправяем пользователя
	$context = stream_context_create(
		array('http' =>
			array(
				'method'  => 'POST',
				'header'  => 'Content-type: application/x-www-form-urlencoded',
				'content' => http_build_query(
					array(
						'nofollow' => 1,
						'expires_at' => 300,
						'redirect_uri' => URL,
						'application_id' => APPLICATION_ID
					)
				)
			)
		)
	);
	$data=json_decode(@file_get_contents('https://api.worldoftanks.ru/wot/auth/login/', false, $context),true);
	if($data['status']=='ok'){
		header ('Location: '.$data['data']['location']);
		exit();
	}else{
		exit('Не удалось получить ссылку для перенаправления.');
	}
}elseif(isset($_GET['status']) && isset($_GET['access_token']) && isset($_GET['nickname']) && isset($_GET['account_id']) && isset($_GET['expires_at'])){//если пользователь попал на страницу с параметрами, которые устанавливает метод auth/login
	if($_GET['status']!="ok"){
		$error_code=500;
		if(preg_match('/^[0-9]+$/u', $_GET['code'])){
			$error_code=$_GET['code'];
		}
		exit("Ошибка авторизации. Код ошибки: $error_code");
	}elseif($_GET[expires_at]<time()){
		exit("Ошибка авторизации. Срок действия access_token истек.");
	}else{
		$context = stream_context_create(
			array('http' =>
				array(
					'method'  => 'POST',
					'header'  => 'Content-type: application/x-www-form-urlencoded',
					'content' => http_build_query(
						array(
							'expires_at' => 14*24*60*60,
							'access_token' => $_GET['access_token'],
							'application_id' => APPLICATION_ID
						)
					)
				)
			)
		);
		$data=json_decode(@file_get_contents('https://api.worldoftanks.ru/wot/auth/prolongate/', false, $context),true);//подтверждаем правдивость полученных параметров
		if($data['status']=="ok"){
			$access_token=$data[data][access_token];
			$expires_at=$data[data][expires_at];
			$account_id=$data[data][account_id];
			//здесь вам нужно установить пользователю куки, записать его токен в БД, сделать все то, что сочтете нужным.
			exit('Это пользователь с id <b>'.$account_id.'</b><br />Токен <b>'.$access_token.'</b>, он подтвержден и действует до <b>'.date("d.m.Y H:i:s",$expires_at).'</b>');
		}else{
			exit('access_token не подтвержден');
		}
	}
}else{
	$error_code=500;
	if(preg_match('/^[0-9]+$/u', $_GET['code'])){
		$error_code=$_GET['code'];
	}
	exit("Произошла ошибка. Код ошибки: $error_code");
}
?>

DEMO

Автор: Samber

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js