OAuth + php тутор и пара вопросов

Здравствуйте! Делаю простенькую авторизацию осмюзеров на ресурсе.
Есть кое-какие наработки, хочу ими поделиться, а также уточнить несколько моментов.

Для неизвестного юзера, который пришел на сайт мы должны сгенерировать линк, по которому он пройдет на сайт осма и подтвердит себя, разрешит нашему ресурсу использовать свои данные.
Для генерации такого линка необходимо использовать токен и ключ, которые Вам выдаст осм при регистрации приложения.
Для регистрации мы идем в свой профиль, заходим на вкладку “настройки OAuth” и жмем “Зарегистрировать ваше приложение”.
Приложений может быть у Вас несколько. Если это так, то вы увидите их список… все сделано очень удобно.
Вобщем мы попали на страницу регистрации приложения:

Тут мы забили название проги, линк на Ваш сервис… он, насколько я понял, значения не имеет…
и самое главное линк обратного вызова. Это будет скрипт на Вашем сервисе с которым осм сможет общаться)

Жмем на “Зарегистрировать” и попадаем на страницу с данными Вашего приложения:

Теперь нам нужно написать скрипты для работы с осмом.

Скрипт генерации линка, по которому пользователь может авторизироваться на осме, в простом варианте выглядит так:


<?php
$req_url = 'http://www.openstreetmap.org/oauth/request_token';     // OSM Request Token URL
$authurl = 'http://www.openstreetmap.org/oauth/authorize';         // OSM Authorize URL
$acc_url = 'http://www.openstreetmap.org/oauth/access_token';      // OSM Access Token URL
$api_url = 'http://api.openstreetmap.org/api/0.6/';                // OSM API URL

$conskey = 'ключик Вашего приложения';
$conssec = 'секрет Вашего приложения';

try {
     $oauth = new OAuth($conskey,$conssec,OAUTH_SIG_METHOD_HMACSHA1,OAUTH_AUTH_TYPE_URI);
     $request_token_info = $oauth->getRequestToken($req_url);
     $_SESSION['secret'] = $request_token_info['oauth_token_secret'];
     echo "<a href=\"".$authurl."?oauth_token=".$request_token_info['oauth_token']."\">Войти</a>";
} catch(OAuthException $E) {
     print_r($E);
}
?>

Как видим тут юзается расширение php OAuth… подробнее про него можно почитать тут: PHP: OAuth - Manual
Также я храню переменную $_SESSION[‘secret’] в сессии, которая к этому моменту уже создана.
В результате работы скрипта мы получаем ссылку вида: httр://www.openstreetmap.org/oauth/authorize?oauth_token=NDbOqI62xgzh2UowaZqqm
Все очень просто… запустили - получили линк, запустили еще раз, новый линк.

Перейдя по этой ссылке с Вашего ресурса, юзер попадает на страницу осма… и там он видит:

Он отмечает галочками то, что нужно вашему ресурсу расшарить и по клику на “Save changes” переходит на ваш ресурс по линку обратного вызова.

Скрипт обратного вызова получает переменную oauth_token т.е. осм перенаправляет Вас обратно на сайт по линку обратного вызова, который выглядит так: httр://myosm.com/oauth_callback?oauth_token=eUir4VsKEuDlc4movbg
Код скрипта:


<?php
$req_url = 'http://www.openstreetmap.org/oauth/request_token';     // OSM Request Token URL
$authurl = 'http://www.openstreetmap.org/oauth/authorize';         // OSM Authorize URL
$acc_url = 'http://www.openstreetmap.org/oauth/access_token';      // OSM Access Token URL
$api_url = 'http://api.openstreetmap.org/api/0.6/';                // OSM API URL

$conskey = 'ключик Вашего приложения';
$conssec = 'секрет Вашего приложения';

