#.net-core #metadata #openid-connect #azure-ad-b2c-custom-policy #self-signed-certificate
Вопрос:
Я пытаюсь настроить систему, подобную Magic link, с использованием Azure B2C. Используя следующие примеры: Первичный:
https://github.com/azure-ad-b2c/samples/tree/master/policies/sign-in-with-magic-link
Для того, чтобы sing B2C генерировал конечные точки метаданных: https://github.com/azure-ad-b2c/samples/tree/master/policies/invite#using-b2c-to-generate-the-metadata-endpoints
В качестве примечания я полагаю, что в какой-то момент он работал, но после очистки я получал ошибку:
Предоставленный параметр id_token_hint не прошел проверку подписи. Пожалуйста, укажите другой токен и повторите попытку.
Шаги, которые я предпринял для настройки, следующие:
- Создайте сертификат с помощью powershell и получите отпечаток пальца для использования в локальном коде
- Используйте certmng через MMC для экспорта сертификата
- Все задачи / Экспорт / Следующий / Да, экспортируйте закрытый ключ
- Обмен персональной информацией — PKCS (включить все сертификаты в путь к сертификату) (включить конфиденциальность сертификата)
- Безопасность (пароль) Случайно сгенерированный пароль из 25 символов.
- Имя: id_token_hint_cert.pfx
- Просмотрите Azure / B2C / Identity Experience Framework / Ключи политики
- Добавить / Параметр: загрузить / Имя: IdTokenHintCert / Загрузка файла id_token_hint_cert.pfx / Пароль: пароль из программы установки 3
Здесь я попробовал 2 разные настройки. Первым делом нужно было настроить набор пользовательских политик, чтобы я мог обновить следующего поставщика утверждений, чтобы для issuer_secret было установлено значение B2C_1A_IdTokenHintCert
<ClaimsProvider>
<DisplayName>Token Issuer</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="JwtIssuer">
<DisplayName>JWT Issuer</DisplayName>
<Protocol Name="None" />
<OutputTokenFormat>JWT</OutputTokenFormat>
<Metadata>
<Item Key="client_id">{service:te}</Item>
<Item Key="issuer_refresh_token_user_identity_claim_type">objectId</Item>
<Item Key="SendTokenResponseBodyWithJsonNumbers">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_IdTokenHintCert" />
<Key Id="issuer_refresh_token_key" StorageReferenceId="B2C_1A_TokenEncryptionKeyContainer" />
</CryptographicKeys>
<InputClaims />
<OutputClaims />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
Это набор политик, полученных из https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/tree/master/LocalAccounts и обновлен для моего арендатора, но оставлен в основном в покое.
Я также попытался изменить issuer_secret в своих основных пользовательских политиках с выводом той же ошибки.
Переход к моему коду: это важная часть моего запуска:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(
OpenIdConnectDefaults.AuthenticationScheme
).AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C"),"OpenIdConnect", "Cookies",true);
services.AddControllersWithViews();
services.AddRazorPages()
.AddMicrosoftIdentityUI();
services.AddTransient<IClaimsTransformation, AppClaimsTransformations>();
}
И вот мой домашний контроллер, на котором я отправляю форму, создаю токен и ссылку, а затем просто перенаправляю на эту ссылку, используя ее в качестве конечной точки run now. (Я знаю, что это не закончится, но мне нужно проверить подпись, прежде чем я смогу двигаться дальше.)
public class HomeController : Controller
{
private static Lazy<X509SigningCredentials> SigningCredentials;
private readonly AppSettingsModel _appSettings;
private readonly IWebHostEnvironment HostingEnvironment;
private readonly ILogger<HomeController> _logger;
// Sample: Inject an instance of an AppSettingsModel class into the constructor of the consuming class,
// and let dependency injection handle the rest
public HomeController(ILogger<HomeController> logger, IOptions<AppSettingsModel> appSettings, IWebHostEnvironment hostingEnvironment)
{
_appSettings = appSettings.Value;
this.HostingEnvironment = hostingEnvironment;
this._logger = logger;
// Sample: Load the certificate with a private key (must be pfx file)
SigningCredentials = new Lazy<X509SigningCredentials>(() =>
{
X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
"***************************************",
false);
// Get the first cert with the thumb-print
if (certCollection.Count > 0)
{
return new X509SigningCredentials(certCollection[0]);
}
throw new Exception("Certificate not found");
});
}
[HttpGet]
public ActionResult Index(string Name, string email, string phone)
{
if (string.IsNullOrEmpty(email))
{
ViewData["Message"] = "";
return View();
}
string token = BuildIdToken(Name, email, phone);
string link = BuildUrl(token);
return Redirect(link);
}
private string BuildIdToken(string Name, string email, string phone)
{
string issuer = $"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase.Value}/";
// All parameters send to Azure AD B2C needs to be sent as claims
IList<System.Security.Claims.Claim> claims = new List<System.Security.Claims.Claim>();
claims.Add(new System.Security.Claims.Claim("name", Name, System.Security.Claims.ClaimValueTypes.String, issuer));
claims.Add(new System.Security.Claims.Claim("email", email, System.Security.Claims.ClaimValueTypes.String, issuer));
if (!string.IsNullOrEmpty(phone))
{
claims.Add(new System.Security.Claims.Claim("phone", phone, System.Security.Claims.ClaimValueTypes.String, issuer));
}
// Create the token
JwtSecurityToken token = new JwtSecurityToken(
issuer,
"******************************************",
claims,
DateTime.Now,
DateTime.Now.AddDays(7),
HomeController.SigningCredentials.Value);
// Get the representation of the signed token
JwtSecurityTokenHandler jwtHandler = new JwtSecurityTokenHandler();
return jwtHandler.WriteToken(token);
}
private string BuildUrl(string token)
{
string nonce = Guid.NewGuid().ToString("n");
return string.Format("https://{0}.b2clogin.com/{0}.onmicrosoft.com/{1}/oauth2/v2.0/authorize?client_id={2}amp;nonce={4}amp;redirect_uri={3}amp;scope=openidamp;response_type=id_token",
"myTenant",
"B2C_1A_SIGNIN_WITH_EMAIL",
"************************************",
Uri.EscapeDataString("https://jwt.ms"),
nonce)
"amp;id_token_hint=" token;
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
Ответ №1:
Местоположение Местоположение Местоположение.
Я настраивал базовый профиль, который, как я узнал, я не должен делать. Когда я применил свое изменение к файлу расширения, вместо этого все начало работать правильно.