Prefácio
Continuação do ciclo de trabalho com o Azure B2C. Neste artigo, falarei sobre o ponto mais difícil e não óbvio, a saber, o Identity Experience Framework.O objetivo principal é montar uma imagem para aqueles que não estão no assunto e ajudar a configurar alguns recursos básicos.Links para posts relacionadosConfiguração básica
Antes de iniciar a configuração básica, gostaria de dizer como ocorre o processo de carregamento de novas regras:- Vá para o Identity Experience Framework
- Clique em enviar política do usuário
- Selecione um arquivo (não se esqueça de clicar em "Substituir política personalizada, se ela já existir")
- Nós enviamos
De fato, nada mudou desde a última vez, MAS:Se você alterar o arquivo TrustFrameworkExtension.xml ou TrustFrameworkBase.xml - faça o download periódico do arquivo que se refere a eles.
Às vezes, quando você faz alterações em um desses arquivos, você testa, acontece que suas alterações não aparecem. Isso se deve ao fato de
você ter alterado algo no arquivo base para que durante a verificação o arquivo filho resulte em erro.
No último artigo, decidimos que adicionamos os seguintes arquivos:a.TrustFrameworkBase.xml
b.TrustFrameworkExtensions.xml
c.SignUpOrSignin. XML
d.ProfileEdit. XML
e.PasswordReset. XML
Agora eu gostaria de contar em detalhes sobre cada um deles.TrustFrameworkBase.xmlEste arquivo contém a configuração básica. De fato, é a base do básico, mas nos tutoriais eles costumam dizer "É melhor não tocar neste arquivo". Isso é parcialmente verdade, mas há alguns pontos que não são discutidos:- Qualquer tutorial que diz para fazer alterações no TrustFrameworkExtensions.xml basicamente reescreve as regras do TrustFrameworkBase.xml
- Há situações em que é mais conveniente alterar algo no TrustFrameworkBase.xml .
- Se você encontrar em outros arquivos um link para um objeto que não esteja nesses arquivos, ele estará 100% no TrustFrameworkBase.xml e poderá abri-lo e ver
De acordo com minha experiência, alterei apenas duas coisas neste arquivo (localização e excluí um campo).TrustFrameworkExtension.xmlCom esse arquivo, você passa muito tempo juntos. De fato, este é o arquivo principal para suas configurações. Ele é constantemente mencionado em tutoriais.SignUpOrSignin. XML, ProfileEdit. XML, PasswordReset. XMLEsses arquivos são páginas de folha. Você provavelmente deseja adicionar o seu. Eles terão a menor quantidade de alteração.Agora vamos falar sobre a estrutura do arquivo. Todos os arquivos têm uma estrutura semelhante, por isso vou descrevê-lo com base no arquivo TrustFrameworkExtension.xml .O arquivo é dividido em vários blocos principais<TrustFrameworkPolicy>
<BasePolicy>
<TenantId>customtenant.onmicrosoft.com</TenantId>
<PolicyId>B2C_1A_TrustFrameworkBase</PolicyId>
</BasePolicy>
<BuildingBlocks>
</BuildingBlocks>
<ClaimsProviders>
</ClaimsProviders>
<UserJourneys>
</UserJourneys>
</TrustFrameworkPolicy>
Agora, sobre cada bloco separadamente.Blocos de construção
Neste bloco, adicionamos "ferramentas" que podemos usar em trabalhos futuros.ClaimsSchemaelemento ClaimsSchema determina os tipos de declarações, que podem ser referenciados dentro da política. <BuildingBlocks>
<ClaimsSchema>
<ClaimType Id="picture">
<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>
PredicadosPredicados e elementos de validação de predicado permitem a validação para garantir que apenas dados formados corretamente sejam inseridos no cliente do Azure Active Directory B2C (Azure AD B2C). <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>
PredicateValidationsEnquanto os predicados determinam se um tipo de asserção é validado, PredicateValidations agrupa um conjunto de predicados para formar uma verificação de entrada do usuário que corresponda ao tipo de asserção. <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>
ClaimsTransformationselemento ClaimsTransformations contém uma lista de funções afirmações de transformação que podem ser usados na forma de interação do usuário, como parte de uma política personalizada. <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" />
<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>
Definições de conteúdoPermite definir modelos para cada uma das suas páginas. <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>
DisplayControlsO controle Display é um elemento da interface do usuário que possui recursos especiais e interage com o serviço do servidor 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>
ClaimProviders
Neste bloco, criaremos as próprias páginas, ou melhor, o seu conteúdo. Aqui, indicaremos o que a página possui dados de entrada e saída.ClaimsProvider vincula perfis técnicos ao provedor de declarações. <ClaimsProviders>
<ClaimsProvider>
<DisplayName>Self Asserted</DisplayName>
O elemento TechnicalProfiles contém um conjunto de perfis técnicos suportados pelo provedor de declarações. <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>
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="newUser" />
<OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
<OutputClaim ClaimTypeReferenceId="givenName" Required="true"/>
<OutputClaim ClaimTypeReferenceId="surname" Required="true"/>
<OutputClaim ClaimTypeReferenceId="country" Required="true"/>
</OutputClaims>
</TechnicalProfile>
</ClaimsProvider>
Exemplo de adição de provedores de identidade do 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>
<Domain>facebook.com</Domain>
<DisplayName>Facebook</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="Facebook-OAUTH">
<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>
<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>
Viagens do usuário
As jornadas do usuário do usuário indicam caminhos explícitos pelos quais a política permite que o aplicativo baseado em declarações forneça ao usuário as reivindicações necessárias.Abaixo, adicionei algumas coisas simples, o resto é fácil de encontrar nos tutoriais que adicionarei abaixo. <UserJourneys>
<UserJourney Id="SignUp">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="ClaimsExchange" ContentDefinitionReferenceId="api.localaccountsignup">
<ClaimsExchanges>
<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>
Exemplo de Troca de Declarações de TrocaClaimsExchanges .
<ClaimsProviderSelections>
<ClaimsProviderSelection TargetClaimsExchangeId="FacebookExchange" />
<ClaimsProviderSelection TargetClaimsExchangeId="GoogleExchange" />
<ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
</ClaimsProviderSelections>
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</ClaimsExchanges>
Tarefas típicas
Como resultado do exposto, será mais fácil para você entender os tutoriais abaixo.SignUpOrSignin.XML, ProfileEdit.XML, PasswordReset.XML
Esses são os arquivos finais nos quais você pode sobrescrever \ add BuildingBlocks e onde indicamos quais dados adicionar ao token. <?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>
<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>
Teste
Para testar as alterações mais recentes, você precisa:- Vá para o Identity Experience Framework
- Selecione a política que você deseja testar.
- Clique em "Executar agora"

Conclusão
Como resultado, você receberá um formulário de autorização que atende totalmente (ou quase) aos requisitos do seu / cliente.Obrigado pela atenção!