Verifiera användarindata med hjälp av en anpassad Azure Active Directory B2C-princip

Med anpassad princip för Azure Active Directory B2C (Azure AD B2C) kan du inte bara göra användarindata obligatoriska utan även verifiera dem. Du kan markera användarindata efter behov, till exempel <DisplayClaim ClaimTypeReferenceId="givenName" Required="true"/>, men det betyder inte att användarna kommer att ange giltiga data. Azure AD B2C tillhandahåller olika sätt att verifiera en användares indata. I den här artikeln får du lära dig hur du skriver en anpassad princip som samlar in användarindata och validerar dem med hjälp av följande metoder:

  • Begränsa de data som en användare anger genom att ange en lista med alternativ att välja mellan. Den här metoden använder uppräknade värden som du lägger till när du deklarerar ett anspråk.

  • Definiera ett mönster som en användarinmatning måste matcha. Den här metoden använder reguljära uttryck som du lägger till när du deklarerar ett anspråk.

  • Definiera en uppsättning regler och kräva att en användarinmatning följer en eller flera av reglerna. Den här metoden använder predikat som du lägger till när du deklarerar ett anspråk.

  • Använd den särskilda anspråkstypen reenterPassword för att verifiera att användaren har angett sitt lösenord på nytt under insamlingen av användarindata.

  • Konfigurera en teknisk valideringsprofil som definierar komplexa affärsregler som inte är möjliga att definiera på anspråksdeklarationsnivå. Du kan till exempel samla in en användarindata som måste verifieras mot ett värde eller ett angivet värde i ett annat anspråk.

Förutsättningar

Kommentar

Den här artikeln är en del av guideserien Skapa och köra egna anpassade principer i Azure Active Directory B2C. Vi rekommenderar att du startar den här serien från den första artikeln.

Steg 1 – Verifiera användarindata genom att begränsa alternativen för användarinmatning

Om du känner till alla möjliga värden som en användare kan ange för en viss indata kan du ange en begränsad uppsättning värden som en användare måste välja mellan. Du kan använda DropdownSinglSelect, CheckboxMultiSelect och RadioSingleSelectUserInputType för det här ändamålet. I den här artikeln använder du en RadioSingleSelect-indatatyp :

  1. Öppna filen ContosoCustomPolicy.XMLi VS Code.

  2. I -elementet ClaimsSchema i ContosoCustomPolicy.XML filen deklarerar du följande anspråkstyp:

        <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>
    

    Vi har deklarerat accountType-anspråk . När anspråkets värde samlas in från användaren måste användaren välja antingen Contoso Employee Account för ett värdearbete eller Ett personligt konto för ett personligt värde.

    Med Azure AD B2C kan du också anpassa din princip till olika språk och tillhandahåller kontotypsbegränsningar för flera språk. Mer information finns i artikeln Lokalisera användargränssnittet i artikeln Lägg till användarattribut.

  3. Leta upp den tekniska profilen med Id="UserInformationCollector"och lägg till accountType-anspråket som visningsanspråk med hjälp av följande kod:

        <DisplayClaim ClaimTypeReferenceId="accountType" Required="true"/>
    
  4. I den tekniska profilen med Id="UserInformationCollector"lägger du till accountType-anspråket som ett utdataanspråk med hjälp av följande kod:

        <OutputClaim ClaimTypeReferenceId="accountType"/>
    
  5. Om du vill inkludera kontotypsanspråket i åtkomsttoken letar du upp elementet RelyingParty och lägger till accountType-anspråket som ett tokenanspråk med hjälp av följande kod:

        <OutputClaim ClaimTypeReferenceId="accountType" />
    

Steg 2 – Verifiera användarindata med hjälp av reguljära uttryck

När det inte går att känna till alla möjliga användarindatavärden i förväg tillåter du användaren att själva mata in data. I det här fallet kan du använda reguljära uttryck (regex) eller mönster för att diktera hur en användarinmatning måste formateras. Ett e-postmeddelande måste till exempel ha symbolen at (@) och en punkt (.) någonstans i texten.

När du deklarerar ett anspråk kan du med en anpassad princip definiera en regex som användarens indata måste matcha. Du kan också ange ett meddelande som visas för användaren om deras indata inte matchar uttrycket.

  1. Leta upp elementet ClaimsSchema och deklarera e-postanspråket med hjälp av följande kod:

        <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. Leta upp den tekniska profilen med Id="UserInformationCollector"och lägg till e-postanspråket som visningsanspråk med hjälp av följande kod:

        <DisplayClaim ClaimTypeReferenceId="email" Required="true"/>
    
  3. I den tekniska profilen med Id="UserInformationCollector"lägger du till e-postanspråket som ett utdataanspråk med hjälp av följande kod:

        <OutputClaim ClaimTypeReferenceId="email"/>
    
  4. Leta upp elementet RelyingParty och lägg till e-postmeddelandet som ett tokenanspråk med hjälp av följande kod:

        <OutputClaim ClaimTypeReferenceId="email" />
    

Steg 3 – Verifiera användarindata med hjälp av predikat

