Использование MSAL.NET для входа пользователей с помощью социальных учетных записей

Important

Начиная с 1 мая 2025 г. Azure AD B2C больше не будет доступен для приобретения для новых клиентов. Дополнительные сведения см. в разделе "Вопросы и ответы".

Вы можете использовать MSAL.NET для входа пользователей в систему с помощью социальных учетных записей, используя Azure AD B2C. Azure AD B2C строится вокруг понятия политик. В MSAL.NET указание политики означает указание authority.

  • При создании экземпляра общедоступного клиентского приложения необходимо указать политику в параметре authority.
  • Если вы хотите применить политику, необходимо вызвать переопределение AcquireTokenInteractive, содержащее параметр authority.

Полномочный URL-адрес для клиента и политики Azure AD B2C

Полномочия для использования: https://login.microsoftonline.com/tfp/{tenant}/{policyName}, где:

  • tenant— имя клиента AZURE AD B2C,
  • policyName Имя политики, применяемой (например, "b2c_1_susi" для входа или регистрации).

Текущая рекомендация со стороны B2C — использовать b2clogin.com в качестве центра сертификации. Например: $"https://{your-tenant-name}.b2clogin.com/tfp/{your-tenant-ID}/{policyname}". Дополнительные сведения см. в разделе "Настройка URL-адресов перенаправления для b2clogin.com.".

// Azure AD B2C Coordinates
public static string Tenant = "fabrikamb2c.onmicrosoft.com";
public static string ClientID = "00001111-aaaa-2222-bbbb-3333cccc4444";
public static string PolicySignUpSignIn = "b2c_1_susi";
public static string PolicyEditProfile = "b2c_1_edit_profile";
public static string PolicyResetPassword = "b2c_1_reset";

public static string AuthorityBase = $"https://fabrikamb2c.b2clogin.com/tfp/{Tenant}/";
public static string Authority = $"{AuthorityBase}{PolicySignUpSignIn}";
public static string AuthorityEditProfile = $"{AuthorityBase}{PolicyEditProfile}";
public static string AuthorityPasswordReset = $"{AuthorityBase}{PolicyResetPassword}";

Создание экземпляра приложения

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

application = PublicClientApplicationBuilder.Create(ClientID)
               .WithB2CAuthority(Authority)
               .Build();

Получение токена для применения политики

Note

Начиная с MSAL .NET 4.15.0 разработчики больше не должны писать собственную логику фильтрации кэша.

В Azure AD B2C каждая политика или поток пользователя является отдельным сервером авторизации. Они выдают свои собственные токены. Поэтому токен, полученный с помощью пользовательского потока b2c_1_editprofile, не будет работать с ресурсом, защищённым пользовательским потоком b2c_1_susi. Поэтому при вызове защищенного API разработчики приложений должны указать MSAL, какой токен следует использовать из кэша, в зависимости от целевого потока пользователя.

Для получения токена для API, защищенного Azure AD B2C, в общедоступном клиентском приложении необходимо использовать:

  • Переопределение метода GetAccountsAsync() для потока пользователя перед вызовом AcquireTokenSilent,
  • Переопределяет AcquireTokenInteractive с помощью центра B2C:
IEnumerable<IAccount> accounts = await application.GetAccountsAsync(B2CConstants.PolicySignUpSignIn);
AuthenticationResult ar = await application.AcquireTokenInteractive(B2CConstants.Scopes)
                                           .WithAccount(accounts.FirstOrDefault())
                                           .ExecuteAsync();

В версиях > 4.15.0 разработчикам пришлось писать собственную логику фильтрации кэша. Начиная с версии >= 4.15.0 это больше не так, поскольку разработчикам достаточно указать только политику или поток пользователя, а MSAL вернёт соответствующую учётную запись для этого конкретного потока пользователя.

В MSAL.NET вам нужно лишь написать:В MSAL < 4.15.0 необходимо было написать:
var accounts = await app.GetAccountsAsync(App.PolicySignUpSignIn);
private IAccount GetAccountByPolicy(IEnumerable<IAccount> accounts, string policy)
{
 foreach (var account in accounts)
 {
  string userIdentifier = account.HomeAccountId.ObjectId.Split('.')[0];
  if (userIdentifier.EndsWith(policy.ToLower()))
   return account;
 }
 return null;
}

Применение политики (например, предоставление пользователю правки профиля или сброса пароля) в настоящее время выполняется путем вызова AcquireTokenInteractive.

Обратите внимание, что в случае этих двух политик вы не используете возвращаемый маркер или результат проверки подлинности.

Особый случай политик EditProfile и ResetPassword

Если вы хотите реализовать сценарий, в котором конечные пользователи входят в систему с помощью учетной записи социальной сети, а затем редактируют свой профиль, следует применить политику B2C EditProfile. Чтобы сделать это, вызовите AcquireTokenInteractive с указанием конкретного центра авторизации для этой политики и параметром Prompt, заданным значением Prompt.NoPrompt, чтобы предотвратить отображение диалогового окна выбора учетной записи (так как пользователь уже вошел в систему).

