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

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

Вот поток, который у меня есть на данный момент:

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

Здесь я вижу проблему:

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


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

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

  • Безопасность, поскольку ключ активации теперь открыт для клиентского приложения.
  • Не DRY, поскольку каждый клиент может нести ответственность за отправку электронной почты.

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

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

Ответ 1

TL; DR

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


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

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

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

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

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

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

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

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

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

В разрешенных полях HTML не поддерживается.

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

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

Ответ 2

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

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

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

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

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

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

EDIT: другой способ - передать шаблон, построенный в дескрипторах, или что-то, что свопит переменные для фактических значений. Затем попробуйте REST api и отправьте его по электронной почте. (Это, вероятно, лучший способ imo haha)

Ответ 3

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

Ответ 4

Я бы добавил шаг 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-Mails ("ishtml":false,), это зависит от вашего приложения и количества времени, которое вы хотите потратить на его реализацию.

Ответ 5

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

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

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

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

Ответ 6

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

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"
}

Ответ 7

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

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

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

User (POST) 

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

User/{userid}/ActivationKey

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

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

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

Обновите электронную почту активации с помощью шаблона, smtp-сервера и т.д. электронной почты.

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

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

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

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

User/{userid}/Emails (GET)
User/{userid}/Emails/{emailid} (GET)

Ответ 8

Я присоединяюсь к nauktur о том, чтобы позволить клиенту отправить вам шаблон своей электронной почты. (И +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, вы должны решить свою проблему.