Должна ли служба API отправлять электронное письмо активации пользователя или клиентское приложение?

Я пытаюсь разработать веб-сервис REST API. У меня есть вопрос о том, как обрабатывать электронную почту активации пользователя. В настоящее время служба API обрабатывает отправку электронной почты.

Вот поток у меня на данный момент:

  1. Пользователь регистрируется через клиентское приложение
  2. Клиентское приложение POST для службы API
  3. Сервис API проверяет и добавляет пользователя в базу данных
  4. Сервис API отправляет Пользователю ссылку для активации
  5. Пользователь нажимает на ссылку активации, которая приведет его к странице активации клиентского приложения.
  6. Страница активации клиентского приложения POST к службе API
  7. Готово

Вот где я сейчас вижу проблему:

Поскольку служба API в настоящее время отправляет электронную почту, клиентское приложение не контролирует внешний вид электронной почты. И в письме могут быть URL-адреса, которые должны указывать на клиентское приложение.


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

Две проблемы, которые я вижу с этой стратегией:

  • Безопасность, поскольку ключ активации теперь доступен клиентскому приложению.
  • Не СУХОЙ, так как каждый клиент может нести ответственность за отправку электронной почты.

Как вы думаете, лучший способ справиться с этим?

Я хотел бы разрешить клиентскому приложению настраивать свою электронную почту, а также включать клиентские URL-адреса (страница активации).

8 ответов

Решение

TL;DR

Создайте небольшой сервис для разработчиков по созданию шаблонов, дайте им возможность объявить, какой шаблон они хотят использовать при размещении в API активации


Краткое изложение проблемы:

  • электронная почта должна выглядеть по-разному для каждого клиентского приложения
  • отправка почты должна быть осуществлена ​​один раз
  • решение должно быть безопасным

Нет необходимости, чтобы электронная почта каждый раз выглядела по-другому. Поэтому нет необходимости отправлять формат электронной почты с запросом POST.

Вместо этого может быть выполнено одно из следующих действий:

1 Создайте отдельную конечную точку API для определения шаблонов и позвольте клиентскому приложению выбрать один из них при отправке запроса на активацию.

Это не совсем безопасно, по крайней мере, создает проблему, чтобы сделать его безопасным, если вы хотите принимать HTML из клиентских приложений.

Рекомендуемое решение:

2 Создайте инструмент для разработчиков (на том же веб-сайте, где они получают ключ API), который принимает шаблоны и помогает создавать их. Клиентское приложение может выбрать один из них при размещении запроса на активацию. Фрагмент тела запроса выглядит примерно так:

...
"template": "foobar-app",
"fields": {
    "title": "Welcome to foobar app",
    "username": "jim78"
}
...

HTML в полях не допускается.

Это позволяет вам иметь предварительно определенные шаблоны, подготовленные разработчиком, которые могут использоваться вашей службой отправки электронной почты, и никакая ошибка в клиентском приложении не может привести к тому, что электронная почта станет небезопасной. Кроме того, вы получаете место, где шаблоны могут работать и тестироваться. (разработчик может отправить их самому себе для отладки - создание шаблонов электронной почты ужасно, поверьте мне)

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

Пункт о безопасности и доверии. Обычно вы отправляете электронное письмо с кодом активации, содержащее код активации. Цель электронного письма - подтвердить, что электронное письмо действительно и что у пользователя есть доступ к этому электронному письму. Пользователь мог получить ссылку для подтверждения только по электронной почте.

Если вы передадите ссылку активации клиенту, то любой, кто имеет доступ к вашему API, получит доступ к коду активации. Если у них есть доступ к ссылке, они могут обойти процесс проверки. Это действительно легко, если у вас есть веб-приложение, так как им просто нужно зайти в режим разработчика браузера, чтобы увидеть ссылку. Если у вас толстый клиент, он может отследить сеть, если вы не используете шифрование, такое как https. Они также могли бы, если бы они были выделены, декомпилировать ваш двоичный файл (вот почему вы не хранили ключи в своих двоичных файлах).

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

Что касается шаблонов, есть много хороших ответов выше. Я бы предложил иметь каталог шаблонов и список аргументов, которые можно заменить.

Таким образом, способ, которым я достиг этого, на мой взгляд, довольно хороший способ. Поэтому я взял методологию работы веб-токенов JSON и применил ее к своим ссылкам активации. Я объясню, как это работает:

У меня есть 2 веб-сервера, один из которых обрабатывает API REST, а другой - спа.

Таким образом, пользователь регистрируется, и запрос отправляется в API. Затем ответ возвращается в SPA, после чего в случае успеха отправляет запрос в бэкэнд SPA, который подписывает токен с учетными данными пользователя, назначение токена (в данном случае это проверка адреса электронной почты) и дату его истечения.,

Этот токен отправляется на адрес электронной почты пользователя, однако на сервере REST существует маршрут получения, который декодирует токен и, если он действителен, проверяет адрес электронной почты.

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

Надеюсь, это поможет!