Du har använt regex för att verifiera användarindata. Regex har dock en svaghet, d.v.s. felmeddelandet visas tills du korrigerar indata utan att visa det specifika kravet att indata saknas.

Med predikatvalidering kan du åtgärda det här problemet genom att låta dig definiera en uppsättning regler (predikater) och ett oberoende felmeddelande för varje regel. I anpassade principer har ett predikat en inbyggd metod som definierar de kontroller som du vill göra. Du kan till exempel använda metoden IsLengthRange-predikat för att kontrollera om ett användarlösenord ligger inom det intervall med minsta och högsta parametrar (värden) som angetts.

Medan predikaten definierar valideringen för att kontrollera mot en anspråkstyp, grupperar PredicateValidations en uppsättning predikat för att bilda en verifiering av användarindata som kan tillämpas på en anspråkstyp. Du kan till exempel skapa en predikatgrupp med validering som validerar olika typer av tillåtna tecken för ett lösenord. Elementen Predicates och PredicateValidations är underordnade element i BuildingBlocks avsnittet i principfilen.

  1. Leta upp elementet ClaimsSchema och deklarera lösenordsanspråket med hjälp av följande kod:

        <ClaimType Id="password">
          <DisplayName>Password</DisplayName>
          <DataType>string</DataType>
          <AdminHelpText>Enter password</AdminHelpText>
          <UserHelpText>Enter password</UserHelpText>
          <UserInputType>Password</UserInputType>
        </ClaimType>
    
  2. Lägg till ett Predicates element som underordnat BuildingBlocks avsnitt med hjälp av följande kod. Du lägger till elementet Predicates under elementet ClaimsSchema :

        <Predicates>
    
        </Predicates>
    
  3. I elementet Predicates definierar du predikat med hjälp av följande kod:

      <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>
    

    Vi har definierat flera regler, som när de sammanställs beskrev ett acceptabelt lösenord. Sedan kan du gruppera predikat för att skapa en uppsättning lösenordsprinciper som du kan använda i din princip.

  4. Lägg till ett PredicateValidations element som underordnat BuildingBlocks avsnitt med hjälp av följande kod. Du lägger till elementet som ett underordnat PredicateValidations BuildingBlocks avsnitt, men under elementet Predicates :

        <PredicateValidations>
    
        </PredicateValidations>
    
  5. I elementet PredicateValidations definierar du PredicateValidations med hjälp av följande kod:

        <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>
    

    Vi har tre definierade predikatvalidering, StrongPassword, CustomPassword och SimplePassword. Beroende på egenskaperna för det lösenord som du vill att användarna ska ange kan du använda valfritt på predikatvalideringarna. I den här artikeln använder vi ett starkt lösenord.

  6. Leta upp deklarationen för anspråkstyp för lösenord och lägg till StrongPassword Predicate Validation strax efter elementdeklarationen UserInputType som den innehåller med hjälp av följande kod:

        <PredicateValidationReference Id="StrongPassword" />
    
  7. Leta upp den tekniska profilen med Id="UserInformationCollector"och lägg till lösenordsanspråket som visningsanspråk med hjälp av följande kod:

        <DisplayClaim ClaimTypeReferenceId="password" Required="true"/>
    
  8. I den tekniska profilen med Id="UserInformationCollector"lägger du till lösenordsanspråket som ett utdataanspråk med hjälp av följande kod:

        <OutputClaim ClaimTypeReferenceId="password"/>
    

Kommentar

Av säkerhetsskäl lägger vi inte till en användares lösenord som ett anspråk i den token som genereras av din princip. Därför lägger vi inte till lösenordsanspråket i det förlitande partelementet.

Steg 4 – Verifiera lösenord och bekräfta lösenord

Du kan kräva att användarna anger sitt lösenord två gånger som ett sätt att bekräfta att användaren kommer ihåg lösenordet de anger. I det här fallet måste du kontrollera att värdena för de två posterna matchar. Anpassad princip är ett enkelt sätt att uppnå detta krav. Anspråkstyperna lösenord och reenterPassword anses vara speciella, så när de används för att samla in användarindata verifierar användargränssnittet att användaren har angett sitt lösenord på nytt.

Använd följande steg för att verifiera att lösenordet har angetts på nytt i din anpassade princip:

  1. I avsnittet ClaimsSchema i ContosoCustomPolicy.XML filen deklarerar du reenterPassword-anspråket strax efter lösenordsanspråket med hjälp av följande kod:

        <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. Om du vill samla in indata för lösenordsbekräftelse från användaren letar du upp den UserInformationCollector självsäkra tekniska profilen, lägger till reenterPassword-anspråk som ett visningsanspråk med hjälp av följande kod:

        <DisplayClaim ClaimTypeReferenceId="reenterPassword" Required="true"/>
    
  3. ContosoCustomPolicy.XML Leta upp den UserInformationCollector självsäkra tekniska profilen i filen och lägg till reenterPassword-anspråket som ett utdataanspråk med hjälp av följande kod:

        <OutputClaim ClaimTypeReferenceId="reenterPassword"/>
    

Steg 5 – Ladda upp anpassad principfil

Nu har du skapat din princip för att hantera de tre första metoderna för verifiering av användarindata.

