Инструкция по авторизации

В этой инструкции описаны шаги по авторизации на MedMe EHR сервере. Инструкция рассматривает процесс авторизации с точки зрения клиентского приложения. С детальным описанием распределенного механизма авторизации/аутентификации пользователя на MedMe EHR сервере можете ознакомиться здесь.

Для тестирования вам понадобится установленный и корректно настроенный MedMe EHR Server на стороне клиники.

Для тестирования вам понадобится в МИС тестовый пациент с вашим номером телефона.

Типы авторизации: первичная и повторная

Сценарий первичной авторизации применяется на стороне клиентского приложения в случае, когда пользователь первый раз заходит в раздел "Электронная Медицинская Карта" (ЭМК). Это легко можно проверить, поскольку в результате аутентификации пользовательскому приложению будет возвращена подпись аутентификации (user_sign) — уникальная произвольная строка символов. Пользовательское приложение должно сохранить подпись аутентификации внутри локального персистентного хранилища. Таким образом, если в хранилище пользовательского приложения нет подписи аутентификации, то следует применять данный сценарий авторизации. Если же в хранилище есть подпись аутентификации (user_sign), то должен применяться сценарий повторной авторизации.

В случае первичной авторизации — когда пользователь первый раз заходит в раздел ЭМК — необходимо привязать профиль пользователя в системе GBooking с записью о пациенте на стороне MedMe EHR Server. Для этого необходимо сначала получить сессию пользователя на платформе GBooking, затем получить токен обмена и затем сделать попытку привязки пользователя. Указанные шаги детально описаны ниже.

С точки зрения конечного пользователя приложения, когда он заходит в раздел ЭМК, появляется форма ввода аутентификационных данных, таких как ФИО, дата рождения и другие. Эта форма может быть предварительно заполнена данными из настроек профиля приложения. Пользователь заполняет эту форму и, в случае успешной аутентификации, он видит свои мед данные (в случае ошибки он видит сообщение о том, что по введенным данным не удалось найти пациента в данной клинике и необходимо обратиться в данную клинику для разрешения ситуации).

В случае повторной авторизации на стороне MedMe EHR Server вы должны передать параметр user_sign в запросе на подтверждение OTP. Внутри этого запроса на сторону EHR сервера будут отправлены креденшиалы и приложение сможет пользоваться той же самой парой user, token и в запросах к серверу мед данных.

В данном сценарии пользователь приложения должен перейти в раздел ЭМК без каких-либо авторизаций.

Общий сценарий авторизации

Общий сценарий логина, включающий оба случая и первичную и повторную авторизации:

  1. Выполняем запрос patient.get_patient к ЭМК серверу
  2. Если пришла ошибка авторизации выполняем запрос на сервер авторизации на получение токена обмена
  3. Если пришла ошибка авторизации — значит токен истек — необходимо перелогиниться
  4. Если токен обмена получен, запрашиваем у пользователя данные, выполняем запрос на аутентицикацию.

Пример реализации данного сценирия на typescript (функция getAuthenticatedPatient).

Пример вызова функции getAuthenticatedPatient.

Шаг 1. Авторизация через OTP

Авторизация с использованием подтверждения по номеру телефона в данном случае имеет принципиальное значение, поскольку на стороне EHR при аутентификации мы опираемся на номер телефона пациента. Нам важно удостовериться, что пользователю, выполняющему запрос на аутентификацию, действительно принадлежит этот номер телефона.

Желательно использовать сторонний, надежный сервис OTP (например, у вашего провайдера), чтобы иметь возможность проверки принадлежности номера телефона на стороне ЭМК у стороннего источника. Это увеличивает защищенность данного метода проверки, поскольку даже в случае взлома сервера авторизации гарантирует верификацию номера телефона.

1. Получение OTP на номер телефона

Чтобы получить смс с OTP кодом авторизации выполните следующий запрос:

curl -v -H 'Origin:http://mydomain.com' 'http://apiv2.gbooking.ru/send_sms?businessID=4000000006762&phone_country=7&phone_area=985&phone_number=3596605'

Укажите в запросе свой номер телефона.

В ответе будет HEADER Set-Cookie, похожий на такой:

Set-Cookie: sms=s%3Aj%3A%7B%22business%22%3A%224000000006762%22%2C%22phone_country%22%3A%227%22%2C%22phone_area%22%3A%22985%22%2C%22phone_number%22%3A%223596605%22%2C%22code%22%3A%22a23cc3ea-6be0-4fe8-877e-245927a9a08f%22%7D.7qJaRYY4516GP2CkbNilc9B4FvU8R1LpxxsdxEF4cDw; Max-Age=600; Domain=.gbooking.ru; Path=/; Expires=Sat, 21 Sep 2019 19:58:42 GMT; HttpOnly

Вам нужно будет передать в следующем запросе на подтверждение кода OTP эту куку (строку "sms=s%3Aj..." до точки с запятой).

Есть аналогичный запрос с использованием OAuth2 авторизации (предварительно, вам нужно будет зарегистрировать свое приложение):

curl -v -H 'Origin:http://mydomain.com' -XGET 'http://oauthv2.gbooking.ru/sms/code?businessID=4000000006762&phone_country=7&phone_area=985&phone_number=3596605'

В ответ придет json, в котором будет параметр token. Так же, на указанный телефон должна прийти смс с кодом. Оба эти значения пригодятся в следующем запросе.

