Я хочу интегрировать Azure AD B2C в устаревшее приложение, запрограммированное с помощью .Net Framework v4.8. Дело в том, что я действительно не могу найти в Интернете ничего, что подходило бы для этой структуры.
Я также пробовал решения
Кто-нибудь уже сделал это и может дать мне несколько советов и рекомендаций по интеграции? Спасибо.
Обновлено: ответ Джеффа был именно тем, что мне нужно. Это то же самое, что и в учебнике, упомянутом Панайотисом в комментариях. Посмотрите здесь.
Вы пробовали проверять документацию вместо ChatGPT? Azure AD B2C был выпущен до самой .NET Framework 4.8. Несколько библиотек Azure AD появились и исчезли, а сам Azure AD теперь называется Entra.
@Panagiotis - конечно, но я придерживался пакетов, которые не мог интегрировать, потому что платформа v4.8 не поддерживалась.
Проверьте этот вопрос , который, в свою очередь, перенаправляет на руководство по документации и образец ASP.NET Framework, настроенный для использования Azure AD B2C. Из того, как написано это руководство, не ясно, что это не основной проект, но пример кода таковым является.
В целом документы Azure будут охватывать больше платформ, чем документы .NET, и для большинства случаев будут содержать готовые примеры. Однако пакеты Azure SDK меняются (относительно) часто, поэтому используемые сегодня имена могут не совпадать с именами в примерах.





