id_token_hint 使用 B2C 生成元数据端点时参数签名验证失败
id_token_hint parameter failed signature validation when Using B2C to generate the metadata endpoints
我正在尝试使用 Azure B2C 设置类似 Magic link 的系统。使用以下示例:
初级:
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
请注意,我相信我曾经让它工作过,但在清理之后我收到了错误:
The provided id_token_hint parameter failed signature validation. Please provide another token and try again.
我设置的步骤如下:
- 通过 powershell 创建证书并获取指纹以在本地代码中使用
- 通过MMC使用certmng导出证书
- 所有任务/导出/下一步/是,导出私钥
- 个人信息交换 - PKCS(包括证书路径中的所有证书)(启用证书隐私)
- 安全(密码)随机生成密码 25 个字符的密码。
- 姓名:id_token_hint_cert.pfx
- 浏览 Azure / B2C / Identity Experience Framework / Policy keys
- 添加/选项:上传/名称: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>();
}
这是我的家庭控制器,我在其中提交表单、创建令牌和 link,然后将其重定向到 link,将其用作 运行 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}&nonce={4}&redirect_uri={3}&scope=openid&response_type=id_token",
"myTenant",
"B2C_1A_SIGNIN_WITH_EMAIL",
"************************************",
Uri.EscapeDataString("https://jwt.ms"),
nonce)
+ "&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 });
}
}
}
位置位置位置。
我正在调整我了解到不应该做的基本配置文件。当我将更改应用到扩展文件时,一切都开始正常工作。
我正在尝试使用 Azure B2C 设置类似 Magic link 的系统。使用以下示例:
初级:
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
请注意,我相信我曾经让它工作过,但在清理之后我收到了错误:
The provided id_token_hint parameter failed signature validation. Please provide another token and try again.
我设置的步骤如下:
- 通过 powershell 创建证书并获取指纹以在本地代码中使用
- 通过MMC使用certmng导出证书
- 所有任务/导出/下一步/是,导出私钥
- 个人信息交换 - PKCS(包括证书路径中的所有证书)(启用证书隐私)
- 安全(密码)随机生成密码 25 个字符的密码。
- 姓名:id_token_hint_cert.pfx
- 浏览 Azure / B2C / Identity Experience Framework / Policy keys
- 添加/选项:上传/名称: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>();
}
这是我的家庭控制器,我在其中提交表单、创建令牌和 link,然后将其重定向到 link,将其用作 运行 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}&nonce={4}&redirect_uri={3}&scope=openid&response_type=id_token",
"myTenant",
"B2C_1A_SIGNIN_WITH_EMAIL",
"************************************",
Uri.EscapeDataString("https://jwt.ms"),
nonce)
+ "&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 });
}
}
}
位置位置位置。
我正在调整我了解到不应该做的基本配置文件。当我将更改应用到扩展文件时,一切都开始正常工作。