Для всего, что связано с аутентификацией, я использую встроенную аутентификацию сеанса Django, поскольку и интерфейс, и серверная часть развертываются в одном и том же месте. сервер.
Мой вопрос: как я могу добавить двухфакторную аутентификацию (с использованием Google Authenticator или yubikey) в проект, где django используется в качестве API?< /p>
Вот в чем проблема: самый простой способ сделать это — разрешить пользователю войти в систему из внешнего интерфейса, и как только пользователь войдет в систему из /accounts/ войти (встроенное представление аутентификации Django), отправить форма, в которой пользователь должен ввести свой код. Проблема с этим подходом заключается в том, что как только пользователь войдет в систему, Django создаст сеанс, поэтому request.user.is_authenticated вернет True, даже если пользователь еще не отправил двухфакторный код, так что все будет зависеть от интерфейса. Мне не нравится этот подход, потому что я боюсь, что кто-то может найти способ избежать отправки двухфакторной формы и перемещаться по остальной части сайта (поскольку, согласно Django, этот сеанс будет аутентифицирован) без двухфакторной аутентификации< /p>
Что я пробовал: Мне все еще придется написать большую часть кода для этого, потому что я хочу сначала понять, насколько это безопасно. Но вот мой подход:
Первый подход
- Пользователь отправляет форму входа< /li>
После отправки формы входа запрос POST с учетными данными отправляется на конечную точку с именем /authenticate в моем приложении Django. Эта конечная точка будет использовать встроенный метод аутентификации() Django, который проверит, принадлежат ли эти учетные данные пользователю, без создания сеанса. - Если учетные данные принадлежат пользователю , он вернет пользователю True. На этом этапе пользователь отправит форму с кодом 2FA, и если код правильный, запрос будет отправлен в /accounts/login, который снова проверит пароль и адрес электронной почты, фактически войдет в систему и создаст сеанс. , на этот раз.
Другой подход, который был бы еще лучше, заключался бы в переопределении Представление входа в Django-Allauth, чтобы я мог добавить проверку токен, что-то вроде (ВНИМАНИЕ: псевдокод):
if provided_code == user_code:
login()
return HttpResponse({'Result': 'Logged in!'})
else:
return HttpResponse({'Result': 'incorrect code'})
Где предоставленный_код — это код 2FA, предоставленный пользователем, а user_code — правильный код, который я получу из другой функции, например get_user_2fa_code(user).
Я не эксперт по безопасности, но лучшего подхода я не придумал. Насколько это было бы безопасно? Есть ли лучший способ добавить аутентификацию 2FA в проект Django, где django работает как серверный API?
Вот вид входа в систему:
class LoginView(
RedirectAuthenticatedUserMixin, AjaxCapableProcessFormViewMixin, FormView
):
form_class = LoginForm
template_name = "account/login." + app_settings.TEMPLATE_EXTENSION
success_url = None
redirect_field_name = "next"
@sensitive_post_parameters_m
def dispatch(self, request, *args, **kwargs):
return super(LoginView, self).dispatch(request, *args, **kwargs)
def get_form_kwargs(self):
kwargs = super(LoginView, self).get_form_kwargs()
kwargs["request"] = self.request
return kwargs
def get_form_class(self):
return get_form_class(app_settings.FORMS, "login", self.form_class)
def form_valid(self, form):
success_url = self.get_success_url()
try:
return form.login(self.request, redirect_url=success_url)
except ImmediateHttpResponse as e:
return e.response
def get_success_url(self):
# Explicitly passed ?next= URL takes precedence
ret = (
get_next_redirect_url(self.request, self.redirect_field_name)
or self.success_url
)
return ret
def get_context_data(self, **kwargs):
ret = super(LoginView, self).get_context_data(**kwargs)
signup_url = passthrough_next_redirect_url(
self.request, reverse("account_signup"), self.redirect_field_name
)
redirect_field_value = get_request_param(self.request, self.redirect_field_name)
site = get_current_site(self.request)
ret.update(
{
"signup_url": signup_url,
"site": site,
"redirect_field_name": self.redirect_field_name,
"redirect_field_value": redirect_field_value,
}
)
return ret
Подробнее здесь: https://stackoverflow.com/questions/668 ... jango-rest