Följ stegen i Ladda upp anpassad principfil. Om du laddar upp en fil med samma namn som den som redan finns i portalen kontrollerar du att du väljer Skriv över den anpassade principen om den redan finns.

Steg 6 – Testa den anpassade principen

  1. Under Anpassade principer väljer du B2C_1A_CONTOSOCUSTOMPOLICY.

  2. För Välj program på översiktssidan för den anpassade principen väljer du webbprogrammet, till exempel webapp1 som du tidigare registrerade. Kontrollera att värdet Välj svars-URL är inställt påhttps://jwt.ms.

  3. Välj knappen Kör nu .

  4. Ange förnamn och efternamn.

  5. Välj Kontotyp.

  6. För E-postadress anger du ett e-postvärde som inte är väl formaterat, till exempel maurice@contoso.

  7. För Lösenord anger du ett lösenordsvärde som inte följer alla egenskaper för ett starkt lösenord som angetts.

  8. Välj knappen Fortsätt . Du ser en skärm som liknar den som visas nedan:

    screenshot of validating user inputs.

    Du måste korrigera dina indata innan du fortsätter.

  9. Ange rätt värden enligt felmeddelandena och välj sedan Knappen Fortsätt igen. När principen har slutfört körningen omdirigeras du till https://jwt.msoch du ser en avkodad JWT-token. Token ser ut ungefär som följande JWT-tokenfragment:

    {
      "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]

Steg 7 – Verifiera användarindata med hjälp av tekniska verifieringsprofiler

De valideringstekniker som vi har använt i steg 1, steg 2 och steg 3 gäller inte för alla scenarier. Om dina affärsregler är komplexa för att definieras på anspråksdeklarationsnivå kan du konfigurera en teknisk validering och sedan anropa den från en självsäkrad teknisk profil.

Kommentar

Endast självsäkra tekniska profiler kan använda tekniska valideringsprofiler. Läs mer om teknisk valideringsprofil

Scenarioöversikt

Vi kräver att om användarens kontotyp är Contoso Employee Account måste vi se till att deras e-postdomän baseras på en uppsättning fördefinierade domäner. Dessa domäner är contoso.com, fabrikam.com och woodgrove.com. Annars visar vi ett fel för användaren tills de använder ett giltigt Contoso-anställdkonto eller byter till personligt konto.

Använd följande steg för att lära dig hur du verifierar användarindata med hjälp av tekniska verifieringsprofiler. Du använder en teknisk profil för validering av anspråkstransformeringstyp, men du kan även anropa en REST API-tjänst för att verifiera data som du lär dig senare i den här serien.

  1. I avsnittet ClaimsSchema i ContosoCustomPolicy.XML filen deklarerar du domän- och domainStatus-anspråk med hjälp av följande kod:

        <ClaimType Id="domain">
          <DataType>string</DataType>
        </ClaimType>
    
        <ClaimType Id="domainStatus">
          <DataType>string</DataType>
        </ClaimType>
    
  2. Leta upp avsnittet ClaimsTransformations och konfigurera anspråkstransformeringar med hjälp av följande kod:

        <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-anspråkstransformeringen extraherar en domän från e-post med parseDomain-metoden och lagrar den i domänanspråket. LookupDomain Claims Transformation använder den extraherade domänen för att kontrollera om den är giltig genom att leta upp den i de fördefinierade domänerna och tilldela giltig till domainStatus-anspråket.

  3. Använd följande kod för att lägga till en teknisk profil i samma anspråksprovider som den tekniska profilen med 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>
    

    Vi har deklarerat teknisk profil för anspråksomvandling som kör anspråksomvandlingarna GetDomainFromEmail och LookupDomain .

  4. Leta upp den tekniska profilen med Id=UserInformationCollectoroch ett ValidationTechnicalProfile strax efter -elementet OutputClaims med hjälp av följande kod:

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

    Vi har lagt till en teknisk valideringsprofil i den självsäkra tekniska profilen UserInformationCollector . Den tekniska profilen hoppas bara över om värdet accountType inte är lika med arbete. Om den tekniska profilen körs och e-postdomänen inte är giltig utlöses ett fel.

  5. Leta upp den tekniska profilen med Id=UserInformationCollectoroch lägg till följande kod i taggen metadata .

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

    Vi har konfigurerat ett anpassat fel om användaren inte använder ett giltigt e-postmeddelande.

  6. Följ anvisningarna i Ladda upp en anpassad principfil för att ladda upp principfilen.

  7. Följ anvisningarna i steg 6 för att testa din anpassade princip:

    1. För Kontotyp väljer du Contoso-anställdkonto
    2. För E-postadress anger du en ogiltig e-postadress, till exempel maurice@fourthcoffee.com.
    3. Ange resten av informationen efter behov och välj Fortsätt

    Eftersom maurice@fourthcoffee.com det inte är ett giltigt e-postmeddelande visas ett fel som liknar det som visas i skärmbilden nedan. Du måste använda en giltig e-postadress för att kunna köra den anpassade principen och ta emot en JWT-token.

    screenshot of error due to invalid email address.

Nästa steg