【问题标题】:ADB2C Custom policy for sending email through sendgrid通过 sendgrid 发送电子邮件的 ADB2C 自定义策略
【发布时间】:2021-03-15 15:36:02
【问题描述】:

除了可选步骤外,我已遵循以下所有步骤: https://docs.microsoft.com/en-us/azure/active-directory-b2c/custom-email-sendgrid

单击“发送验证码”按钮时,我不断收到以下错误 -

为“SendOtp”指定的基本凭据无效。检查凭据是否正确以及资源是否已授予访问权限。

sendgrid 帐户配置正确,我可以通过 Postman 发送电子邮件。邮递员请求,使用我在 Azure 策略密钥中设置的相同 sendgrid api 密钥

{
  "personalizations": [
    {
      "to": [
        {
          "email": "abc@abc.com",
          "name": "abc abc"
        }
      ],
      "dynamic_template_data": {
        "otp": "123456",
        "subject": "account email verification code",
      },
    }
  ],
  "from": {
    "email": "noreply@johndoe.com",
    "name": "John Doe"
  },
  "reply_to": {
    "email": "noreply@johndoe.com",
    "name": "John Doe"
  },
  "template_id": "d-xxxxxxxxxxxxxxxxxxxxxxxx"
}

这些是我添加的上述链接中的块

      <!--Step 1 SendGrid Email-->
       <ClaimType Id="Otp">
      <DisplayName>Secondary One-time password</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="emailRequestBody">
      <DisplayName>SendGrid request body</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="VerificationCode">
      <DisplayName>Secondary Verification Code</DisplayName>
      <DataType>string</DataType>
      <UserHelpText>Enter your email verification code</UserHelpText>
      <UserInputType>TextBox</UserInputType>
    </ClaimType>
    <!--Step 1-->
    <!--Step 2 SendGrid Email To be worked on -->
    <ClaimsTransformation Id="GenerateEmailRequestBody" 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>
        <!-- Update the template_id value with the ID of your SendGrid template. -->
        <InputParameter Id="template_id" DataType="string" Value="d-xxxxxxxxxxxxxxxxxxxxxxxxxx"/>
        <InputParameter Id="from.email" DataType="string" Value="my_email@mydomain.com"/>
        <!-- Update with a subject line appropriate for your organization. -->
        <InputParameter Id="personalizations.0.dynamic_template_data.subject" DataType="string" Value="account email verification code"/>
      </InputParameters>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="emailRequestBody" TransformationClaimType="outputClaim"/>
      </OutputClaims>
    </ClaimsTransformation>
    <!--Step 2-->
      <!--Step 3 SendGrid Email-->
         <ContentDefinition Id="api.localaccountsignup">
      <DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.0</DataUri>
    </ContentDefinition>
    <ContentDefinition Id="api.localaccountpasswordreset">
      <DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.0</DataUri>
    </ContentDefinition>
          <!--Step 3-->
    <!--Step 4 SendGrid Email-->
    <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="SendOtp" />
          </ValidationClaimsExchange>
        </Action>
        <Action Id="VerifyCode">
          <ValidationClaimsExchange>
            <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="VerifyOtp" />
          </ValidationClaimsExchange>
        </Action>
      </Actions>
    </DisplayControl>
    </DisplayControls>
    <!--Step 4-->
     <!--Step 5 SendGrid Email-->
      <ClaimsProvider>
    <DisplayName>One time password technical profiles</DisplayName>
    <TechnicalProfiles>
      <TechnicalProfile Id="GenerateOtp">
        <DisplayName>Generate one time password</DisplayName>
        <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.OneTimePasswordProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        <Metadata>
          <Item Key="Operation">GenerateCode</Item>
          <Item Key="CodeExpirationInSeconds">1200</Item>
          <Item Key="CodeLength">6</Item>
          <Item Key="CharacterSet">0-9</Item>
          <Item Key="ReuseSameCode">true</Item>
          <Item Key="NumRetryAttempts">5</Item>
        </Metadata>
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="identifier" />
        </InputClaims>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="otp" PartnerClaimType="otpGenerated" />
        </OutputClaims>
      </TechnicalProfile>

      <TechnicalProfile Id="VerifyOtp">
        <DisplayName>Verify one time password</DisplayName>
        <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.OneTimePasswordProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        <Metadata>
          <Item Key="Operation">VerifyCode</Item>
        </Metadata>
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="identifier" />
          <InputClaim ClaimTypeReferenceId="verificationCode" PartnerClaimType="otpToVerify" />
        </InputClaims>
      </TechnicalProfile>
     </TechnicalProfiles>
  </ClaimsProvider>
  <!--Step 5-->
  <!--Step 6 SendGrid Email-->
  <ClaimsProvider>
  <DisplayName>RestfulProvider</DisplayName>
  <TechnicalProfiles>
    <TechnicalProfile Id="SendOtp">
      <DisplayName>Use SendGrid's email API to send the code the the user</DisplayName>
      <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      <Metadata>
        <Item Key="ServiceUrl">https://api.sendgrid.com/v3/mail/send</Item>
        <Item Key="AuthenticationType">Bearer</Item>
        <Item Key="SendClaimsIn">Body</Item>
        <Item Key="ClaimUsedForRequestPayload">emailRequestBody</Item>
      </Metadata>
      <CryptographicKeys>
        <Key Id="BearerAuthenticationToken" StorageReferenceId="B2C_1A_SendGridSecret" />
      </CryptographicKeys>
      <InputClaimsTransformations>
        <InputClaimsTransformation ReferenceId="GenerateEmailRequestBody" />
      </InputClaimsTransformations>
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="emailRequestBody" />
      </InputClaims>
    </TechnicalProfile>
  </TechnicalProfiles>
