Статьи

PHP OAuth-провайдер: аутентификация пользователя

Я работал с OAuth , как с поставщиком, так и с потребителем, и на данный момент не так много документации по PHP, поэтому я решил поделиться своим опытом в этой серии статей. Это относится к стабильной спецификации OAuth 1.0a, однако OAuth2 уже начал использоваться (и сильно отличается). В этой статье используется расширение pecl_oauth, и оно основано на публикации поставщика OAuth Rasmus . Этот пост является третьим в серии, следуя за начальными требованиями и о том, как обращаться с токенами запросов .

Этот этап, вероятно, наиболее знаком нам как разработчикам, поскольку это просто форма входа в систему. Потребитель отправит нам пользователя по URL-адресу, который мы указали в токене запроса, и у пользователя будет ключ ключа токена запроса в качестве параметра. Контроль доступа на этой странице будет выглядеть так же, как и на остальной части сайта; если у пользователя уже есть сеанс, то страница отображается, в противном случае они должны войти в систему, чтобы увидеть его.

Запросить токен

Прежде всего нам нужно убедиться, что предоставленный токен запроса действителен. Для меня код выглядит примерно так:

  $sql = 'SELECT request_token FROM oauth_request_tokens
WHERE request_token = ' . $this->db->escape($token) . '
AND authorised_user_id IS NULL';
$query = $this->db->query($sql);

$result = $query->result();
if(count($result) > 0) {
return true;
}
return false;

Жетоны запроса могут использоваться только один раз, поэтому, если с этим пользователем уже связан пользователь, что-то не так, и мы не должны его принимать. Если токен существует и ожидает информацию о пользователе, то это все хорошо, и мы можем идти дальше.

Предоставить или Отказать

Как только мы узнаем, кто пользователь, и проверим токен, мы дадим им возможность предоставить или запретить запрашиваемый доступ. В моей системе я помещаю токен запроса в сеанс пользователя, а не помещаю его в форму, а затем снова принимаю его, просто чтобы быть уверенным, что ничего неожиданного не происходит. В зависимости от того, принимает пользователь или нет, мы предпримем различные действия.

Отрицать

Это самый простой случай, поэтому давайте сначала рассмотрим его. Если пользователь отказывает в доступе, мы удаляем этот токен запроса. Он может быть использован только один раз, и если пользователь отклонил его, токен становится недействительным. Вы можете буквально удалить его или пометить как недействительный — мои удаляются, так что мне не нужно забывать возвращаться и очищать таблицы позже.

Грант

Если пользователь предоставляет доступ, нам нужно хранить некоторую информацию на этом этапе. Сначала мы генерируем код верификатора. Мое приложение поддерживает параметр «oob», который означает, что пользователи иногда будут повторно вводить код из одного приложения в другое, поэтому я сокращаю его, чтобы сделать это проще! На самом деле, это тривиально (прочитайте комментарии, чтобы найти лучшие способы сделать это, я уверен, что люди предложат некоторые из них!)

substr(md5(rand()), 0, 6);

Затем мы берем код верификатора и user_id и добавляем их в нашу таблицу против соответствующего токена запроса. Напоминаем, что это структура нашей таблицы:

desc oauth_request_tokens;
+----------------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| consumer_key | varchar(30) | NO | | NULL | |
| request_token | varchar(8) | NO | | NULL | |
| request_token_secret | varchar(32) | NO | | NULL | |
| callback | varchar(400) | YES | | NULL | |
| verification | varchar(20) | YES | | NULL | |
| authorised_user_id | int(11) | YES | | NULL | |
| created_date | timestamp | NO | | CURRENT_TIMESTAMP | |
+----------------------+--------------+------+-----+-------------------+----------------+


Мы просто соответствующим образом обновляем столбцы проверки и authorised_user_id, затем перехватываем обратный вызов, чтобы мы могли перенаправить пользователя обратно к потребителю; мой код выглядит следующим образом:

$verification_code = substr(md5(rand()), 0, 6);
$sql = 'UPDATE oauth_request_tokens SET authorised_user_id = '
. $this->db->escape($user_id) . ',
verification = "' . $verification_code . '"
WHERE request_token = ' . $this->db->escape($token);
$query = $this->db->query($sql);

if ($this->db->affected_rows() == 1) {
$fetch_sql = 'SELECT callback, verification FROM oauth_request_tokens
WHERE request_token = ' . $this->db->escape($token);
$fetch_query = $this->db->query($fetch_sql);

$result = $fetch_query->result();
return $result[0];
}

 

Коды проверки

Если у потребителя был URL-адрес обратного вызова, мы просто возвращаем ему пользователя с кодом верификатора, прикрепленным в качестве параметра, в противном случае мы выводим верификатор для пользователя, чтобы он мог принять и использовать его в соответствии с инструкциями приложения потребителя.

 if($oauth_info->callback == "oob") {
// special case, we can't forward the user on so just display verification code
$view_data['verification'] = $oauth_info->verification;
} else {
// add our parameter onto the URL
if(strpos($oauth_info->callback, '?' !== false)) {
$url = $oauth_info->callback . '&';
} else {
$url = $oauth_info->callback . '?';
}
$url .= 'oauth_token=' . $oauth_info->verification;
redirect($url);
exit; // we shouldn't be here
}

Проверенный

На этом этапе пользователь авторизовал (или нет) токен запроса, а у потребителя есть код верификатора. Последний шаг в танце — это обмен известной информацией на действительный токен доступа, о котором мы расскажем в следующем посте.

От http://www.lornajane.net/posts/2011/PHP-OAuth-Provider-Authenticate-User