Я пытаюсь использовать настраиваемые политики, в которых мне удалось развернуть REST API для получения групповых заявлений
<ClaimsSchema>
<ClaimType Id="groups">
<DisplayName>B2C-user-test,B2C-admin-test</DisplayName>
<DataType>stringCollection</DataType>
</ClaimType>
<!--Demo: List of permitted security groups user can sign-in.
Null or empty means, user any user can sign-in.
This claim sends to REST API-->
<ClaimType Id="onlyMembersOf">
<DisplayName>onlyMembersOf</DisplayName>
<DataType>string</DataType>
</ClaimType>
</ClaimsSchema>
</BuildingBlocks>
<ClaimsProviders>
<ClaimsProvider>
<DisplayName>Local Account</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
<OutputClaims>
<!--Demo: Add the groups claim type to the output claim collection-->
<OutputClaim ClaimTypeReferenceId="groups" />
</OutputClaims>
<ValidationTechnicalProfiles>
<!-- Demo: Make sure you first call the login-NonInteractive technical profile, to get the user ID.
Then call the role-based access control REST API to get adn validate user's groups -->
<ValidationTechnicalProfile ReferenceId="login-NonInteractive" />
<ValidationTechnicalProfile ReferenceId="REST-RBAC" />
</ValidationTechnicalProfiles>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
<!-- Local account Sign-In claims provider -->
<ClaimsProvider>
<DisplayName>Local Account SignIn</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="login-NonInteractive">
<Metadata>
<Item Key="client_id">444b09a2-0f8b-4f05-b454-54495b5ef601</Item>
<Item Key="IdTokenAudience">bd80807b-81d0-4732-a517-1132b128206c</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="client_id" DefaultValue="444b09a2-0f8b-4f05-b454-54495b5ef601" />
<InputClaim ClaimTypeReferenceId="resource_id" PartnerClaimType="resource" DefaultValue="bd80807b-81d0-4732-a517-1132b128206c" />
</InputClaims>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
<ClaimsProvider>
<DisplayName>REST APIs</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="REST-RBAC">
<DisplayName>Read and validate user's groups</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<!--Demo: Change the service URL with your REST API location-->
<Item Key="ServiceUrl">https://test.azurewebsites.net/api/Identity/IsMemberOf</Item>
<!--Demo: Change the AuthenticationType to basic or ClientCertificate.
For more information, see: https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-custom-rest-api-netfw-secure-cert-->
<Item Key="AuthenticationType">None</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="AllowInsecureAuthInProduction">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="BasicAuthenticationUsername" StorageReferenceId="B2C_1A_RestApiUsername" />
<Key Id="BasicAuthenticationPassword" StorageReferenceId="B2C_1A_RestApiPassword" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="objectId" />
<!--Demo: set the DefaultValue to empty string or comma delimiter list
of security groups to validate-->
<InputClaim ClaimTypeReferenceId="onlyMembersOf" DefaultValue="B2C-user-test" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="groups" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
</ClaimsProviders>
, поэтому политика TrustFrameworkExtensions выше вызывает метод Rest, но возвращает исключение оператора catch
catch (Exception ex)
{
if (ex.Message.Contains("Request_ResourceNotFound"))
{
return StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Can not read user groups, user not found", HttpStatusCode.Conflict));
}
return StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Can not read user groups", HttpStatusCode.Conflict));
}"
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using AADB2C.RBAC.Sample.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Net.Http;
namespace AADB2C.RBAC.Sample.Controllers
{
[Route("api/[controller]/[action]")]
public class IdentityController : Controller
{
private readonly AppSettingsModel AppSettings;
// Demo: Inject an instance of an AppSettingsModel class into the constructor of the consuming class,
// and let dependency injection handle the rest
public IdentityController(IOptions<AppSettingsModel> appSettings)
{
this.AppSettings = appSettings.Value;
}
[HttpPost(Name = "IsMemberOf")]
public async Task<ActionResult> IsMemberOf()
{
string input = null;
// If not data came in, then return
if (this.Request.Body == null)
{
return StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Request content is null", HttpStatusCode.Conflict));
}
//Read the input claims from the request body
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
input = await reader.ReadToEndAsync();
}
//string input = Request.Content.ReadAsStringAsync().Result;
//string content = "";
//System.Web.HttpContext.Current.Request.InputStream.Position = 0;
//using (var reader = new StreamReader(
// Request.InputStream, System.Text.Encoding.UTF8, true, 4096, true))
//{
// content = reader.ReadToEnd();
//}
////Rest
//System.Web.HttpContext.Current.Request.InputStream.Position = 0;
// Check input content value
if (string.IsNullOrEmpty(input))
{
return StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Request content is empty", HttpStatusCode.Conflict));
}
// Convert the input string into InputClaimsModel object
InputClaimsModel inputClaims = InputClaimsModel.Parse(input);
if (inputClaims == null)
{
return StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Can not deserialize input claims", HttpStatusCode.Conflict));
}
if (string.IsNullOrEmpty(inputClaims.objectId))
{
return StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("User 'objectId' is null or empty", HttpStatusCode.Conflict));
}
try
{
AzureADGraphClient azureADGraphClient = new AzureADGraphClient(this.AppSettings.Tenant, this.AppSettings.ClientId, this.AppSettings.ClientSecret);
// Demo: Get user's groups
GraphGroupsModel groups = await azureADGraphClient.GetUserGroup(inputClaims.objectId);
// Demo: Add the groups to string collections
List<string> groupsList = new List<string>();
foreach (var item in groups.value)
{
groupsList.Add(item.displayName);
}
// Demo: Set the output claims
OutputClaimsModel output = new OutputClaimsModel() { groups = groupsList };
// Demo: Check if user needs to be a member of a security group
if (!string.IsNullOrEmpty(inputClaims.onlyMembersOf))
{
List<string> onlyMembersOf = inputClaims.onlyMembersOf.ToLower().Split(',').ToList<string>();
bool isMemberOf = false;
foreach (var item in output.groups)
{
if (onlyMembersOf.Contains(item.ToLower()))
{
isMemberOf = true;
break;
}
}
// Demo: Throw error if user is not member of one of the security groups
if (isMemberOf == false)
{
return StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("You are not authorized to sign-in to this application.", HttpStatusCode.Conflict));
}
}
// Demo: Return the groups collection
return Ok(output);
}
catch (Exception ex)
{
if (ex.Message.Contains("Request_ResourceNotFound"))
{
return StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Can not read user groups, user not found", HttpStatusCode.Conflict));
}
return StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Can not read user groups", HttpStatusCode.Conflict));
}
}
}
}
Итак, я достиг точки, когда настраиваемая политика использует метод REST POST для получения сведений о группах, но этот упомянутый код не предоставляет мне сведения о группе, поскольку он переходит к оператору catch, а throws не может читать группы пользователей. Проблема здесь в том, что я не могу использовать localhost для запуска Rest API и попадать в точки останова API с помощью настраиваемой политики, поскольку он не поддерживается, я пробовал использовать ngrox.exe, но он возвращает мне неверный запрос.
Any помощь или пример будут очень полезны