if(isset($_GET['oauth_token']) && isset($_SESSION['secret']))
{
try {
       $oauth = new OAuth($conskey, $conssec, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
       $oauth->enableDebug();

       $oauth->setToken($_GET['oauth_token'], $_SESSION['secret']);
       $access_token_info = $oauth->getAccessToken($acc_url);

       $_SESSION['token'] = strval($access_token_info['oauth_token']);
       $_SESSION['secret'] = strval($access_token_info['oauth_token_secret']);

       $oauth->setToken($_SESSION['token'], $_SESSION['secret']);

       /// получаем данные пользователя через /api/0.6/user/details
       $oauth->fetch($api_url."user/details");
       $user_details = $oauth->getLastResponse();
       // выводим ответ
       echo str_replace("\n", "<br/>", htmlentities($oauth->getLastResponse()))."<br/><br/>";

       // парсим ответ, получаем имя осмопользователя и его id
       $xml = simplexml_load_string($user_details);       
       $_SESSION['osm_id'] = strval ($xml->user['id']);
       $_SESSION['osm_user'] = strval($xml->user['display_name']);

       // вывожу все это
       echo $_SESSION['osm_id']."<br/>";
       echo $_SESSION['osm_user']."<br/>";
       echo $_SESSION['token']."<br/>";
       echo $_SESSION['secret'];
       echo "<br/><br/>";


       /// тут мы можем создать юзера в своей базе и сохранить его osm_id, osm_user, token? и secret?.

/*  
       // пример получения настроек юзера
       $oauth->fetch($api_url."user/preferences");
       echo str_replace("\n", "<br/>", htmlentities($oauth->getLastResponse()))."<br/><br/>";

       // пример создания чейнджсета. ВНИМАНИЕ тут уже используем метод PUT... OAUTH_HTTP_METHOD_PUT
       $changeset = "<osm> <changeset> <tag k=\"created_by\" v=\"My OSM Service\"/>";
       $changeset = $changeset."<tag k=\"comment\" v=\"Test changeset\"/> </changeset> </osm>";
       $oauth->fetch($api_url."changeset/create", $changeset, OAUTH_HTTP_METHOD_PUT);
       $idchangeset = str_replace("\n", "<br/>", htmlentities($oauth->getLastResponse()));
       echo $idchangeset."<br/><br/>";

       // ну и закрываем чейнджсет.
       $oauth->fetch($api_url."changeset/".$idchangeset."/close", "", OAUTH_HTTP_METHOD_PUT);
       echo str_replace("\n", "<br/>", htmlentities($oauth->getLastResponse()))."<br/><br/>";
*/
} catch(OAuthException $E) {
       print_r($E);
}
}else
{
       if(!isset($_SESSION['secret'])) echo "Нет секрета!<br/><br/>";
       if(!isset($_GET['oauth_token'])) echo "Нет токена!<br/><br/>";
}
?>

Тут мы получили возможность работать с API и можем сделать все что оно позволяет.
Не совсем понятно что нужно хранить в базе чтобы повторно не производить авторизацию пользователя… насколько я понял достаточно хранить переменные $_SESSION[‘token’] и $_SESSION[‘secret’], которые я отметил знаками вопроса. Но это я еще не проверил.

Далее хотелось бы получить через API почту юзера! Это скорее даже обязательное условие, иначе с такой системой авторизации я работать не смогу.
Имя пользователя тоже уникально, но многие движки типа modX (ну очень классная вещь!), на котором я леплю все это дело, требуют мыло для создания пользователя. Вводить одно и тоже мыло для всех или какое-то бредовое - не выход.
Есть ли у каждого пользователя какой-нибудь уникальный ящик на осме? Например, что-нибудь имя@osm.org… чтобы я его использовал как ящик юзера не зная его настоящего ящика.
Не понимаю почему разработчики не дают почту через АПИ, ведь пользователь сам может подтвердить согласие на передачу своего адреса нашему сервису…
Вобщем я очень долго плевался, но когда разобрался с OAuth все показалось красивым и удобным… я начал плеваться вновь, когда не смог получить адрес почты(

Кто знает как обойти проблему с этой почтой? Как получить страну, город проживания… параметры юзера вобщем… осм апи ничего не выдает(

Я, думаю, если не удастся как-то этот вопрос решить, то придется сперва выдавать юзеру форму логина/пароля и после этого логиниться втихушку CURL’ом на страничку осма, авторизировать приложение OAuth и привязывать его логин к почте, которую он ввел, а пароль не запоминать.
Это конечно криво, но зато даст хоть какую-нибудь валидную почту осмоюзера.

Кстати, в настройках ящик можно менять, так что жестко привязываться нужно именно к логину… вобщем все запутанно и нужно разбираться(

Не понятно как писать комменты, устанавливать друзей и т.д. в API я вроде бы такого не увидел, а где еще посмотреть не знаю.

Скрипты кривоваты, написано для тестов, но рабочие… кто увидит явные ошибки отпишитесь, пожалуйста.

Спасибо за внимание!

Я думаю вам придется пересмотреть концепцию.
Когда в ОСМ запретили анонимное редактирование (кстати, при этом все старые анонимные правки остались анонимными),
то клялись и божились, что никогда и ни при каких обстоятельствах (кроме как предусмотренных британским законодательством) e-mail адреса
передаваться не будут. ОСМ все-таки не какой-нибудь там facebook или фконтакте.

usm78-gis, это понятно, но ведь базу мыл никто сливать и не собирается.
Я же с согласия пользователя прошу только его мыло! Не просто же через API: дайте мне адреса пользователя с вот этими id.

Впрочем, тут действительно придется выкручиваться по-другому… т.к. почта может меняться и даже ник.
В базе нужно жестко привязываться к тому, к чему привязан осм (id осмоюзеров), либо делать вообще отдельную регу и связывать свои логины с осмовскими… но это бардак. Хочется чтобы все было красиво.

Вот был бы у каждого осмопользователя постоянный ящик вида user_id@osm.org, (где user_id айдишник осмоюзера), который автоматом отсылал бы все что на него приходит на текущую почту юзера. Тогда бы можно было к нему привязываться и все бы работало без проблем.

Пока я надумал следующее…
Логин привяжу к мылу user_id@osm.org и пофиг что оно не существует, туда ничего все равно слать не буду.
Имя пользователя буду сверять с именем на осме при каждом начале сессии пользователя.
Не будет стандартного метода оповещения пользователей через мыло, но этого и не нужно. Т.к. каким-то макаром можно отправлять сообщения юзеру, но я пока не понял как.

Thank you for sharing this code. If i want to add, for example, the following point

name: Musen & Elefanten
city: Gotham City
address: Vestergade 21
longitude: 12.5699
latitude: 55.6774
category: pub

how to do that using APIs? I can do it manually using the website, but how to do the same with APIs?