حكاية كيف قمت بتكوين Azure AD B2C على رد فعل وتفاعل الجزء الأصلي 2 (برنامج تعليمي)

صورة

مقدمة


استمرار دورة العمل مع Azure B2C. سأتحدث في هذه المقالة عن النقطة الأكثر صعوبة وغير الواضحة ، وهي إطار تجربة الهوية.

الهدف الرئيسي هو وضع صورة لأولئك الذين ليسوا على الإطلاق في الموضوع والمساعدة في إعداد بعض الميزات الأساسية.

روابط إلى الوظائف ذات الصلة


الإعداد الأساسي


قبل بدء الإعداد الأساسي ، أود أن أخبرك كيف تحدث عملية تحميل القواعد الجديدة:

  1. انتقل إلى إطار تجربة الهوية
  2. انقر فوق إرسال سياسة المستخدم
  3. حدد ملفًا (لا تنس النقر على "استبدال السياسة المخصصة ، إذا كانت موجودة بالفعل")
  4. نحن نرسل

صورة

في الواقع ، لم يتغير شيء منذ آخر مرة ، ولكن:
إذا قمت بتغيير الملف TrustFrameworkExtension.xml أو TrustFrameworkBase.xml - قم بتنزيل الملف الذي يشير إليهم بشكل دوري.
في بعض الأحيان ، عندما تجري تغييرات على أحد هذه الملفات ، تختبر ، ويحدث أن التغييرات لا تظهر. هذا يرجع إلى حقيقة
أنك قمت بتغيير شيء ما في الملف الأساسي بحيث أنه أثناء التحقق سيؤدي الملف الفرعي إلى حدوث خطأ.

في المقالة الأخيرة ، استقرنا على حقيقة أننا أضفنا الملفات التالية:
a.TrustFrameworkBase.xml
b.TrustFrameworkExtensions.xml
ج. SignUpOrSignin. XML
d.ProfileEdit. XML
e.PasswordReset. XML

الآن أود أن أقول بالتفصيل عن كل منهم.

TrustFrameworkBase.xml

يحتوي هذا الملف على الإعداد الأساسي. في الواقع ، إنه أساس الأساسيات ، ولكن في البرامج التعليمية يقولون غالبًا "من الأفضل عدم لمس هذا الملف". هذا صحيح جزئيًا ، ولكن هناك بعض النقاط التي لا يتم الحديث عنها:

  1. أي برنامج تعليمي يقول إجراء تغييرات على TrustFrameworkExtensions.xml يعيد كتابة القواعد من TrustFrameworkBase.xml
  2. هناك حالات يكون من المناسب فيها تغيير شيء ما في TrustFrameworkBase.xml .
  3. إذا وجدت في ملفات أخرى ارتباطًا لكائن غير موجود في هذه الملفات ، فإنه يقع 100٪ في TrustFrameworkBase.xml ويمكنك فتحه ورؤية

من تجربتي سأقول - لقد غيرت شيئين فقط في هذا الملف (الأقلمة وحذف حقل واحد).

TrustFrameworkExtension.xml

باستخدام هذا الملف ، ستقضي الكثير من الوقت معًا. في الواقع ، هذا هو الملف الرئيسي لإعداداتك. هو مذكور باستمرار في الدروس.

تسجيل الدخول. XML ، ProfileEdit. XML ، PasswordReset. XML

هذه الملفات صفحات طرفية. ربما تريد أن تضيف لك. سيكون لديهم أقل قدر من التغيير.

الآن دعونا نتحدث عن هيكل الملف. جميع الملفات لها بنية متشابهة ، لذلك سأصفها على أساس ملف TrustFrameworkExtension.xml .

ينقسم الملف إلى عدة كتل رئيسية

<TrustFrameworkPolicy>
  <BasePolicy> <!--     -->
      <TenantId>customtenant.onmicrosoft.com</TenantId>
      <PolicyId>B2C_1A_TrustFrameworkBase</PolicyId>
  </BasePolicy>

  <BuildingBlocks> <!--       UI -->
  </BuildingBlocks>

  <ClaimsProviders> <!--        JWT token) -->
  </ClaimsProviders>
  
  <UserJourneys> <!--       -->
  </UserJourneys>
</TrustFrameworkPolicy>

الآن عن كل كتلة على حدة.

اللبنات


في هذه المجموعة نضيف "أدوات" يمكننا استخدامها في العمل المستقبلي.

ClaimsSchema

عنصر ClaimsSchema يحدد أنواع البيانات التي يمكن الرجوع إليها في هذه السياسة.

  <BuildingBlocks>
    <ClaimsSchema>
      <ClaimType Id="picture"><!--      UI     -->
        <DisplayName>Picture</DisplayName>
        <DataType>string</DataType>
      </ClaimType>
      <ClaimType Id="country"><!--     -->
        <DisplayName>Country</DisplayName>
        <DataType>string</DataType>
        <UserInputType>DropdownSingleSelect</UserInputType>
        <Restriction>
          <Enumeration Text="Russia" Value="russia" SelectByDefault="false" />
          <Enumeration Text="Other" Value="other" SelectByDefault="false" />
        </Restriction>
      </ClaimType>
           ...
    </ClaimsSchema>
  

المسندات

المسندات وعناصر التحقق من صحة الأصلية تسمح التحقق للتأكد من أن البيانات فقط شكلت بشكل صحيح يتم إدخالها في أزور خدمة Active Directory B2C العميل (B2C أزور AD).

    <Predicates> <!--     ,       -->
      <Predicate Id="LengthRange" Method="IsLengthRange">
        <UserHelpText>The password must be between 6 and 64 characters.</UserHelpText>
        <Parameters>
          <Parameter Id="Minimum">6</Parameter>
          <Parameter Id="Maximum">64</Parameter>
        </Parameters>
      </Predicate>
      <Predicate Id="Lowercase" Method="IncludesCharacters">
        <UserHelpText>a lowercase letter</UserHelpText>
        <Parameters>
          <Parameter Id="CharacterSet">a-z</Parameter>
        </Parameters>
      </Predicate>
          ...
    </Predicates>
  

في

حين أن المسندات تحدد ما إذا كان نوع التأكيد يتم التحقق منه أم لا ، تقوم PredicateValidations بتجميع مجموعة من المسندات لتشكيل فحص إدخال مستخدم يطابق نوع التأكيد.

    <PredicateValidations> <!--       -->
      <PredicateValidation Id="CustomPassword">
        <PredicateGroups>
          <PredicateGroup Id="LengthGroup">
            <PredicateReferences MatchAtLeast="1">
              <PredicateReference Id="LengthRange" />
            </PredicateReferences>
          </PredicateGroup>
          <PredicateGroup Id="CharacterClasses">
            <UserHelpText>The password must have at least 1 of the following:</UserHelpText>
            <PredicateReferences MatchAtLeast="2">
              <PredicateReference Id="Lowercase" /> <!--   ,    -->
              <PredicateReference Id="Uppercase" />
                    ...
            </PredicateReferences>
          </PredicateGroup>
        </PredicateGroups>
      </PredicateValidation>
    </PredicateValidations>
  

ClaimsTransformations

عنصر ClaimsTransformations يحتوي على قائمة من الوظائف تأكيدات التحول التي يمكن استخدامها في طريقة تفاعل المستخدم كجزء من سياسة مخصصة.

    <ClaimsTransformations> <!--      -->
      <ClaimsTransformation Id="GenerateSendGridRequestBody" TransformationMethod="GenerateJson">
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="personalizations.0.to.0.email" />
          <InputClaim ClaimTypeReferenceId="otp" TransformationClaimType="personalizations.0.dynamic_template_data.otp" />
          <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="personalizations.0.dynamic_template_data.email" />
        </InputClaims>
        <InputParameters>
          <InputParameter Id="template_id" DataType="string" Value="d-b0000000000000000000000000000000" /> <!-- Template ID SendGrid (    ) -->
          <InputParameter Id="from.email" DataType="string" Value="custom@email.com" />
          <InputParameter Id="personalizations.0.dynamic_template_data.subject" DataType="string" Value="Welcome to Habr!"/>
        </InputParameters>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="sendGridReqBody" TransformationClaimType="outputClaim" />
        </OutputClaims>
      </ClaimsTransformation>
            ...
    </ClaimsTransformations>
  

ContentDefinitions

يتيح لك تحديد قوالب لكل صفحة من صفحاتك.

    <ContentDefinitions> <!--         -->
      <ContentDefinition Id="api.signuporsignin">
        <LoadUri>https://azure.blob.core.windows.net/yourblobstorage/pagelayoutfile.html</LoadUri>
        <RecoveryUri>~/common/default_page_error.html</RecoveryUri>
        <DataUri>urn:com:microsoft:aad:b2c:elements:contract:unifiedssp:1.2.0</DataUri>
      </ContentDefinition>
          ...
    </ContentDefinitions>
  

DisplayControls

عنصر تحكم العرض هو عنصر واجهة مستخدم له ميزات خاصة ويتفاعل مع خدمة خادم Azure Active Directory B2C (Azure AD B2C)

    <DisplayControls> <!--      -->
      <DisplayControl Id="emailVerificationControl" UserInterfaceControlType="VerificationControl">
        <DisplayClaims> <!--   -->
          <DisplayClaim ClaimTypeReferenceId="email" Required="true" />
          <DisplayClaim ClaimTypeReferenceId="verificationCode" ControlClaimType="VerificationCode" Required="true" />
        </DisplayClaims>
        <OutputClaims> <!--   (     ) -->
          <OutputClaim ClaimTypeReferenceId="email" />
        </OutputClaims>
        <Actions>
          <Action Id="SendCode"> <!--        -->
            <ValidationClaimsExchange>
              <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="GenerateOtp" />
              <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="SendGrid" />
            </ValidationClaimsExchange>
          </Action>
            ...
        </Actions>
      </DisplayControl>
          ...
    </DisplayControls>
  </BuildingBlocks>

مطالبات مقدمي


في هذه الكتلة ، سنقوم بإنشاء الصفحات بأنفسهم ، أو بالأحرى محتواها. سنوضح هنا ما تحتويه الصفحة من بيانات إدخال وإخراج. يربط

ClaimsProvider الملفات الشخصية التقنية بمزود المطالبات.

  <ClaimsProviders>
    <ClaimsProvider> <!--   -          -->
      <DisplayName>Self Asserted</DisplayName>
    

يحتوي عنصر TechnicalProfiles على مجموعة من ملفات التعريف الفنية التي يدعمها موفر المطالبات.

      <TechnicalProfiles>
        <TechnicalProfile Id="SelfAsserted-Social">
          <DisplayName>User ID signup</DisplayName>
          <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
          <Metadata>
            <Item Key="ContentDefinitionReferenceId">api.selfasserted</Item> <!--  . (        ,   )-->
          </Metadata>
          <CryptographicKeys>
            <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" /> <!--       -->
          </CryptographicKeys>
          <InputClaims> <!--   ..          -->
            <InputClaim ClaimTypeReferenceId="givenName" />
            <InputClaim ClaimTypeReferenceId="surname" />
          </InputClaims>
          <OutputClaims> <!--  .       ,      (   ) -->
              <!-- These claims ensure that any values retrieved in the previous steps (e.g. from an external IDP) are prefilled. 
                 Note that some of these claims may not have any value, for example, if the external IDP did not provide any of
                 these values, or if the claim did not appear in the OutputClaims section of the IDP.
                 In addition, if a claim is not in the InputClaims section, but it is in the OutputClaims section, then its
                 value will not be prefilled, but the user will still be prompted for it (with an empty value). -->
            <OutputClaim ClaimTypeReferenceId="objectId" />
            <OutputClaim ClaimTypeReferenceId="newUser" />
            <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />

            <!-- Optional claims. These claims are collected from the user and can be modified. If a claim is to be persisted in the directory after having been 
                 collected from the user, it needs to be added as a PersistedClaim in the ValidationTechnicalProfile referenced below, i.e. 
                 in AAD-UserWriteUsingAlternativeSecurityId. -->
            <OutputClaim ClaimTypeReferenceId="givenName" Required="true"/>
            <OutputClaim ClaimTypeReferenceId="surname" Required="true"/>
            <OutputClaim ClaimTypeReferenceId="country" Required="true"/>
          </OutputClaims>
        </TechnicalProfile>
      </ClaimsProvider>
      

مثال على إضافة موفري هوية Facebook


    <ClaimsProvider> <!--    .       -->
      <DisplayName>Facebook</DisplayName>
      <TechnicalProfiles>
        <TechnicalProfile Id="Facebook-OAUTH">
          <Metadata>
            <Item Key="client_id">FACEBOOK_ID</Item>
            <Item Key="scope">email public_profile</Item>
            <Item Key="ClaimsEndpoint">https://graph.facebook.com/me?fields=id,first_name,last_name,name,email,picture</Item>
          </Metadata>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="picture" PartnerClaimType="picture" />
          </OutputClaims>
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>
  

TrustFrameworkBase.xml

      <ClaimsProvider>
        <!-- The following Domain element allows this profile to be used if the request comes with domain_hint 
             query string parameter, e.g. domain_hint=facebook.com  -->
        <Domain>facebook.com</Domain>
        <DisplayName>Facebook</DisplayName>
        <TechnicalProfiles>
          <TechnicalProfile Id="Facebook-OAUTH">
            <!-- The text in the following DisplayName element is shown to the user on the claims provider 
                 selection screen. -->
            <DisplayName>Facebook</DisplayName>
            <Protocol Name="OAuth2" />
            <Metadata>
              <Item Key="ProviderName">facebook</Item>
              <Item Key="authorization_endpoint">https://www.facebook.com/dialog/oauth</Item>
              <Item Key="AccessTokenEndpoint">https://graph.facebook.com/oauth/access_token</Item>
              <Item Key="HttpBinding">GET</Item>
              <Item Key="UsePolicyInRedirectUri">0</Item>
  
              <!-- The Facebook required HTTP GET method, but the access token response is in JSON format from 3/27/2017 -->
              <Item Key="AccessTokenResponseFormat">json</Item>
            </Metadata>
            <CryptographicKeys>
              <Key Id="client_secret" StorageReferenceId="B2C_1A_FacebookSecret" />
            </CryptographicKeys>
            <InputClaims />
            <OutputClaims>
              <OutputClaim ClaimTypeReferenceId="issuerUserId" PartnerClaimType="id" />
              <OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="first_name" />
              <OutputClaim ClaimTypeReferenceId="surname" PartnerClaimType="last_name" />
              <OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="name" />
              <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="email" />
              <OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="facebook.com" AlwaysUseDefaultValue="true" />
              <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="socialIdpAuthentication" AlwaysUseDefaultValue="true" />
            </OutputClaims>
            <OutputClaimsTransformations>
              <OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName" />
              <OutputClaimsTransformation ReferenceId="CreateUserPrincipalName" />
              <OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId" />
            </OutputClaimsTransformations>
            <UseTechnicalProfileForSessionManagement ReferenceId="SM-SocialLogin" />
          </TechnicalProfile>
        </TechnicalProfiles>
      </ClaimsProvider>


رحلات المستخدم


على المستخدم UserJourneys تشير إلى مسارات واضحة من خلالها سياسة تسمح تطبيق يستند إلى المطالبات لتوفير للمستخدم مع المطالبات المطلوبة.

أدناه أضفت بضعة أشياء بسيطة ، من السهل العثور على الباقي في الدروس التي سأضيفها أدناه.

  <UserJourneys>
    <UserJourney Id="SignUp"> <!--  ID UserJourney.       ,     TrustFrameworkExtension.xml-->
      <OrchestrationSteps><!--  .   -->
        <OrchestrationStep Order="1" Type="ClaimsExchange" ContentDefinitionReferenceId="api.localaccountsignup">
          <ClaimsExchanges> <!--       TechnicalProfileReferenceId. Id   ,       -->
            <ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail-2" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="2" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" /> <!--     -->
      </OrchestrationSteps>
      <ClientDefinition ReferenceId="DefaultWeb" />
    </UserJourney>
    <UserJourney Id="PasswordReset">
      <OrchestrationSteps>
        <OrchestrationStep Order="1" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="PasswordResetUsingEmailAddressExchange" TechnicalProfileReferenceId="LocalAccountDiscoveryUsingEmailAddress" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="2" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordUsingObjectId" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="3" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
      </OrchestrationSteps>
      <ClientDefinition ReferenceId="DefaultWeb" />
    </UserJourney>
       ...
  </UserJourneys>

مثال على ExchangesExchange Exchange
ClaimsExchanges .

    <ClaimsProviderSelections>
      <ClaimsProviderSelection TargetClaimsExchangeId="FacebookExchange" />
      <ClaimsProviderSelection TargetClaimsExchangeId="GoogleExchange" />
      <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
    </ClaimsProviderSelections>
    <ClaimsExchanges>
      <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
    </ClaimsExchanges>
  


المهام النموذجية


نتيجة لما سبق ، سيكون من الأسهل عليك فهم الدروس أدناه.


SignUpOrSignin.XML ، ProfileEdit.XML ، PasswordReset.XML


هذه هي الملفات النهائية حيث يمكنك الكتابة فوق \ add BuildingBlocks وحيث نشير إلى البيانات المراد إضافتها إلى الرمز المميز.

  <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TrustFrameworkPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns="http://schemas.microsoft.com/online/cpim/schemas/2013/06" PolicySchemaVersion="0.3.0.0" TenantId="antekesd.onmicrosoft.com" PolicyId="B2C_1A_signup_signin" PublicPolicyUri="http://antekesd.onmicrosoft.com/B2C_1A_signup_signin">

  <BasePolicy>
    <TenantId>antekesd.onmicrosoft.com</TenantId>
    <PolicyId>B2C_1A_TrustFrameworkExtensions</PolicyId>
  </BasePolicy>
  <BuildingBlocks>
    <ContentDefinitions>
      <ContentDefinition Id="api.signuporsignin"> <!--        -->
        <LoadUri>https://some.blob.core.windows.net/some/some.html</LoadUri>
        <RecoveryUri>~/common/default_page_error.html</RecoveryUri>
        <DataUri>urn:com:microsoft:aad:b2c:elements:contract:unifiedssp:1.2.0</DataUri>
      </ContentDefinition>
    </ContentDefinitions>
  </BuildingBlocks>
  <RelyingParty>
    <DefaultUserJourney ReferenceId="SignUpOrSignIn" /> <!--  ,     -->
    <TechnicalProfile Id="PolicyProfile">
      <DisplayName>PolicyProfile</DisplayName>
      <Protocol Name="OpenIdConnect" />
      <OutputClaims> <!--    JWT Token.        -->
        <OutputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="email"/>
        <OutputClaim ClaimTypeReferenceId="givenName" Required="true"/>
        <OutputClaim ClaimTypeReferenceId="surname" Required="true"/>
        <OutputClaim ClaimTypeReferenceId="email" />
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
        <OutputClaim ClaimTypeReferenceId="identityProvider" />
        <OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue="{Policy:TenantObjectId}" />
        <OutputClaim ClaimTypeReferenceId="picture" />
        <OutputClaim ClaimTypeReferenceId="country" Required="true"/>
      </OutputClaims>
      <SubjectNamingInfo ClaimType="sub" />
    </TechnicalProfile>
  </RelyingParty>
</TrustFrameworkPolicy>

اختبارات


لاختبار أحدث التغييرات التي تحتاجها:

  1. انتقل إلى إطار تجربة الهوية
  2. حدد السياسة التي تريد اختبارها.
  3. انقر فوق "تشغيل الآن"

صورة

استنتاج


ونتيجة لذلك ، ستتلقى نموذج تفويض يلبي تمامًا (أو تقريبًا) متطلبات عميلك / عميلك.

شكرا للانتباه!

All Articles