Если вы работаете с сетью бизнесов, то вместо параметра businessID используйте networkID. В данные параметры вы можете взять в настройках бизнеса в Бэкофис (параметр networkID одинаков для любого бизнеса сети).

Пример ответа:

{
  "token": "eac0f081-f3e7-44a2-830a-4e86106a8a29"
}

2. Подтверждение OTP

В случае первичной авторизации вы вызываете запрос без каких-либо дополнительных параметров — никакого взаимодействия с EHR сервером на этом этапе нет.

В запросе передается кука, полученная из предыдущего запроса и код в GET параметре, полученный в смс на указанный выше номер телефона.

curl -v -H 'Origin:http://mydomain.com' --cookie 'sms=s%3Aj%3A%7B%22business%22%3A%224000000006762%22%2C%22phone_country%22%3A%227%22%2C%22phone_area%22%3A%22985%22%2C%22phone_number%22%3A%223596605%22%2C%22code%22%3A%22a23cc3ea-6be0-4fe8-877e-245927a9a08f%22%7D.7qJaRYY4516GP2CkbNilc9B4FvU8R1LpxxsdxEF4cDw' -XGET 'http://apiv2.gbooking.ru/confirm_sms?code=40987'

В случае успешной авторизации вы получите user, token. В данном случае user приходит в поле profileId):

{
  "clientId": "5d5eb047356cbb7be678db20",
  "profileId": "55d98d643ef4d79e909cdbfc",
  "token": "4e17c0ad9cc722877f5a323547a6b0bc71a8fcca"
}

Пока никаких запросов на сторону EHR не было - это стандартная авторизация в системе MedMe через OTP.

В случае повторной авторизации вам нужно помимо стандартных параметров этого запроса отправить так же параметр ehr_user_sign. В этом случае креденшиалы будут отправлены на EHR сервер и вы сразу будете авторизованы и на сервере мед данных.

Для проверки авторизации удобно использовать запрос на получение данных пациента patient.get_patient, поскольку он не содержит параметров и возвращает данные о пациенте, которые пригодятся в дальнейшем, и user_sign.

curl http://ehr-demo-api.dev.gbooking.ru -X POST -d '{"jsonrpc":"2.0","id":1,"method":"patient.get_patient","params":{},"cred":{"user":"55d98d643ef4d79e909cdbfc","token":"4e17c0ad9cc722877f5a323547a6b0bc71a8fcca"}}'

При использовании OAuth2 сервера запрос на подтверждение OTP выглядит так:

curl 'http://oauthv2.gbooking.ru/sms/verify' -v -H 'Origin:http://mydomain.com' -H 'Content-Type:application/json' -XPOST -d '{"token":"c18edfed-7a10-4205-887e-a87cbbc78e9a","code":"22834","client":"54ae263ec469881d068b4567","ehr_user_sign":"user_sign_333"}'

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

  • token — параметр, полученный из предыдущего запроса
  • code — код, полученный в смс на предыдущем шаге
  • client — идентификатор приложения в OAuth

Пример ответа:

{
  "auth_user": "5d5eb047356cbb7be678db23",
  "user": "55d98d643ef4d79e909cdbfc",
  "token": "b2bfa760023d2e7e4ec210925e5624097b68e8c9"
}

Шаг 2. Запрос client.get_exchange_token

Данный запрос генерирует токен обмена и отправляет его на сторону EHR сервера, на обработчик embedded_storage.save_exchange_token, а также текущие креденшиалы пользователя. Данный запрос берет данные о EHR сервере из настроек бизнеса или нетворка (см. Настройка межсерверного взаимодействия).

curl -XPOST http://apiv2.gbooking.ru/rpc -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"client.get_exchange_token","params":{"business":{"id":"4000000006762"},"client":{"id":"5d5eb047356cbb7be678db20"}},"cred":{"user":"55d98d643ef4d79e909cdbfc","token":"4e17c0ad9cc722877f5a323547a6b0bc71a8fcca"}}'

В ответ должен прийти exchange_token.

{"jsonrpc":"2.0","id":1,"result":{"exchangeToken":"DdTc5BUPo3wg9nTvC7iSiGUL2CofFNEcO3wbMeXdsduMNFIVjNfBiS9boaPipkSI"}}

С этим токеном можно отправить данные в запрос на аутентификацию на EHR сервер.

Шаг 3. Аутентификация на EHR сервере

Если вам придет успешный статус вы можете отправлять свои запросы с текущими креденшиалами на EHR сервер. Так же в случае успешной аутентификации вы получите в ответе user_sign - уникальную последовательность символов, которую необходимо сохранить на стороне клиента. user_sign в последующем необходимо передавать в запрос на подтверждение OTP. В этом случае сервер авторизации должен отправить запрос на сохранение ваших креденшиалов.

curl http://ehr-demo-api.dev.gbooking.ru -X POST -d '{"jsonrpc":"2.0","id":1,"method":"embedded_storage.authenticate","params":{"exchangeToken":"DdTc5BUPo3wg9nTvC7iSiGUL2CofFNEcO3wbMeXdsduMNFIVjNfBiS9boaPipkSI","patientProperties":{"name":"Alisa","surname":"Johnson","date":"2010-01-01 00:00:00.000","gender":2,"phone":"2222222222"}}}'

В случае, если пользователь уже привязан к пациенту, вернется успешный ответ с данными пациента