使用 Graph SDK 将角色添加到 Azure AD B2C 中的现有用户

发布于 2025-01-15 16:58:07 字数 149 浏览 0 评论 0原文

我们使用 GRAPH SDK 来管理 Azure AD B2C 中的用户。 我们已经能够创建一个用户帐户,现在想要为该用户分配一个角色。 我们已经参考了文档,但无法找到前进的方向。 有没有一种方法可以使用 Graph SDK 为用户分配角色

如有任何帮助,我们将不胜感激

We are using GRAPH SDK to manage users In Azure AD B2C.
We have been able to create an user account and now want to assign a role to the user.
We have referred the documentation but not able to find the way forward.
Is there a way we can assign role to a user using Graph SDK

Any help on this would be appreciated

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

等数载,海棠开 2025-01-22 16:58:07

遗憾的是,Azure AD B2C 并不真正支持开箱即用的角色。有几种方法可以做到这一点。如果您想在登录时将角色添加到令牌中,则必须使用自定义策略和 API 调用(或 Azure 函数)将角色添加到您的声明中。如果您不熟悉自定义策略,我强烈建议您建议先阅读自定义策略的官方文档

如果您只想管理角色而不在登录时将其添加到令牌中。您可以在 ActiveDirectory 中(与 B2C 租户位于同一目录中)创建安全组。这应该看起来像这样。
输入图片此处描述
然后,您可以使用 获取群组通话。列出调用成员

GET /groups/{id}
GET /me/memberOf
GET /users/{id | userPrincipalName}/memberOf

当然你也可以 将用户添加到组

POST /groups/{group-id}/members/$ref

如果您确实想在登录时将角色添加到令牌中,我个人使用了该视频。 https://www.youtube.com/watch?v=C9qN6QqnxQ8 Azure 函数,但如果您愿意,您也可以使用自己的 API。

重要提示:您无法在自定义策略中使用 localhost 测试对您自己的 API 的调用,因此请确保使用 ngrok。

我还将描述这些步骤: 首先将角色(或多个角色)ClaimTypeReferenceId 添加到您的 SignUp.xml

  <TechnicalProfile Id="PolicyProfile">
      <DisplayName>PolicyProfile</DisplayName>
      <Protocol Name="OpenIdConnect" />
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="email" />
        Other claims
        <OutputClaim ClaimTypeReferenceId="role" />
      </OutputClaims>
      <SubjectNamingInfo ClaimType="sub" />
    </TechnicalProfile>

在 TrustFrameworkExtensions.xml 中添加声明类型角色(或多个角色)

 <ClaimType Id="role">
    <DisplayName>Role</DisplayName>
    <DataType>stringCollection</DataType> <!-- or string if you only want 1 role -->
 </ClaimType>

将 Rest API 调用添加到您的 TrustFrameworkExtensions.xml。这会将 API 调用的参数设置为您在登录时收到的电子邮件地址,并且它期望得到一个角色。

 <ClaimsProvider>
      <DisplayName>REST APIs</DisplayName>
      <TechnicalProfiles>
        <TechnicalProfile Id="REST-GetProfile">
          <DisplayName>Get user extended profile Azure Function web hook</DisplayName>
          <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
          <Metadata>
            <!-- Set the ServiceUrl with your own REST API endpoint -->
            <Item Key="ServiceUrl">https://functions.azurewebsites.net/api/HttpTriggerGetRoles?code=YOURCODE</Item> <!-- TODO CHANGE THIS URL to your own-->
            <Item Key="SendClaimsIn">Body</Item>
            <!-- Set AuthenticationType to Basic or ClientCertificate in production environments -->
            <Item Key="AuthenticationType">None</Item>
            <!-- REMOVE the following line in production environments -->
            <Item Key="AllowInsecureAuthInProduction">true</Item>
          </Metadata>
          <InputClaims>
            <!-- Claims sent to your REST API -->
            <InputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="emails" />
            <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="email" />
          </InputClaims>
          <OutputClaims>
            <!-- Claims parsed from your REST API -->
            <OutputClaim ClaimTypeReferenceId="role" PartnerClaimType="role"/>
          </OutputClaims>
          <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>

最后,将 GetRoleData TechnicalProfile 添加到倒数第二个 OrchestrationStep

        <OrchestrationStep Order="10" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="GetRoleData" TechnicalProfileReferenceId="REST-GetProfile" />
          </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="11" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />

为了测试,我使用以下 C# 代码创建了一个 Azure 函数。在这个例子中,我只是将其硬编码。但您可以从此处调用图形 API。

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static IActionResult Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string[] roles = {"Admin", "Employee"};
    var adminrole = new {
        role = roles
    };

    return new OkObjectResult(adminrole);
}

// string email = req.Query["email"];

    // string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    // dynamic data = JsonConvert.DeserializeObject(requestBody);
    // email = email ?? data?.email;

