Перейти к основному содержимому

Интеграция для ASP.NET приложений

В статье рассматривается пример подключения двухфакторной аутентификации для сайтов, построенных на платформе ASP.NET MVC. За основу взят шаблонный проект веб-приложения ASP.NET (.NET Framework).

Принцип работы

  1. Сайт проверяет логин и пароль пользователя
  2. Если данные указаны корректно, запрашивает API мультифактора для получения адреса страницы доступа и отправляет на нее пользователя
  3. Получает от Мультифактора токен доступа, проверяет подпись, время выдачи и срок действия
  4. Если токен валидный, авторизует пользователя

Дополнительные библиотеки

Установите из NUGET пакет JWT для валидации токена доступа https://www.nuget.org/packages/JWT

Конфигурационный файл

Добавьте в файл web.config в раздел appSettings параметры для подключения к API Мультифактора

<!-- mfa settings-->
<add key="mfa-api-url" value="https://api.multifactor.ru" />
<add key="mfa-api-key" value="" />
<add key="mfa-api-secret" value="" />

Далее создайте класс, который будет читать настройки конфигурации

public class MultiFactorSettings
{
public string ApiUrl { get; set; }
public string ApiKey { get; }
public string ApiSecret { get; }

public MultiFactorSettings()
{
ApiUrl = ConfigurationManager.AppSettings["mfa-api-url"];
ApiKey = ConfigurationManager.AppSettings["mfa-api-key"];
ApiSecret = ConfigurationManager.AppSettings["mfa-api-secret"];
}
}

Клиент для API

Добавьте в проект службу для взаимодействия с API Мультифактора

/// <summary>
/// Multifactor Web Client
/// </summary>
public class MultiFactorWebClient
{
private MultiFactorSettings _settings;

public MultiFactorWebClient(MultiFactorSettings settings)
{
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
}

public string CreateRequest(string login, string postbackUrl)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

//payload
var json = JsonConvert.SerializeObject(new
{
Identity = login,
Callback = new
{
Action = postbackUrl,
Target = "_self"
}
});

var requestData = Encoding.UTF8.GetBytes(json);
byte[] responseData = null;

//basic authorization
var auth = Convert.ToBase64String(Encoding.ASCII.GetBytes(_settings.ApiKey + ":" + _settings.ApiSecret));

using (var web = new WebClient())
{
web.Headers.Add("Content-Type", "application/json");
web.Headers.Add("Authorization", "Basic " + auth);
responseData = web.UploadData(_settings.ApiUrl + "/access/requests", "POST", requestData);
}

json = Encoding.UTF8.GetString(responseData);
var response = JsonConvert.DeserializeObject<MultiFactorWebResponse<MultiFactorAccessPage>>(json);

return response.Model.Url;
}
}

public class MultiFactorWebResponse<TModel>
{
public bool Success { get; set; }
public TModel Model { get; set; }
}

public class MultiFactorAccessPage
{
public string Url { get; set; }
}

Сервис — клиент для API Мультифактора. В конструктор класса передаются параметры для подключения, которые берутся из конфигурационного файла web.config. В методе CreateRequest формируется запрос для получения адреса страницы проверки доступа, далее запрашивается API и возвращается результат.

AccountController

Вся подготовительная работа завершена, осталось доделать сценарий формы входа и получения токена доступа. Будем считать, что в вашем проекте есть класс AccountController, который запрашивает логин и пароль пользователя.

Добавьте в него настройки для работы с API Мультифактора

private MultiFactorSettings _settings = new MultiFactorSettings();

И сделайте запрос на мультифакторную аутентификацию после проверки логина и пароля

[HttpPost]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
//check here login and password
if (model.Email == "user@example.com" && model.Password == "123")
{
return RedirectToMfa(model.Email);
}

ModelState.AddModelError(string.Empty, "Invalid credentials");
}

return View(model);
}

Добавьте метод для получения страницы мультифакторной аутентификации

private ActionResult RedirectToMfa(string login)
{
var postbackUrl = Url.Action("PostbackFromMfa", "Account", null, Request.Url.Scheme);

var client = new MultiFactorWebClient(_settings);
var url = client.CreateRequest(login, postbackUrl);

return RedirectPermanent(url);
}

И метод для возврата пользователя с токеном доступа

[HttpPost]
public ActionResult PostbackFromMfa(string accessToken)
{
//Postback from Multifactor

try
{
var userParams = new JwtBuilder()
.WithSecret(_settings.ApiSecret)
.WithAlgorithm(new HMACSHA256Algorithm())
.MustVerifySignature()
.Decode<IDictionary<string, object>>(accessToken);

var login = userParams["sub"] as string;

FormsAuthentication.SetAuthCookie(login, false);
return RedirectToAction("Index", "Home");
}
catch (TokenExpiredException)
{
//log: Token has expired
return RedirectToAction("Login");
}
catch (SignatureVerificationException)
{
//log: Token has invalid signature
return RedirectToAction("Login");
}
}

В этом метод происходит валидация токена доступа и, если он валиден, авторизация пользователя.

Смотрите также: