问题描述
我想要做的:通过 REST API 创建和配置 B2C 租户。
我做了什么:
我在默认目录中创建了一个名为 CDTester 的应用注册和一个密钥,然后将其添加到目标订阅中,角色为 Contributor
。
我从用户机密加载了一个配置对象 cfg,其中包含 CDTester 的应用程序 ID 和机密,以及我的默认目录的租户 ID 和目标订阅的 ID。
在代码中,我使用 ConfidentialClientApplicationBuilder
进行身份验证。
然后我使用我得到的令牌做一些事情:
- 我检查特定资源组是否存在
- 如果它不存在,我会创建它
- 我检查 B2C 租户所需的名称是否可用
- 我(尝试)创建租户。
步骤 1-3 工作正常。但是第 4 步给了我一个 401/Unauthorized。响应的正文被格式化为内容类型的 HTML(而不是 JSON)并且只包含
您无权查看此目录或页面。
因为第 1-3 步有效,所以我知道我的身份验证是正确的。我什至可以访问 B2C 特定的 API(我在第 3 步中使用)。
接下来,我进入 Portal 并将 CDTester
设为订阅的所有者,因此应该没有任何不允许它执行的操作。唉,无济于事,我得到了相同的结果。
作为参考,这里是我的代码的相关部分:
// getting the access token
var app = ConfidentialClientApplicationBuilder
.Create(authConfig.ApplicationId)
.WithTenantId(authConfig.LoginTenantId)
.WithClientSecret(authConfig.ApplicationSecret)
.Build();
var authResult = await app.AcquiretokenForClient(new[] {"https://management.azure.com/.default"})
.ExecuteAsync();
// I use FlurlHttp and set the token
FlurlHttp.Configure(s => s.BeforeCall = c => c.Request.Headers.Add("Authorization",$"Bearer {authResult.Accesstoken}"));
// this call works just fine
var nameAvailabilityResponse = await $"https://management.azure.com/subscriptions/{authConfig.SubscriptionId}/providers/Microsoft.AzureActiveDirectory/checkNameAvailability?api-version=2019-01-01-preview"
.PostJsonAsync(new
{
name = creation.FullDirectoryName,countryCode = creation.CountryCode
})
.ReceiveJson();
if (!nameAvailabilityResponse.nameAvailable)
{
await Console.Error.WriteLineAsync(nameAvailabilityResponse.message);
return ExitCodes.DirectoryNameIsNotAvailable;
}
var displayName = creation.EnvironmentName == "production"
? "DEON"
: $"DEON - {creation.EnvironmentName.toupperInvariant()}";
// this one gives the 401
var creationResponse = await $"https://management.azure.com/subscriptions/{authConfig.SubscriptionId}/resourceGroups/{creation.ResourceGroupName}/providers/Microsoft.AzureActiveDirectory/b2cDirectories/{creation.FullDirectoryName}?api-version=2019-01-01-preview"
.AllowAnyHttpStatus()
.PutJsonAsync(new
{
location = "Europe",properties = new
{
createTenantProperties = new
{
countryCode = creation.CountryCode,displayName
}
},sku = new
{
name = "Standard",tier = "A0"
}
});
谷歌搜索带来了零相关甚至半相关的命中。现在我卡住了。
解决方法
根据此处提供的答案:https://docs.microsoft.com/en-us/answers/questions/481152/creating-azure-b2c-tenant-via-rest-api-fails-with.html,您似乎无法使用服务主体创建 Azure AD B2C 租户(至少在今天如此)。
您需要在实际用户的上下文中执行此请求。换句话说,您需要获取令牌以执行具有 user_impersonation
范围的服务管理 API,而服务主体无法实现这一点。