MSAL — это официальная библиотека Microsoft для интеграции входа в систему OIDC/AD/AD B2C в ваше собственное приложение.
Поддерживается множество различных фреймворков, а также настольные приложения, написанные на WPF: https://learn.microsoft.com/en-us/entra/identity-platform/sample-v2-code?tabs=apptype#desktop
Пример кода для WPF можно найти здесь: https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2/tree/master/1.%20Desktop%20app%20calls%20Web% 20API
Однако эти примеры предназначены для AD, обычно в конфигурации MSAL есть опция, разговариваете ли вы с AD, AD B2C или просто с любым другим IDP OpenID Connect. Если у вас есть какие-либо конкретные проблемы с использованием этого кода, я предлагаю открыть для этого специальный вопрос с подробностями + кодом того, что не работает в вашем приложении.
Да, ты можешь. У меня все еще работает приложение ASP.Net Framework MVC, использующее B2C. Вот краткий обзор того, как я добавил B2C к существующему приложению.
Добавьте класс запуска OWIN, следуя инструкциям здесь — https://learn.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/getting-started-with-owin-and-katana# хост-owin-in-iis
В примере, которому я следовал (несколько лет назад), класс с именем Startup был настроен как частичный класс, разделенный между классом запуска Owin в примере (мой — Startup.cs) и файлом с именем Startup.Auth.cs в папке App_Start. (Если бы я все еще мог найти пример, я бы просто дал на него ссылку, но не могу, поэтому включаю соответствующий код.)
Мой Startup.cs выглядит так:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
// this controls the claim type that is used to populate User.Identity.Name
System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier = "emails";
ConfigureAuth(app);
}
}
Мой Startup.Auth.cs выглядит так (почти полностью из примера):
public partial class Startup
{
/*
* Configure the OWIN middleware
*/
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
// ASP.NET web host compatible cookie manager
CookieManager = new SystemWebChunkingCookieManager()
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// Generate the metadata address using the tenant and policy information
MetadataAddress = String.Format(Globals.WellKnownMetadata, Globals.Tenant, Globals.DefaultPolicy),
// These are standard OpenID Connect parameters, with values pulled from web.config
ClientId = Globals.ClientId,
RedirectUri = Globals.RedirectUri,
PostLogoutRedirectUri = Globals.RedirectUri,
// Specify the callbacks for each type of notifications
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed,
},
// Specify the claim type that specifies the Name property.
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "emails",
ValidateIssuer = false
},
// Specify the scope by appending all of the scopes requested into one string (separated by a blank space)
Scope = $"openid profile offline_access {Globals.ReadTasksScope} {Globals.WriteTasksScope}",
// ASP.NET web host compatible cookie manager
CookieManager = new SystemWebCookieManager()
}
);
}
/*
* On each call to Azure AD B2C, check if a policy (e.g. the profile edit or password reset policy) has been specified in the OWIN context.
* If so, use that policy when making the call. Also, don't request a code (since it won't be needed).
*/
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
var policy = notification.OwinContext.Get<string>("Policy");
if (!string.IsNullOrEmpty(policy) && !policy.Equals(Globals.DefaultPolicy))
{
notification.ProtocolMessage.Scope = OpenIdConnectScope.OpenId;
notification.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken;
notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(Globals.DefaultPolicy.ToLower(), policy.ToLower());
}
return Task.FromResult(0);
}
/*
* Catch any failures received by the authentication middleware and handle appropriately
*/
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
// Handle the error code that Azure AD B2C throws when trying to reset a password from the login page
// because password reset is not supported by a "sign-up or sign-in policy"
if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90118"))
{
// If the user clicked the reset password link, redirect to the reset password route
notification.Response.Redirect("/Account/ResetPassword");
}
else if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90091"))
{
notification.Response.Redirect("/Home/Index");
}
else if (notification.Exception.Message == "access_denied")
{
notification.Response.Redirect("/");
}
else
{
notification.Response.Redirect("/Home/Error?message = " + notification.Exception.Message);
}
return Task.FromResult(0);
}
/*
* Callback function when an authorization code is received
*/
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
{
try
{
/*
The `MSALPerUserMemoryTokenCache` is created and hooked in the `UserTokenCache` used by `IConfidentialClientApplication`.
At this point, if you inspect `ClaimsPrinciple.Current` you will notice that the Identity is still unauthenticated and it has no claims,
but `MSALPerUserMemoryTokenCache` needs the claims to work properly. Because of this sync problem, we are using the constructor that
receives `ClaimsPrincipal` as argument and we are getting the claims from the object `AuthorizationCodeReceivedNotification context`.
This object contains the property `AuthenticationTicket.Identity`, which is a `ClaimsIdentity`, created from the token received from
Azure AD and has a full set of claims.
*/
IConfidentialClientApplication confidentialClient = MsalAppBuilder.BuildConfidentialClientApplication(new ClaimsPrincipal(notification.AuthenticationTicket.Identity));
// Upon successful sign in, get & cache a token using MSAL
AuthenticationResult result = await confidentialClient.AcquireTokenByAuthorizationCode(Globals.Scopes, notification.Code).ExecuteAsync();
}
catch (Exception ex)
{
throw new HttpResponseException(new HttpResponseMessage
{
StatusCode = HttpStatusCode.BadRequest,
ReasonPhrase = $"Unable to get authorization code {ex.Message}."
});
}
}
}
У меня есть эти значения в разделе настроек приложения web.config (очевидно, замените их значениями из регистрации приложения):
<add key = "ida:Tenant" value = "tenantname.onmicrosoft.com" />
<add key = "ida:TenantId" value = "hidden" />
<add key = "ida:ClientId" value = "hidden" />
<add key = "ida:ClientSecret" value = "hidden" />
<add key = "ida:AadInstance" value = "https://tenantname.b2clogin.com/tfp/{0}/{1}" />
<add key = "ida:RedirectUri" value = "https://homepageurl" />
<add key = "ida:SignUpSignInPolicyId" value = "b2c_1_susi" />
<add key = "ida:EditProfilePolicyId" value = "b2c_1_edit_profile" />
<add key = "ida:ResetPasswordPolicyId" value = "b2c_1_reset" />
Вы можете увидеть пару мест, где я использую «электронные письма» для заполнения User.Identity.Name. При желании вы можете указать другую претензию.
Спасибо за этот ответ @jefftrotman! Но у меня есть вопрос: как я могу получить атрибуты пользователя из утверждений, содержащихся в Id-Token?
Взгляните на пример здесь Learn.microsoft.com/en-us/dotnet/api/…
Я почти уверен, что ты сможешь. AAD B2C использует OpenID Connect (или, я думаю, SAML), поэтому, пока вы можете его использовать, вы можете использовать AAD B2C.