создание refresh token php
Добавляем Refresh Token
Повышаем безопасность
Предлагаю читателям перед тем, как двигаться дальше самостоятельно, подумать, что мы можем сделать с безопасностью.
Приведу несколько подходов, которые могут улучшить безопасность. Можете писать в комментариях, какие еще существуют подходы — я их добавлю.
Вспомним, что такое JWT
JWT использует преимущества подхода цифровой подписи JWS (Signature) и кодирования JWE (Encrypting). Подпись не дает кому-то подделать токен без информации о секретном ключе, а кодирование защищает от прочтения данных третьими лицами.
Давайте разберемся, как они могут нам помочь для аутентификации и авторизации пользователя на сайте.
Аутентифика́ция (англ. authentication; от греч. αὐθεντικός [authentikos] – реальный, подлинный; от αὐθέντης [authentes] – автор) — процедура проверки подлинности. В нашем случае, мы проверяем логин + пароль на совпадение с записью в базе даных пользователей.
Авториза́ция (англ. authorization — разрешение, уполномочивание) — предоставление пользователю прав на выполнение определённых действий; а также процесс проверки (подтверждения) данных прав при попытке выполнения этих действий.
Другими словами, аутентификация проверяет легальность пользователя, а затем, если все хорошо, пользователь становится авторизированным, то есть может выполнять разрешенные действия с базой данных. Обычно, эти два процесса совмещаются, поэтому и возникает известная путанница.
Виды токенов
Ключевая идея разделения токенов состоит в том, что, с одной стороны, токены авторизации позволяют нам легко проверять пользователя без участия сервера авторизации, просто сравнением подписей.
В заключение
[Примеры] Авторизация (получение access и refresh token) OAuth 2.0 Google и работа с API Google на PHP
1. Регистрация OAuth 2.0 приложения в Google API Console
1) Зайдите в Google Developers Console и создайте новый проект.
2) Процесс создания нового проекта может занять несколько минут. После создания проекта перейдите на страницу управления этим проектом и зайдите в панель управленя раздела «API и сервисы».
3) В панели управления включите API и сервисы, которые вы планируете использовать.
4) После этого перейдите в раздел «Учетные данные». Нажмите на «Создать учетные данные» — «Идентификатор клиента OAuth».
5) Укажите тип приложения «Веб-приложение».
6) После создания «Веб-приложения» вы получите ID клиента и секретный ключ. Сохраните эти данные.
2. Пример получения токена (access token) для доступа к API Google на PHP
Устанавливаем библиотеку для работы с API Google на PHP:
composer require google/apiclient:»^2.0″
OAuth with PHP Part Two: refreshing & revoking tokens
Heads up, we’ve moved! If you’d like to continue keeping up with the latest technical content from Square please visit us at our new home https://developer.squareup.com/blog
This is a follow up to part 1 that talks about creating access tokens from authorization codes.
At the end of the first part of our PHP journey with OAuth, we had two scripts: an index.php that would begin the OAuth process and a callback.php that would accept the result from Square and use the provided authorization code to create an access token that your application can use to use Square’s APIs on a merchant’s behalf.
Your newly minted access token will work great for about a month, but then your token will expire and your app won’t be able to do anything with Square’s APIs until the merchant reauthorizes the application. That isn’t very convenient for your users, so luckily there is a way to programatically refresh your OAuth credentials without requiring your end users to authorize your application. Refreshing your tokens will only work if your permissions do not change your application’s permissions. Any time you want to change the scopes available to your application, you must reauthenticate with the merchant.
Expiration dates
When you exchange an authorization code for an access token, you’ll get back a json response like this:
You’ll want to keep track of that expires_at time, so that you will be able to refresh the token in time. You can even refresh a token after it is expired, as long as you do it within 15 days of the expiration date.
The refresh endpoint
The endpoint to refresh your access tokens is a little different than most of our endpoints because you need to authorize with your client_secret instead of the access_token in the header. Here is what it looks like with PHP using file_get_contents code:
An important thing to note is that if you have everything correct, but provide an invalid access_token in your request body, you will get a 404 response because the access token cannot be found.
If everything goes well, you should get a response similar to when you first got your access token, with the refresh date now a month after the date you refreshed:
That is all you need to do to refresh your access tokens! Now your application will be able to continue making requests on other merchants’ behalf.
The revoke endpoint
Revoking an access token removes any access it has to Square merchant accounts. This endpoint is accessed similarly to the renew endpoint, with the client_secret in the header:
If your request is successful, then the API will return the following response:
Now the access token that you had created is invalidated, and cannot be used, or refreshed. Your end users will need to authorize your application again in order for your application to be able to use Square’s APIs on their behalf.
The Code
To simplify everything, I’ve included all of the code (including the authorization from part 1) into a single page that will redirect you to Square, create an access token, renew the token and then revoke it all in one go.
Now you should have a complete example in PHP to do everything you can do with OAuth. If you have any questions, leave a comment on this post, and of course take a look at the official Square OAuth documentation.
JWT — как безопасный способ аутентификации и передачи данных
JSON Web Token (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанный на формате JSON. Как правило, используется для передачи данных для аутентификации в клиент-серверных приложениях. Токены создаются сервером, подписываются секретным ключом и передаются клиенту, который в дальнейшем использует данный токен для подтверждения своей личности.
В простом понимании — это строка в специальном формате, которая содержит данные, например, ID и имя зарегистрированного пользователя. Она передается при каждом запросе на сервер, когда необходимо идентифицировать и понять, кто прислал этот запрос.
В этой статье разберу, что такое Access токен, Refresh токен и как с ними работать.
Для дальнейших разборов будет использован токен:
После того, как посетитель прошел авторизацию в нашей системе, указав свой логин и пароль, система выдает ему 2 токена: access token и refresh токен.
После чего посетитель, когда хочет получить с сервера данные, например, свой профиль, вместе с запросом он передает Access токен, как на примере выше. Сервер, получив его проверяет, что он действительный (об этом чуть ниже), вычитывает полезные данные из него (тот же user_id) и, таким образом, может идентифицировать пользователя.
Токен разделен на три основные группы: заголовок, полезные данные и сигнатура, разделенные между собой точкой.
Это можно проверить прям в браузере, выполнив в консоле или js коде:
Вторым блоком идет eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9
Это есть полезные данные, так же закодированные в Base64. После раскодирования получим:
Поскольку необходимо ограничивать токен по времени, поле exp обязательно. По нему можно проверить, актуален ли токен или нет.
Она получается примерно следующим образом:
Берем заголовок, например <"alg":"HS256","typ":"JWT">и кодируем его в base64, получаем ту самую часть eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Тоже самое проделываем с данными eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9
После этого склеиваем их и получаем eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9
Далее эти данные шифруем с помощью нашего алгоритма HMAC-SHA256 и ключа.
Для проверка токена необходимо проделать ту же операцию.
Как только время выйдет, пользователю снова придется проходить авторизацию. Так вот чтобы этого избежать, существует Refresh токен. С помощью него можно продлить Access токен.
У него, обычно, нет какой-то структуры и это может быть некая случайная строка.
Для проекта odo24.ru я использовал следующий подход.
Генерируется Access токен и после случайная строка, например T6cjEbghMZmybUd_fhE
С нашего нового Access токена eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9.E4FNMef6tkjIsf7paNrWZnB88c3WyIfjONzAeEd4wF0 беру последние шесть знаков, получаю Ed4wF0
Склеиваю и получаю рефреш токен T6cjEbghMZmybUd_fhEEd4wF0
Это сделано для привязки Access токена к Refresh. Для получения новых токенов необходимо передать эти два токена. Делается проверка на их связку и только после валидируется Access токен. Если и второй этап прошел успешно, тогда получаем с базы данных по текущему user_id рефреш токен и сверяем с тем, что к нам пришел. Если они совпадают, тогда генерируются новые токены и в базе данных обновляется Refresh токен на новый.
В моем случае я разделил оба токена и храню в разных местах. Access токен нужен только для идентификации пользователя и на клиенте (JS) он не нужен, поэтому он передается в Cookie (http only).
Refresh токен хранится в LocalStorage и используется только когда Access токен перестал быть актуальным.
Представим ситуацию, когда у нас каким-то образом украли Access токен. Да, это уже плохо и где-то у нас брешь в безопасности. Злоумышленник в этом случае сможет им воспользоваться не более чем на 15-30 минут. После чего токен «протухнет» и перестанет быть актуальным. Ведь нужен второй токен для продления.
Если украли Refresh токен, то без Access токена (который недоступен в JS) продлить ничего нельзя и он оказывается просто бесполезным.
Дату протухания внедрил прям в токен с той целью, чтобы не хранить эту информацию где-то в другом месте, например, в базе данных.
Дата содержит год, месяц, день, час и минуты. Хранится в ASCII
Кодирование даты на Golang:
Всю реализацию на Go можно изучить на Github-е
В этой статье попытался рассказать о взаимодействии двух токенов и как ими пользоваться. В сети достаточно много информации о Access токенах, однако мало, как мне показалось, информации о Refresh токенах.
Token, refresh token и создание асинхронной обертки для REST-запроса
В данном туториале мы кратко разберем, как реализовываются REST-запросы к API, требующие, чтобы пользователь был авторизован, и создадим асинхронную «обертку» для запроса, которая будет проверять авторизацию и своевременно ее обновлять.
Данные для авторизации
Сделав REST-запрос к api, куда мы отправили логин и пароль, в ответ мы получаем json следующего формата (значения взяты рандомные и строки обычно длиннее):
Полей в ответе может быть больше, например еще «token_type», «expires_on» и т. д., но, для данной реализации, нам нужны только три поля, приведенные выше.
Давайте их рассмотрим подробнее:
Получение токена
Теперь создадим функцию, которая будет получать json, описанный выше, и сохранять его.
Хранить данные для авторизации мы будем в sessionStorage или localStorage, в зависимости от наших нужд. В первом случае данные хранятся до тех пор, пока пользователь не завершит сеанс или не закроет браузер, во втором случае данные в браузере будут храниться неограниченное время, пока по каким-либо причинам localStorage не будет очищен.
Функция для сохранения токена в sessionStorage:
Функция для получения токена:
Таким образом мы получили токен с полями «access_token», «refresh_token» и «expires_in» и сохранили его в sessionStorage для дальнейшего использования.
Обновление токена
Токен полученный нами ранее имеет ограниченное время жизни, которое задано в поле «expires_in». После того как его время жизни истечет, пользователь не сможет получить новые данные, отправляя данный токен в запросе, поэтому нужно получить новый токен.
Получить токен мы можем двумя способами: первый способ это заново авторизовавшись, отправив логин и пароль на сервер. Но это нам не подходит, т. к. заставлять пользователя каждый раз заново вводить данные авторизации по истечению какого-то отрезка времени — неправильно, это надо делать автоматически. Но хранить где-то в памяти пару логин/пароль для автоматической отправки небезопасно, именно для этого и нужен «refresh_token», который был получен ранее вместе с «access_token» и хранится в sessionStorage. Отправив данный токен на другой адрес, который предоставляет api, мы сможем получить в ответ новый «свежий» токен.
Функция для обновления токена
С помощью кода выше мы перезаписали токен в sessionStorage и теперь по новой можем отправлять запросы к api.
Создание функции-обертки
Теперь создадим функцию, которая будет добавлять данные для авторизации в шапку запроса, и при необходимости их автоматически обновлять перед совершением запроса.
Так как в случае, если срок жизни токена истек, нам надо будет делать запрос нового токена, то наша функция будет асинхронной. Для этого мы будем использовать конструкцию async/await.
Функция-обертка
С помощью кода выше мы создали функцию, которая будет добавлять токен к запросам в api. На эту функцию мы можем заменить fetch в нужных нам запросах, где требуется авторизация и для этого нам не потребуется менять синтаксис или добавлять в аргументы еще какие-либо данные.
Просто достаточно будет «импортнуть» ее в файл и заменить на нее стандартный fetch.