private async void EditProfileButton_Click(object sender, RoutedEventArgs e)
{
 IEnumerable<IAccount> accounts = await app.GetAccountsAsync();
 try
 {
  var authResult = await app.AcquireToken(scopes:App.ApiScopes)
                               .WithAccount(GetUserByPolicy(accounts, App.PolicyEditProfile)),
                               .WithPrompt(Prompt.NoPrompt),
                               .WithB2CAuthority(App.AuthorityEditProfile)
                               .ExecuteAsync();
  DisplayBasicTokenInfo(authResult);
 }
 catch
 {
  . . .
}

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

 if (ex.Message.Contains("AADB2C90118"))
{
       authResult = await app.AcquireTokenInteractive(App.ApiScopes)
              .WithParentActivityOrWindow(new WindowInteropHelper(this).Handle)
              .WithPrompt(Prompt.SelectAccount)
              .WithB2CAuthority(App.AuthorityResetPassword)
              .ExecuteAsync();
}

Или какая-то специальная логика, которую вы использовали для обработки ошибки AADB2C90118.

Учетные данные пароля владельца ресурса (ROPC) для B2C

Дополнительные сведения о потоке ROPC см. в документации по потоку имени пользователя и пароля.

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

Используя имя пользователя и пароль, вы отказываееся от ряда вещей:

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

Настройка потока ROPC в Azure AD B2C

В клиенте AD B2C Azure создайте новый поток пользователя и выберите вход с помощью ROPC. Это позволит включить политику ROPC для вашего клиента. Дополнительные сведения см. в разделе "Настройка потока учетных данных владельца ресурса ".

IPublicClientApplication содержит метод с именем AcquireTokenByUsernamePassword:

AcquireTokenByUsernamePassword(
            IEnumerable<string> scopes,
            string username,
            SecureString password)

Этот метод принимает три параметра:

  • scopes для запроса маркера доступа для
  • Имя пользователя
  • Пароль SecureString для пользователя

Не забудьте использовать центр, содержащий политику ROPC.

Ограничения потока ROPC

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

Google Auth и Embedded Webview

Если вы являетесь разработчиком B2C, использующим Google в качестве поставщика удостоверений, мы рекомендуем использовать системный браузер, так как Google не разрешает проверку подлинности из внедренных веб-представлений. В настоящее время login.microsoftonline.com является доверенным источником для Google. Использование этой авторизации будет работать со встроенным WebView. Однако использование b2clogin.com не является доверенным центром в Google, поэтому пользователи не смогут пройти проверку подлинности.

Кэширование с использованием B2C в MSAL.NET

Известная проблема с Azure AD B2C

MSAL.Net поддерживает кэш маркеров. Ключ кэширования токенов основан на утверждениях, возвращаемых поставщиком удостоверений. В настоящее время для создания ключа кэша токенов MSAL.Net требуются два утверждения:

  1. tidкоторый является идентификатором арендатора Microsoft Entra
  2. preferred_username

Оба этих утверждения отсутствуют во многих сценариях Azure AD B2C.

Проблема для клиента заключается в следующем: при попытке отобразить поле имени пользователя отображается значение «Отсутствует в ответе токена»? Если это так, то это связано с тем, что B2C не возвращает значение preferred_username в токене IdToken из-за ограничений, связанных с учетными записями социальных сетей и внешними поставщиками удостоверений (IdP). Microsoft Entra ID возвращает значение для preferred_username, так как он знает, кто пользователь, но для B2C, так как пользователь может войти с помощью локальной учетной записи, Facebook, Google, GitHub и т. д. Для B2C не существует согласованного значения, используемого для preferred_username. Чтобы устранить препятствие для внедрения в MSAL совместимости кэша с ADAL, мы решили со своей стороны использовать значение «Отсутствует в ответе с токеном» при работе с учетными записями B2C, когда IdToken не возвращает значение preferred_username. MSAL должен возвращать значение для preferred_username для обеспечения совместимости кэша между библиотеками.

Обходные пути

Устранение недостатка tid

Рекомендуемый обходной путь — использовать кэширование по политике.

В качестве альтернативы, если вы используете пользовательские политики B2C, можно использовать утверждение tid, поскольку оно позволяет возвращать приложению дополнительные утверждения. Дополнительные сведения см. в разделе Claims Transformation.

Способ устранения проблемы «Отсутствует в ответе токена»

Один из вариантов — использовать утверждение «name» в качестве предпочтительного имени пользователя. Процесс обычно упоминается в этом документе B2C:

В столбце «Возвращаемое утверждение» выберите утверждения, которые нужно вернуть в токенах авторизации, отправляемых обратно в ваше приложение после успешного редактирования профиля. Например, выберите отображаемое имя, почтовый код".

Настройка пользовательского интерфейса

Настройте пользовательский интерфейс с помощью Azure AD B2C.