次の方法で共有


Azure Active Directory B2C カスタム ポリシーを使用してユーザー入力を検証する

重要

2025 年 5 月 1 日より、Azure AD B2C は新規のお客様向けに購入できなくなります。 詳細については、FAQ を参照してください

Azure Active Directory B2C (Azure AD B2C) カスタム ポリシーを使用すると、ユーザー入力を必須にするだけでなく、それらを検証することもできます。 など、ユーザー入力を<DisplayClaim ClaimTypeReferenceId="givenName" Required="true"/>に応じてマークできますが、ユーザーが有効なデータを入力するわけではありません。 Azure AD B2C には、ユーザー入力を検証するためのさまざまな方法が用意されています。 この記事では、次の方法を使用して、ユーザー入力を収集して検証するカスタム ポリシーを記述する方法について説明します。

  • 選択するオプションの一覧を指定して、ユーザーが入力するデータを制限します。 この方法ではクレームを宣言するときに追加する列挙値を使用します。

  • ユーザー入力が一致する必要があるパターンを定義します。 この方法では、要求を宣言するときに追加する正規表現を使用します。

  • 一連のルールを定義し、ユーザー入力が 1 つ以上の規則に従うように要求します。 このアプローチでは、要求を宣言するときに追加する述語を使用します。

  • ユーザー入力の収集中にユーザーがパスワードを正しく再入力したことを検証するには、特殊な要求の種類 reenterPassword を使用します。

  • 要求宣言レベルでは定義できない複雑なビジネス ルールを定義する 検証技術プロファイル を構成します。 たとえば、ユーザー入力を収集します。これは、別の要求の値または設定値に対して検証する必要があります。

前提条件

この記事は、 Azure Active Directory B2C での独自のカスタム ポリシーの作成と実行に関するハウツー ガイド シリーズの一部です。 最初の記事からこのシリーズを開始することをお勧めします。

手順 1 - ユーザー入力オプションを制限してユーザー入力を検証する

特定の入力に対してユーザーが入力できるすべての可能な値がわかっている場合は、ユーザーが選択する必要がある有限の値セットを指定できます。 この目的には 、DropdownSingleSelectCheckboxMultiSelectRadioSingleSelectUserInputType を使用できます。 この記事では、 RadioSingleSelect 入力の種類を使用します。

  1. VS Code で、ファイル ContosoCustomPolicy.XMLを開きます。

  2. ClaimsSchema ファイルのContosoCustomPolicy.XML要素で、次の要求の種類を宣言します。

        <ClaimType Id="accountType">
            <DisplayName>Account Type</DisplayName>
            <DataType>string</DataType>
            <UserHelpText>The type of account used by the user</UserHelpText>
            <UserInputType>RadioSingleSelect</UserInputType>
            <Restriction>
                <Enumeration Text="Contoso Employee Account" Value="work" SelectByDefault="true"/>
                <Enumeration Text="Personal Account" Value="personal" SelectByDefault="false"/>
            </Restriction>
        </ClaimType>
    

    accountType 要求を宣言しました。 クレームの値がユーザーから収集されると、使用者は、仕事用の値にContoso 従業員アカウントを選択するか、個人用の値に個人用アカウントを選択する必要があります。

    Azure AD B2C では、ポリシーをさまざまな言語に対応させ、複数の言語のアカウントの種類の制限を提供することもできます。 詳細については、ユーザー属性の追加に関する記事 の UI のローカライズ関する記事を参照してください

  3. Id="UserInformationCollector"を使用して技術プロファイルを見つけ、次のコードを使用して accountType 要求を表示要求として追加します。

        <DisplayClaim ClaimTypeReferenceId="accountType" Required="true"/>
    
  4. Id="UserInformationCollector"の技術プロファイルで、次のコードを使用して accountType 要求を出力要求として追加します。

        <OutputClaim ClaimTypeReferenceId="accountType"/>
    
  5. アクセス トークンにアカウントの種類の要求を含めるには、 RelyingParty 要素を見つけ、次のコードを使用して accountType 要求をトークン要求として追加します。

        <OutputClaim ClaimTypeReferenceId="accountType" />
    

手順 2 - 正規表現を使用してユーザー入力を検証する

すべてのユーザー入力値を事前に把握できない場合は、ユーザーが自分でデータを入力できます。 この場合、 正規表現 (正規表現) または パターン を使用して、ユーザー入力の書式設定方法を指定できます。 たとえば、メールのテキストのどこかに at (@) 記号と ピリオド (.) が含まれている必要があります。