</ClaimsProvider>
  <!--Step 6-->
  <!--Step 7 SendGrid Email-->
  <ClaimsProvider>
  <DisplayName>Local Account</DisplayName>
  <TechnicalProfiles>
    <TechnicalProfile Id="LocalAccountSignUpWithLogonEmail">
      <Metadata>
        <!--OTP validation error messages-->
        <Item Key="UserMessageIfSessionDoesNotExist">You have exceeded the maximum time allowed.</Item>
        <Item Key="UserMessageIfMaxRetryAttempted">You have exceeded the number of retries allowed.</Item>
        <Item Key="UserMessageIfInvalidCode">You have entered the wrong code.</Item>
        <Item Key="UserMessageIfSessionConflict">Cannot verify the code, please try again later.</Item>
      </Metadata>
      <DisplayClaims>
        <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
        <DisplayClaim ClaimTypeReferenceId="displayName" Required="true" />
        <DisplayClaim ClaimTypeReferenceId="givenName" Required="true" />
        <DisplayClaim ClaimTypeReferenceId="surName" Required="true" />
        <DisplayClaim ClaimTypeReferenceId="newPassword" Required="true" />
        <DisplayClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
      </DisplayClaims>
    </TechnicalProfile>
    <TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddress">
      <Metadata>
        <!--OTP validation error messages-->
        <Item Key="UserMessageIfSessionDoesNotExist">You have exceeded the maximum time allowed.</Item>
        <Item Key="UserMessageIfMaxRetryAttempted">You have exceeded the number of retries allowed.</Item>
        <Item Key="UserMessageIfInvalidCode">You have entered the wrong code.</Item>
        <Item Key="UserMessageIfSessionConflict">Cannot verify the code, please try again later.</Item>
      </Metadata>
      <DisplayClaims>
        <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
      </DisplayClaims>
    </TechnicalProfile>
  </TechnicalProfiles>
</ClaimsProvider>
  <!--Step 7-->

谁能帮我弄清楚如何调试这个问题。非常感谢。

【问题讨论】:

  • 您是否在 SendGrid 或 Bearer/API Key 上使用基本身份验证?sendgrid.com/docs/for-developers/sending-email/authentication。尝试在 POSTMan 中测试您的请求,或者使用上面的 SendGrid 链接以及您获得的凭据进行 curl。
  • @Jas Sendgrid 帐户是一个 API 密钥帐户。根据您提供的 sendgrid 文档链接,我创建了一个 API 密钥以用作承载/API 密钥并将其设置在 CustomPolicy - 它将 sendOtp 中的 Crypographic 密钥定义为 BearerAuthenticationToken,所以我假设策略会发送它作为标头中的不记名令牌。当我从 Postman 将该凭证作为不记名令牌发送时,它可以工作,并且我会收到在 sendgrid 模板中定义的电子邮件。
  • 一切看起来都不错,因此您可能希望在 sendgrid 生成一个新密钥并在 B2C 重新创建它。
  • Jas,新密钥也不起作用。尝试输入不正确的值以查看它是否会触发差异响应 - 不会。还将 StorageReferenceId 更改为 B2C_1A_SendGridApiKey,如示例 github.com/azure-ad-b2c/samples/blob/master/policies/… 中所示,而不是 docs.microsoft.com/en-us/azure/active-directory-b2c/… 中提到的 B2C_1A_SendGridSecret - 没有区别。从 B2C 中的策略键中删除键会触发差异消息,因此策略会读取键
  • 您是否尝试过在元数据中指定“UseClaimAsBearerToken”?我猜需要有一个声明来携带不记名令牌......

标签: azure-ad-b2c sendgrid-api-v3 azure-ad-b2c-custom-policy


【解决方案1】:

尝试将块中的“my_email@mydomain.com”替换为 SendGrid 帐户>单发件人验证>已验证的“DOMAIN”

Like here

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。要修复它,您必须执行以下步骤:

    1. 添加发件人:为此,请浏览发件人身份验证页面,然后单击创建新发件人。接下来,您必须填写页面上的所有字段,然后点击保存

    1. 验证发件人:您将收到一封需要确认的验证电子邮件。
    2. 更新自定义政策的 from.email 参数
        <ClaimsTransformations> 
          <ClaimsTransformation Id="GenerateEmailRequestBody" TransformationMethod="GenerateJson">
            ...
              <InputParameter Id="from.email" DataType="string" Value="XXX@gmail.com"/>
            ...
          </ClaimsTransformation>
        </ClaimsTransformations>
    
    1. 更新自定义政策的 template_id 参数:如果您使用的是动态模板,则必须更新模板 ID。

        <ClaimsTransformations> 
          <ClaimsTransformation Id="GenerateEmailRequestBody" TransformationMethod="GenerateJson">
            ...
            <InputParameter Id="template_id" DataType="string" Value="d-ac01c68f69364014adc44c7857f95d2e"/>
            ...
          </ClaimsTransformation>
        </ClaimsTransformations>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多