Я работаю над API, предоставляемым через HTTP, который будет использоваться компаниями-партнерами и развертываться на их многочисленных клиентах.
В некоторых случаях клиент будет работать в браузере. Это мой основной фокус, но я мог бы потенциально применить тот же шаблон, где клиент является приложением Windows. Я чувствую, что есть более широкие возможности для защиты личного ключа на клиенте, когда это приложение для Windows, а не приложение на основе браузера. Таким образом, общение происходит со страницы браузера, отображаемой приложением-партнером, на наш сервер, где мы размещаем наш API.
Суть в том, что мы не можем запрашивать у конечного пользователя учетные данные и должны полагаться на сохраненный пароль / ключ / токен, который будет передаваться при каждом запросе. Меня беспокоит то, что я хочу отговорить партнерскую компанию от внедрения этого токена в код на стороне клиента. Ниже приведено высокоуровневое описание сценария.
- Партнер создает у нас учетную запись (ручной процесс), выполняет необходимую работу по разработке, чтобы использовать API в своем продукте, а затем развертывает его своим клиентам.
- Затем клиент запускает продукт и работает через мастера, создавая свою учетную запись у нас. На этом этапе мы можем запросить у них имя пользователя и пароль, но тогда все будущие запросы к API никогда не должны запрашивать у конечного пользователя учетные данные.
- Затем они выполняют множество бизнес-процессов, которые вызывают наш API на многих рабочих станциях в разных пользовательских контекстах. Нас не интересует информация об отдельных пользователях.
Для целей этого вопроса я собираюсь пропустить шаг 1 и сосредоточиться на шагах 2 и 3.
В настоящее время я работаю над защитой этого API и разработал следующий дизайн:
- HTTPS везде (все запросы используют SSL / TLS)
- Все запросы POST используют токены CSRF
- На шаге 2, когда клиент создает учетную запись, мы предоставляем ему код авторизации клиента. Партнер должен написать свое приложение для хранения этого кода авторизации на сервере.
- Перед будущими вызовами нашего API они вызывают функцию Init в нашей библиотеке javascript и предоставляют обратный вызов, что-то вроде «GetAuthToken».
- При каждом обращении к нашему API мы проверяем, есть ли у нас Auth Token (на сервере), если нет, мы возвращаем ошибку и вызываем обратный вызов.
- Партнер при реализации обратного вызова должен позвонить на свой сервер, используя HTTPS для получения токена. Этот запрос будет подлежать обычной аутентификации, поэтому предполагается, что если пользователь прошел аутентификацию в своей системе, он может получить токен аутентификации.
- Мы получаем токен авторизации, звоним на наш сервер, чтобы проверить его, а затем устанавливаем файл cookie HTTPOnly, содержащий токен.
- Когда срок действия файла cookie истекает, мы снова вызываем обратный вызов GetAuthToken.
- Междоменные проблемы решаются с помощью postMessage
- Мы можем сделать токен авторизации отзывным
У нас есть форма федеративной безопасности: если пользователь проходит проверку подлинности с партнером, мы предполагаем, что у него есть доступ к нашему API. Единственный способ избежать использования секретного ключа / токена авторизации в коде на стороне клиента - это механизм обратного вызова.
Я слишком усложняю это? Есть ли другие более простые подходы? Я понимаю, что если какой-либо сайт открыт для XSS или скомпрометирован вредоносными программами, все ставки отключены, но, по крайней мере, не превращая закрытый ключ в javascript или разметку, пользователь не может щелкнуть правой кнопкой мыши просмотр исходного кода и сообщить всем закрытый ключ.
Редактировать: Нашел этот вопрос. Верхний ответ описывает нечто похожее на то, что я описал, хотя упоминает WIF, который я не хочу заставлять Партнера внедрять (возможно, он даже не работает под Windows). Хотелось бы еще оставить отзыв о моем подходе ...
Веб-приложение - аутентификация пользователя на разных доменах