Я работаю над API для службы REST, которую собираюсь и производить, и потреблять. Я провел последние несколько дней, пытаясь понять, как правильно обращаться с аутентификацией, и думаю, что наконец-то что-то придумал.
Я придумаю это на основе следующих фактов о стеке приложений:
- Клиент и сервер находятся в .NET4 (часть клиента в профиле клиента)
- Сервер выставляется с использованием WCF REST
- Я действительно не хочу хранить имя пользователя и пароль в памяти приложения
С 3 я хотел использовать форму аутентификации токена, чтобы после проверки учетных данных сервером клиент получал токен для использования в остальной части приложения (это позволит мне делать другие вещи, такие как время ожидания пользователей, возможность плавного перемещения пользователей между веб-версиями и версиями для настольных компьютеров и т. д.). После того, как я выяснил, как сделать вызовы воспроизводимыми и защищенными от несанкционированного доступа, я придумал следующее:
- Прежде чем клиент попытается аутентифицироваться, он генерирует пару ключей Диффи-Хеллмана, используя
ECDiffieHellmanCng
класс. - Он передает открытую часть пары ключей по проводам вместе с именем пользователя и паролем (конечно, через HTTPS).
- Сервер аутентифицирует комбинацию имени пользователя и пароля, в случае успеха он затем делает следующее:
- Создает уникальный токен сеанса
- Генерирует свою собственную пару ключей DH и вычисляет общий секрет из открытого ключа, предоставленного клиентом
- Запоминает токен сеанса, общий секрет, пользователя и время «последнего действия» (используется для скользящего окна истечения) в своей базе данных
- Возвращает маркер сеанса, его открытый ключ DH и сообщение об успешной аутентификации
- Клиент берет ключ DH из ответа, вычисляет общий секрет и сохраняет токен и секрет в памяти.
С этого момента комбинация токен / секрет сеанса работает, как и большинство других API REST, с запросом, который снимают и ставят метки времени, а затем генерируют HMAC. Всякий раз, когда клиент выполняет действие против сервера, он проверяет пару токен / секрет и разрешает действие, если оно допустимо и не истекло, и обновляет последнюю запись действия в сеансе.
Я не вижу никаких явных недостатков, и, вероятно, слишком перегружен для этого, но мне нужно научиться делать это в какой-то момент. HMAC предотвращает повторные атаки, согласование DH помогает предотвратить MITM-атаки (я не могу представить себе работоспособную атаку на макушку между HMAC / DH).
Любые дыры, которые кто-нибудь может проткнуть в этом?