您的令牌现在应该包含角色。

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "H-0"
}.{
  "iss": "https://demo.b2clogin.com/9729/v2.0/",
  "exp": 164,
  "nbf": 1634,
  "aud": "4a12ea396",
  "given_name": "Tim C",
  "family_name": "C",
  "name": "Tim",
  "idp": "google.com",
  "sub": "adc1",
  "role": [
    "Admin",
    "Employee"
  ],
  "scp": "demo.write demo.read",
  "ver": "1.0",
}.[Signature]

Azure AD B2C does not really support roles out of the box sadly. There are a couple of ways to do this. If you want to add the roles to your token on sign-in, then you will have to use custom policies and an API call (or Azure Function) to add roles to your claims. If you are new to custom policies, I highly recommend reading the official documentation on custom policies first.

If you only want to manage roles without adding them to your token on sign-in. You can create Security groups in your ActiveDirectory (In the same directory as your B2C tenant). This should look something like this.
enter image description here
You can then use the Get Groups call. or list memberOf call.

GET /groups/{id}
GET /me/memberOf
GET /users/{id | userPrincipalName}/memberOf

Ofcourse you can also add users to the groups

POST /groups/{group-id}/members/$ref

If you do want to add the roles to your token on sign-in, I personally used the video. https://www.youtube.com/watch?v=C9qN6QqnxQ8 This uses an Azure function but you can also use your own API if you want to.

IMPORTANT: You cannot test calls to your own API with localhost in custom policies, so make sure to make it available with something like ngrok.

I will describe the steps as well: First add the role (or roles) ClaimTypeReferenceId to your SignUp.xml

  <TechnicalProfile Id="PolicyProfile">
      <DisplayName>PolicyProfile</DisplayName>
      <Protocol Name="OpenIdConnect" />
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="email" />
        Other claims
        <OutputClaim ClaimTypeReferenceId="role" />
      </OutputClaims>
      <SubjectNamingInfo ClaimType="sub" />
    </TechnicalProfile>

In the TrustFrameworkExtensions.xml add the claimtype role (or roles)

 <ClaimType Id="role">
    <DisplayName>Role</DisplayName>
    <DataType>stringCollection</DataType> <!-- or string if you only want 1 role -->
 </ClaimType>

Add the Rest API call to your TrustFrameworkExtensions.xml. This sets the Parameters of your API call to an email address which you have received from the sign-in, and it expects a role as a result.

 <ClaimsProvider>
      <DisplayName>REST APIs</DisplayName>
      <TechnicalProfiles>
        <TechnicalProfile Id="REST-GetProfile">
          <DisplayName>Get user extended profile Azure Function web hook</DisplayName>
          <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
          <Metadata>
            <!-- Set the ServiceUrl with your own REST API endpoint -->
            <Item Key="ServiceUrl">https://functions.azurewebsites.net/api/HttpTriggerGetRoles?code=YOURCODE</Item> <!-- TODO CHANGE THIS URL to your own-->
            <Item Key="SendClaimsIn">Body</Item>
            <!-- Set AuthenticationType to Basic or ClientCertificate in production environments -->
            <Item Key="AuthenticationType">None</Item>
            <!-- REMOVE the following line in production environments -->
            <Item Key="AllowInsecureAuthInProduction">true</Item>
          </Metadata>
          <InputClaims>
            <!-- Claims sent to your REST API -->
            <InputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="emails" />
            <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="email" />
          </InputClaims>
          <OutputClaims>
            <!-- Claims parsed from your REST API -->
            <OutputClaim ClaimTypeReferenceId="role" PartnerClaimType="role"/>
          </OutputClaims>
          <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>

Lastly, add the GetRoleData TechnicalProfile to your second to last OrchestrationStep

        <OrchestrationStep Order="10" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="GetRoleData" TechnicalProfileReferenceId="REST-GetProfile" />
          </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="11" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />

For testing I created an Azure Function with the following code in C#. In this example I just put it hard coded. But you could make a call to the graph API from here.

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static IActionResult Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string[] roles = {"Admin", "Employee"};
    var adminrole = new {
        role = roles
    };

    return new OkObjectResult(adminrole);
}

// string email = req.Query["email"];

    // string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    // dynamic data = JsonConvert.DeserializeObject(requestBody);
    // email = email ?? data?.email;

Your token should now contain the roles.

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "H-0"
}.{
  "iss": "https://demo.b2clogin.com/9729/v2.0/",
  "exp": 164,
  "nbf": 1634,
  "aud": "4a12ea396",
  "given_name": "Tim C",
  "family_name": "C",
  "name": "Tim",
  "idp": "google.com",
  "sub": "adc1",
  "role": [
    "Admin",
    "Employee"
  ],
  "scp": "demo.write demo.read",
  "ver": "1.0",
}.[Signature]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文