РЕДАКТИРОВАТЬ: другой способ будет передать шаблон, встроенный в руль или что-то, что заменяет переменные на фактические значения. Затем сделайте, чтобы REST API сделал его, и пошлите по электронной почте. (Это, наверное, лучший способ, имхо, ха-ха)

Ваш API может иметь объект IEmailBodyFormatter, который передается в качестве параметра вашему вызову API....

Я бы расширил шаг 2 дополнительными пост-данными, отправленными на сервер:

"mail":{
  "placeholder":"someStringChoosenByClientWhichWillBeReplaceByActivationCode",
  "subject":"Hey there, please activate",
  "ishtml":false,
  "body":"SSdtIHRyeWluZyB0byBkZXZlbG9wIGEgUkVTVCBBUEkgd2ViIHNlcnZpY2UuIEkgaGF2ZSBhIHF1ZXN0aW9uIGFib3V0IGhvdyB0byBoYW5kbGUgdXNlciBhY3RpdmF0aW9uIGVtYWlsLiBDdXJyZW50bHksIHRoZSBBUEkgc2VydmljZSBoYW5kbGVzIGVtYWlsIHNlbmRpbmcu"
  "attachments":[
                  {
                     "content-type":"image/png",
                     "filename":"inline_logo.png",
                     "content":"base64_data_of_image"
                  }
                ]
}

Это позволило бы клиенту полностью контролировать отправленное сообщение, но процедура активации (генерация и доставка почты) все еще обрабатывается службой.

Все, кроме ключа активации, может быть сгенерировано для каждого пользователя клиентом (например, используя "Hello XYZ" в качестве субъекта).

Я не уверен, стоит ли разрешать html-письма ("ishtml":false,), это зависит от вашего приложения и количества времени, которое вы хотите потратить на его реализацию.

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

POST /email-templates
{
    "subject": "Complete Your Registration",
    "body": "<html>Follow this link to complete your registration: {activationLink}. It is valid for 45 minutes.</html>"
}

POST /registration-requests
{
    "name": "John Q. Public",
    "emailTemplate": "/email-templates/45"
}

Я присоединяюсь к naugtur с идеей позволить клиенту отправить вам шаблон своей электронной почты. (И +1 за разговор о способе тестирования, потому что я согласен с ужасной "разработкой" почты).

Но почему так сложно? Клиентские приложения означают разработчиков, так почему бы не позволить им дать им шаблон по умолчанию (с HTML), позволить им поиграть, если они захотят, и отправить вам обратно версию, которую они предпочитают?
Это не много работы для вас (просто новое поле в таблице клиента и новый маршрут), и это дает им много возможностей.

Вот базовый пример, где мы представим некоторые параметры, чтобы они могли поиграться с HTML, даже не зная их:

  • app.name
  • app.description
  • activation_code
  • user.* регистрация информации

Базовый шаблон

{
  title: "Your activation code for %{app.name}",
  body: "<p>Hi, you've been registered on %{app.name}.
    <p>%{app.description}</p>
    <p>Follow <a href="%{activation_code}">this link to confirm your inscription</a>."
}

Зарегистрировать новый шаблон

Тогда клиент говорит: "Я предпочитаю иметь более простую почту, но я хочу, чтобы его имя было в ней!".
[PUT] /api/email/templates/client_id

{
  title: "Your activation code",
  body: "<p>Hi %{user.fullname}, Follow <a href="%{activation_code}">this link to confirm your inscription</a>."
}

И вот, пожалуйста. Пусть они играют с HTML, это позволяет гораздо больше персонализации.
В этом нет никакого вреда, кроме их имиджа на их клиентах, если они все испортят, но они их клиенты.

Проблемы с безопасностью

Было отмечено, что злоумышленники могут получить доступ к токену клиентского приложения и могут внедрить вредоносный контент в шаблон. Во-первых, риск утечки токена уже настолько высок, что это последнее из ваших опасений. Тем не менее, если вы боитесь этого, запретив img теги и сделать содержание a теги соответствуют href Атрибут должен решить вашу проблему.

Я думаю, что правильный способ - предоставить клиенту ключ активации, чтобы он делал с ним все, что хочет.

Вы также можете добавить другую конечную точку для отправки ключа активации для пользователя.

Возвращает пользователя. (с URL, как User/{userid} и другие ресурсы, как URL User/{userid}/ActivationKey)

User (POST) 

Это может вернуть текущего пользователя и другие ресурсы, такие как электронная почта, активировать и т. Д. Для получения информации о ключе (например, даты, срок действия и т. Д.)

User/{userid}/ActivationKey

оттуда вы можете продлить его так долго, как хотите:

Предварительный электронный адрес для активации:

User/{userid}/ActivationKey/Email (GET) 

Обновите электронное письмо активации с шаблоном, сервером smtp и т. Д.:

User/{userid}/ActivationKey/Email (PUT)

Создайте (и отправьте) электронное письмо активации, возможно с датой отправки или другими вариантами отправки (версии text-html и т. Д.):

User/{userid}/ActivationKey/Email (POST)

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

User/{userid}/Emails (GET)
User/{userid}/Emails/{emailid} (GET)
Другие вопросы по тегам