要求を宣言すると、カスタム ポリシーを使用して、ユーザー入力が一致する必要がある正規表現を定義できます。 必要に応じて、入力が式と一致しない場合にユーザーに表示されるメッセージを指定できます。

  1. ClaimsSchema要素を見つけ、次のコードを使用して電子メール要求を宣言します。

        <ClaimType Id="email">
            <DisplayName>Email Address</DisplayName>
            <DataType>string</DataType>
            <DefaultPartnerClaimTypes>
                <Protocol Name="OpenIdConnect" PartnerClaimType="email"/>
            </DefaultPartnerClaimTypes>
            <UserHelpText>Your email address. </UserHelpText>
            <UserInputType>TextBox</UserInputType>
            <Restriction>
                <Pattern RegularExpression="^[a-zA-Z0-9.!#$%&amp;&apos;^_`{}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" HelpText="Please enter a valid email address something like maurice@contoso.com"/>
            </Restriction>
        </ClaimType>
    
  2. Id="UserInformationCollector"を使用して技術プロファイルを見つけ、次のコードを使用して、表示要求として電子メール要求を追加します。

        <DisplayClaim ClaimTypeReferenceId="email" Required="true"/>
    
  3. Id="UserInformationCollector"の技術プロファイルで、次のコードを使用して、電子メール要求を出力要求として追加します。

        <OutputClaim ClaimTypeReferenceId="email"/>
    
  4. RelyingParty要素を見つけ、次のコードを使用して、トークン要求として電子メールを追加します。

        <OutputClaim ClaimTypeReferenceId="email" />
    

手順 3 - 述語を使用してユーザー入力を検証する

正規表現を使用してユーザー入力を検証しました。 ただし、正規表現には 1 つの弱点があります。つまり、入力が不足している特定の要件を示さずに入力を修正するまで、エラー メッセージが表示されます。

述語の検証を使用すると、ルールのセット (述語) とルールごとに独立したエラー メッセージを定義できるため、この問題に対処できます。 カスタム ポリシーでは、述語には組み込みのメソッドがあり、それがあなたがチェックしたいことを定義しています。 たとえば、 IsLengthRange 述語メソッドを使用して、ユーザー パスワード が指定された最小パラメーターと最大パラメーター (値) の範囲内にあるかどうかを確認できます。

述語では、要求の種類に対してチェックする検証を定義しますが、PredicateValidations は、要求の種類に適用できるユーザー入力の検証を形成する述語のセットをグループ化します。 たとえば、パスワードに使用できるさまざまな種類の文字を検証する検証の述語グループを作成します。 Predicates 要素と PredicateValidations 要素はどちらも、ポリシー ファイルのBuildingBlocksセクションの子要素です。

  1. ClaimsSchema要素を見つけ、次のコードを使用してパスワード要求を宣言します。

        <ClaimType Id="password">
          <DisplayName>Password</DisplayName>
          <DataType>string</DataType>
          <AdminHelpText>Enter password</AdminHelpText>
          <UserHelpText>Enter password</UserHelpText>
          <UserInputType>Password</UserInputType>
        </ClaimType>
    
  2. 次のコードを使用して、 Predicates 要素 BuildingBlocks セクションの子として追加します。 Predicates要素の下にClaimsSchema要素を追加します。

        <Predicates>
    
        </Predicates>
    
  3. Predicates要素内で、次のコードを使用して述語を定義します。

      <Predicate Id="IsLengthBetween8And64" Method="IsLengthRange" HelpText="The password must be between 8 and 64 characters.">
        <Parameters>
          <Parameter Id="Minimum">8</Parameter>
          <Parameter Id="Maximum">64</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Lowercase" Method="IncludesCharacters" HelpText="a lowercase letter">
        <Parameters>
          <Parameter Id="CharacterSet">a-z</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Uppercase" Method="IncludesCharacters" HelpText="an uppercase letter">
        <Parameters>
          <Parameter Id="CharacterSet">A-Z</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Number" Method="IncludesCharacters" HelpText="a digit">
        <Parameters>
          <Parameter Id="CharacterSet">0-9</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="Symbol" Method="IncludesCharacters" HelpText="a symbol">
        <Parameters>
          <Parameter Id="CharacterSet">@#$%^&amp;*\-_+=[]{}|\\:',.?/`~"();!</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="PIN" Method="MatchesRegex" HelpText="The password must be numbers only.">
        <Parameters>
          <Parameter Id="RegularExpression">^[0-9]+$</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="AllowedCharacters" Method="MatchesRegex" HelpText="An invalid character was provided.">
        <Parameters>
          <Parameter Id="RegularExpression">(^([0-9A-Za-z\d@#$%^&amp;*\-_+=[\]{}|\\:',?/`~"();! ]|(\.(?!@)))+$)|(^$)</Parameter>
        </Parameters>
      </Predicate>
    
      <Predicate Id="DisallowedWhitespace" Method="MatchesRegex" HelpText="The password must not begin or end with a whitespace character.">
        <Parameters>
          <Parameter Id="RegularExpression">(^\S.*\S$)|(^\S+$)|(^$)</Parameter>
        </Parameters>
      </Predicate>
    

    いくつかのルールを定義しました。これをまとめると、許容できるパスワードが記述されています。 次に、述語をグループ化して、ポリシーで使用できる一連のパスワード ポリシーを形成できます。

  4. 次のコードを使用して、 PredicateValidations 要素 BuildingBlocks セクションの子として追加します。 PredicateValidations要素は、BuildingBlocks セクションの子として追加しますが、Predicates要素の下に追加します。

        <PredicateValidations>
    
        </PredicateValidations>
    
  5. PredicateValidations要素内で、次のコードを使用して PredicateValidations を定義します。

        <PredicateValidation Id="SimplePassword">
            <PredicateGroups>
                <PredicateGroup Id="DisallowedWhitespaceGroup">
                    <PredicateReferences>
                        <PredicateReference Id="DisallowedWhitespace"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="AllowedCharactersGroup">
                    <PredicateReferences>
                        <PredicateReference Id="AllowedCharacters"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="LengthGroup">
                    <PredicateReferences>
                        <PredicateReference Id="IsLengthBetween8And64"/>
                    </PredicateReferences>
                </PredicateGroup>
            </PredicateGroups>
        </PredicateValidation>
        <PredicateValidation Id="StrongPassword">
            <PredicateGroups>
                <PredicateGroup Id="DisallowedWhitespaceGroup">
                    <PredicateReferences>
                        <PredicateReference Id="DisallowedWhitespace"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="AllowedCharactersGroup">
                    <PredicateReferences>
                        <PredicateReference Id="AllowedCharacters"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="LengthGroup">
                    <PredicateReferences>
                        <PredicateReference Id="IsLengthBetween8And64"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="CharacterClasses">
                    <UserHelpText>The password must have at least 3 of the following:</UserHelpText>
                    <PredicateReferences MatchAtLeast="3">
                        <PredicateReference Id="Lowercase"/>
                        <PredicateReference Id="Uppercase"/>
                        <PredicateReference Id="Number"/>
                        <PredicateReference Id="Symbol"/>
                    </PredicateReferences>
                </PredicateGroup>
            </PredicateGroups>
        </PredicateValidation>
        <PredicateValidation Id="CustomPassword">
            <PredicateGroups>
                <PredicateGroup Id="DisallowedWhitespaceGroup">
                    <PredicateReferences>
                        <PredicateReference Id="DisallowedWhitespace"/>
                    </PredicateReferences>
                </PredicateGroup>
                <PredicateGroup Id="AllowedCharactersGroup">
                    <PredicateReferences>
                        <PredicateReference Id="AllowedCharacters"/>
                    </PredicateReferences>
                </PredicateGroup>
            </PredicateGroups>
        </PredicateValidation>
    

    3 つの述語検証 (StrongPassword、CustomPasswordSimplePassword) が定義されています。 ユーザーが入力するパスワードの特性に応じて、[述語の検証] で任意の値を使用できます。 この記事では、強力なパスワードを使用します。

  6. パスワード要求の種類の宣言を見つけ、次のコードを使用して、含まれている UserInputType 要素宣言の直後に StrongPassword 述語検証を追加します。

        <PredicateValidationReference Id="StrongPassword" />
    
  7. Id="UserInformationCollector"を使用して技術プロファイルを見つけ、次のコードを使用して、表示要求としてパスワード要求を追加します。

        <DisplayClaim ClaimTypeReferenceId="password" Required="true"/>
    
  8. Id="UserInformationCollector"の技術プロファイルで、次のコードを使用して、出力要求としてパスワード要求を追加します。

        <OutputClaim ClaimTypeReferenceId="password"/>
    

セキュリティ上の理由から、ポリシーによって生成されたトークンには、ユーザーのパスワードを要求として追加しません。 そのため、証明書利用者要素にはパスワード要求を追加しません。

手順 4 - パスワードを検証し、パスワードを確認する

ユーザーが入力したパスワードを覚えているか確認する手段として、ユーザーにパスワードの入力を 2 回要求できます。 この場合、2 つのエントリの値が一致することを確認する必要があります。 カスタム ポリシーを使用すると、この要件を簡単に実現できます。 要求の種類 のパスワードreenterPassword は特別と見なされるため、ユーザー入力の収集に使用すると、UI はユーザーが自分のパスワードを正しく再入力したことを検証します。

カスタム ポリシーでパスワードを再入力することを検証するには、次の手順に従います。

  1. ClaimsSchema ファイルの ContosoCustomPolicy.XML セクションで、次のコードを使用して、パスワード要求の直後に reenterPassword 要求を宣言します。

        <ClaimType Id="reenterPassword">
            <DisplayName>Confirm new password</DisplayName>
            <DataType>string</DataType>
            <AdminHelpText>Confirm new password</AdminHelpText>
            <UserHelpText>Reenter password</UserHelpText>
            <UserInputType>Password</UserInputType>
        </ClaimType>    
    
  2. ユーザーからパスワード確認入力を収集するには、セルフアサート技術プロファイル UserInformationCollector を見つけ、次のコードを使用して 、表示要求として reenterPassword 要求を追加します。

        <DisplayClaim ClaimTypeReferenceId="reenterPassword" Required="true"/>
    
  3. ContosoCustomPolicy.XML ファイルで、UserInformationCollectorセルフ アサート技術プロファイルを見つけ、次のコードを使用して出力要求として reenterPassword 要求を追加します。

        <OutputClaim ClaimTypeReferenceId="reenterPassword"/>
    

手順 5 - カスタム ポリシー ファイルをアップロードする

この時点で、ユーザー入力の検証に対する最初の 3 つのアプローチに対処するポリシーを構築しました。

「カスタム ポリシー ファイルのアップロード」の手順に従います。 ポータルに既に存在するファイルと同じ名前のファイルをアップロードする場合は、[ カスタム ポリシーが既に存在する場合は上書きする] を選択してください。

手順 6 - カスタム ポリシーをテストする

  1. [ カスタム ポリシー] で、[ B2C_1A_CONTOSOCUSTOMPOLICY] を選択します。

  2. カスタム ポリシーの概要ページの [ アプリケーションの選択 ] で、以前に登録した Webapp1 などの Web アプリケーションを選択します。 [ 応答 URL の選択 ] の値が [https://jwt.ms] に設定されていることを確認します。

  3. [ 今すぐ実行 ] ボタンを選択します。

  4. [指定された名前] と [姓] を入力します

  5. [ アカウントの種類] を選択します

  6. [ 電子メール アドレス] に、maurice@contosoなど、適切な形式ではないメール値を入力 します

  7. [ パスワード] には、設定されている強力なパスワードのすべての特性に従わないパスワード値を入力します。

  8. [続行] ボタンを選択します。 次のような画面が表示されます。

    ユーザー入力の検証のスクリーンショット。

    続行する前に、入力を修正する必要があります。

  9. エラー メッセージで推奨される正しい値を入力し、もう一度 [続行 ] ボタンを選択します。 ポリシーの実行が完了すると、 https://jwt.msにリダイレクトされ、デコードされた JWT が表示されます。 トークンは、次の JWT スニペットのようになります。

    {
      "typ": "JWT",
      "alg": "RS256",
      "kid": "pxLOMWFg...."
    }.{
      ...
      "sub": "c7ae4515-f7a7....",
      ...
      "acr": "b2c_1a_contosocustompolicy",
      "accountType": "work",
      ...
      "email": "maurice@contoso.com",
      "name": "Maurice Paulet",
      "message": "Hello Maurice Paulet"
    }.[Signature]

手順 7 - 検証技術プロファイルを使用してユーザー入力を検証する

手順 1、手順 2、手順 3 で使用した検証手法は、すべてのシナリオに適用できるわけではありません。 ビジネス ルールが複雑すぎて要求宣言レベルで定義できない場合は、 検証技術を構成し、 Self-Asserted 技術プロファイルから呼び出すことができます。

検証技術プロファイルを使用できるのは、セルフアサート技術プロファイルのみです。 検証技術プロファイルの詳細

シナリオの概要

ユーザーの アカウントの種類Contoso Employee Account の場合は、電子メール ドメインが一連の定義済みドメインに基づいていることを確認する必要があります。 これらのドメインは 、contoso.com、fabrikam.comおよび woodgrove.com です。 それ以外の場合は、有効な Contoso 従業員アカウント を使用するか 、個人アカウントに切り替えるまで、ユーザーにエラーが表示されます。

検証技術プロファイルを使用してユーザー入力を検証する方法については、次の手順に従います。 要求変換の種類の検証技術プロファイルを使用しますが、REST API サービスを呼び出してデータを検証することもできます。これについては、このシリーズの後半で説明します。

  1. ClaimsSchema ファイルの ContosoCustomPolicy.XML セクションで、次のコードを使用して ___domaindomainStatus 要求を宣言します。

        <ClaimType Id="___domain">
          <DataType>string</DataType>
        </ClaimType>
    
        <ClaimType Id="domainStatus">
          <DataType>string</DataType>
        </ClaimType>
    
  2. ClaimsTransformations セクションを見つけ、次のコードを使用して要求変換を構成します。

        <ClaimsTransformation Id="GetDomainFromEmail" TransformationMethod="ParseDomain">
            <InputClaims>
                <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="emailAddress"/>
            </InputClaims>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="___domain" TransformationClaimType="___domain"/>
            </OutputClaims>
        </ClaimsTransformation>
        <ClaimsTransformation Id="LookupDomain" TransformationMethod="LookupValue">
            <InputClaims>
                <InputClaim ClaimTypeReferenceId="___domain" TransformationClaimType="inputParameterId"/>
            </InputClaims>
            <InputParameters>
                <InputParameter Id="contoso.com" DataType="string" Value="valid"/>
                <InputParameter Id="fabrikam.com" DataType="string" Value="valid"/>
                <InputParameter Id="woodgrove.com" DataType="string" Value="valid"/>
                <InputParameter Id="errorOnFailedLookup" DataType="boolean" Value="true"/>
            </InputParameters>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="domainStatus" TransformationClaimType="outputClaim"/>
            </OutputClaims>
        </ClaimsTransformation>
    

    GetDomainFromEmail 要求変換は、ParseDomain メソッドを使用して電子メールからドメインを抽出し、ドメイン要求に格納します。 LookupDomain 要求変換では、抽出されたドメインを使用して、定義済みのドメインで参照し、domainStatus 要求に有効なドメインを割り当てることによって、有効かどうかを確認します。

  3. 次のコードを使用して、 Id=UserInformationCollectorの技術プロファイルと同じクレーム プロバイダーに技術プロファイルを追加します。

        <TechnicalProfile Id="CheckCompanyDomain">
            <DisplayName>Check Company validity </DisplayName>
            <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
            <InputClaimsTransformations>
                <InputClaimsTransformation ReferenceId="GetDomainFromEmail"/>
            </InputClaimsTransformations>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="___domain"/>
            </OutputClaims>
            <OutputClaimsTransformations>
                <OutputClaimsTransformation ReferenceId="LookupDomain"/>
            </OutputClaimsTransformations>
        </TechnicalProfile>
    

    GetDomainFromEmail および LookupDomain 要求変換を実行する要求変換技術プロファイルを宣言しました。

  4. 次のコードを使用して、Id=UserInformationCollector要素の直後にValidationTechnicalProfileOutputClaimsを含む技術プロファイルを見つけます。

        <ValidationTechnicalProfiles>
            <ValidationTechnicalProfile ReferenceId="CheckCompanyDomain">
                <Preconditions>
                    <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
                        <Value>accountType</Value>
                        <Value>work</Value>
                        <Action>SkipThisValidationTechnicalProfile</Action>
                    </Precondition>
                </Preconditions>
            </ValidationTechnicalProfile>
        </ValidationTechnicalProfiles>
    

    UserInformationCollector セルフアサート技術プロファイルに検証技術プロファイルが追加されました。 技術プロファイルは、accountType 値が 仕事に等しくない場合のみスキップされます。 技術プロファイルが実行され、電子メールドメインが有効でない場合は、エラーが発生します。

  5. Id=UserInformationCollectorを使用して技術プロファイルを見つけ、metadata タグ内に次のコードを追加します。

        <Item Key="LookupNotFound">The provided email address isn't a valid Contoso Employee email.</Item>
    

    ユーザーが有効な電子メールを使用しない場合に備えて、カスタム エラーを設定しました。

  6. カスタム ポリシー ファイルのアップロード 」の手順に従って、ポリシー ファイルをアップロードします。

  7. 手順 6 の手順に従って、カスタム ポリシーをテストします。

    1. [アカウントの種類] で、[Contoso Employee Account]\(Contoso 従業員アカウント\) を選択します
    2. [ 電子メール アドレス] に、 maurice@fourthcoffee.comなどの無効な電子メール アドレスを入力します。
    3. 必要に応じて残りの詳細を入力し、[続行] を選択します

    maurice@fourthcoffee.comは有効な電子メールではないので、次のスクリーンショットに示すようなエラーが表示されます。 有効な電子メール アドレスを使用して、カスタム ポリシーを正常に実行し、JWT を受信する必要があります。

    無効なメール アドレスによるエラーのスクリーンショット。