Azure B2C - 提供的令牌不包含有效的颁发者

Azure B2C - The provided token does not contain a valid issuer

我正在使用 Azure B2C 连接到外部 OpenID Connect 身份提供者,我在 B2C 中创建了一个基本的用户流,它可以工作但只带回少量声明,所以我需要创建一个自定义策略来传递为我的 IDP 自定义输入参数并收集额外的声明。

我从 SocialAndLocalAccount 示例开始,并使用我的 IDP 的详细信息进行了修改:

TrustFrameworkBase.xml(缩减为技术概况 + 用户旅程)

      ...
      <ClaimType Id="sub">
        <DisplayName>Subject</DisplayName>
        <DataType>string</DataType>
        <DefaultPartnerClaimTypes>
          <Protocol Name="OpenIdConnect" PartnerClaimType="sub" />
        </DefaultPartnerClaimTypes>
        <UserHelpText />
      </ClaimType>
      <ClaimType Id="ui_locales">
        <DisplayName>UI Locales</DisplayName>
        <DataType>string</DataType>
        <UserHelpText>Special parameter passed for account authentication to Tell Us Once.</UserHelpText>
      </ClaimType>
      <ClaimType Id="givenName">
        <DisplayName>Given Name</DisplayName>
        <DataType>string</DataType>
        <DefaultPartnerClaimTypes>
          <Protocol Name="OAuth2" PartnerClaimType="given_name" />
          <Protocol Name="OpenIdConnect" PartnerClaimType="given_name" />
          <Protocol Name="SAML2" PartnerClaimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" />
        </DefaultPartnerClaimTypes>
        <UserHelpText>Your given name (also known as first name).</UserHelpText>
        <UserInputType>TextBox</UserInputType>
      </ClaimType>
      <ClaimType Id="surname">
        <DisplayName>Surname</DisplayName>
        <DataType>string</DataType>
        <DefaultPartnerClaimTypes>
          <Protocol Name="OAuth2" PartnerClaimType="family_name" />
          <Protocol Name="OpenIdConnect" PartnerClaimType="family_name" />
          <Protocol Name="SAML2" PartnerClaimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" />
        </DefaultPartnerClaimTypes>
        <UserHelpText>Your surname (also known as family name or last name).</UserHelpText>
        <UserInputType>TextBox</UserInputType>
      </ClaimType>
      <ClaimType Id="DateOfBirth">
        <DisplayName>Date Of Birth</DisplayName>
        <DataType>string</DataType>
        <DefaultPartnerClaimTypes>
          <Protocol Name="OAuth2" PartnerClaimType="birthdate" />
          <Protocol Name="OpenIdConnect" PartnerClaimType="birthdate" />
          <Protocol Name="SAML2" PartnerClaimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth" />
        </DefaultPartnerClaimTypes>
        <UserHelpText>Your date of birth.</UserHelpText>
        <UserInputType>TextBox</UserInputType>
      </ClaimType>
      ...
    <ClaimsProvider>
      <Domain>tellusonce</Domain>
      <DisplayName>Tell Us Once</DisplayName>
      <TechnicalProfiles>
        <TechnicalProfile Id="TUO-OpenIdConnect">
          <DisplayName>Tell Us Once Login</DisplayName>
          <Description>Login through Tell Us Once</Description>
          <Protocol Name="OpenIdConnect" />
          <Metadata>
            <Item Key="client_id">this is where i put my client id</Item>
            <Item Key="ProviderName">Tell Us Once</Item>
            <Item Key="METADATA">this is where my metadata is</Item>
            <Item Key="response_types">code</Item>
            <Item Key="response_mode">form_post</Item>
            <Item Key="scope">openid</Item>
            <Item Key="HttpBinding">POST</Item>
            <Item Key="UsePolicyInRedirectUri">false</Item>
          </Metadata>
          <CryptographicKeys>
            <Key Id="client_secret" StorageReferenceId="B2C_1A_TellUsOnceSecret" />
          </CryptographicKeys>
          <InputClaims>
            <InputClaim ClaimTypeReferenceId="scope" DefaultValue="openid profile" />
            <InputClaim ClaimTypeReferenceId="prompt" DefaultValue="login" />
            <InputClaim ClaimTypeReferenceId="ui_locales" DefaultValue="en-US" />
          </InputClaims>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="issuerUserId" PartnerClaimType="sub" />
            <OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="given_name" />
            <OutputClaim ClaimTypeReferenceId="middleName" DefaultValue="" />
            <OutputClaim ClaimTypeReferenceId="surname" PartnerClaimType="family_name" />
            <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="email" />
            <OutputClaim ClaimTypeReferenceId="DateOfBirth" PartnerClaimType="birthdate" />
            <OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="ITP-B2C" />
            <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="ITP-Auth-DEV-OIDC" />
          </OutputClaims>
          <OutputClaimsTransformations>
            <OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName" />
            <OutputClaimsTransformation ReferenceId="CreateUserPrincipalName" />
            <OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId" />
            <OutputClaimsTransformation ReferenceId="CreateSubjectClaimFromAlternativeSecurityId" />
          </OutputClaimsTransformations>
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>
    ...
  <UserJourneys>
    <UserJourney Id="SignUpOrSignInOidc">
      <OrchestrationSteps>
        <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
          <ClaimsProviderSelections>
            <ClaimsProviderSelection TargetClaimsExchangeId="TUO-OIDCExchange" />
          </ClaimsProviderSelections>
        </OrchestrationStep>
        <OrchestrationStep Order="2" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="TUO-OIDCExchange" TechnicalProfileReferenceId="TUO-OpenIdConnect" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <!-- For social IDP authentication, attempt to find the user account in the directory. -->
        <OrchestrationStep Order="3" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="AADUserReadUsingAlternativeSecurityId" TechnicalProfileReferenceId="AAD-UserReadUsingAlternativeSecurityId-NoError" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <!-- Create the user in the directory if one does not already exist. -->
        <OrchestrationStep Order="4" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>objectId</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <ClaimsExchanges>
            <ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="5" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
      </OrchestrationSteps>
      <ClientDefinition ReferenceId="DefaultWeb" />
    </UserJourney>
  </UserJourneys>

TrustFrameworkExtensions.xml

<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="itpauthdev.onmicrosoft.com" 
  PolicyId="B2C_1A_TrustFrameworkExtensions" 
  PublicPolicyUri="http://itpauthdev.onmicrosoft.com/B2C_1A_TrustFrameworkExtensions" 
  TenantObjectId="ae2201eb-e4e9-44e7-8c73-b52e37ba01f8">
  <BasePolicy>
    <TenantId>itpauthdev.onmicrosoft.com</TenantId>
    <PolicyId>B2C_1A_TrustFrameworkBase</PolicyId>
  </BasePolicy>
  <BuildingBlocks></BuildingBlocks>
  <ClaimsProviders>
    <ClaimsProvider>
      <Domain>tellusonce</Domain>
      <DisplayName>Tell Us Once</DisplayName>
      <TechnicalProfiles>
        <TechnicalProfile Id="TUO-OpenIdConnect">
          <DisplayName>Tell Us Once Login</DisplayName>
          <Description>Login through Tell Us Once</Description>
          <Protocol Name="OpenIdConnect" />
          <Metadata>
            <Item Key="client_id">this is where i put my client id</Item>
            <Item Key="ProviderName">Tell Us Once</Item>
            <Item Key="METADATA">this is where my metadata is</Item>
            <Item Key="response_types">code</Item>
            <Item Key="response_mode">form_post</Item>
            <Item Key="scope">openid</Item>
            <Item Key="HttpBinding">POST</Item>
            <Item Key="UsePolicyInRedirectUri">false</Item>
          </Metadata>
          <CryptographicKeys>
            <Key Id="client_secret" StorageReferenceId="B2C_1A_TellUsOnceSecret" />
          </CryptographicKeys>
          <InputClaims>
            <InputClaim ClaimTypeReferenceId="acr_values" DefaultValue="urn:id.gov.au:tdif:acr:ip1:cl1" />
            <InputClaim ClaimTypeReferenceId="scope" DefaultValue="openid profile" />
            <InputClaim ClaimTypeReferenceId="prompt" DefaultValue="login" />
            <InputClaim ClaimTypeReferenceId="ui_locales" DefaultValue="en-US" />
          </InputClaims>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="issuerUserId" PartnerClaimType="sub" />
            <OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="given_name" />
            <OutputClaim ClaimTypeReferenceId="middleName" DefaultValue="" />
            <OutputClaim ClaimTypeReferenceId="surname" PartnerClaimType="family_name" />
            <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="email" />
            <OutputClaim ClaimTypeReferenceId="DateOfBirth" PartnerClaimType="birthdate" />
            <OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="ITP-B2C" />
            <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="ITP-Auth-DEV-OIDC" />
          </OutputClaims>
          <OutputClaimsTransformations>
            <OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName" />
            <OutputClaimsTransformation ReferenceId="CreateUserPrincipalName" />
            <OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId" />
            <OutputClaimsTransformation ReferenceId="CreateSubjectClaimFromAlternativeSecurityId" />
          </OutputClaimsTransformations>
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>
  </ClaimsProviders>
  <UserJourneys>
    <UserJourney Id="SignUpOrSignInOidc">
      <OrchestrationSteps>
        <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
          <ClaimsProviderSelections>
            <ClaimsProviderSelection TargetClaimsExchangeId="TUO-OIDCExchange" />
          </ClaimsProviderSelections>
        </OrchestrationStep>
        <OrchestrationStep Order="2" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="TUO-OIDCExchange" TechnicalProfileReferenceId="TUO-OpenIdConnect" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <!-- For social IDP authentication, attempt to find the user account in the directory. -->
        <OrchestrationStep Order="3" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="AADUserReadUsingAlternativeSecurityId" TechnicalProfileReferenceId="AAD-UserReadUsingAlternativeSecurityId-NoError" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <!-- Create the user in the directory if one does not already exist. -->
        <OrchestrationStep Order="4" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>objectId</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <ClaimsExchanges>
            <ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="5" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
      </OrchestrationSteps>
      <ClientDefinition ReferenceId="DefaultWeb" />
    </UserJourney>
  </UserJourneys>
</TrustFrameworkPolicy>

signin_signup_oidc.xml

<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="itpauthdev.onmicrosoft.com" 
  PolicyId="B2C_1A_signup_signin_oidc" 
  PublicPolicyUri="http://itpauthdev.onmicrosoft.com/B2C_1A_signup_signin" 
  TenantObjectId="ae2201eb-e4e9-44e7-8c73-b52e37ba01f8">
  <BasePolicy>
    <TenantId>itpauthdev.onmicrosoft.com</TenantId>
    <PolicyId>B2C_1A_TrustFrameworkExtensions</PolicyId>
  </BasePolicy>
  <RelyingParty>
    <DefaultUserJourney ReferenceId="SignUpOrSignInOidc" />
    <UserJourneyBehaviors></UserJourneyBehaviors>
    <TechnicalProfile Id="PolicyProfile">
      <DisplayName>PolicyProfile</DisplayName>
      <Protocol Name="OpenIdConnect" />
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="givenName" />
        <OutputClaim ClaimTypeReferenceId="middleName" DefaultValue="" />
        <OutputClaim ClaimTypeReferenceId="surname" />
        <OutputClaim ClaimTypeReferenceId="email" />
        <OutputClaim ClaimTypeReferenceId="DateOfBirth" DefaultValue="ClaimNotFound" />
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
        <OutputClaim ClaimTypeReferenceId="identityProvider" />
        <OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue="{Policy:TenantObjectId}" />
      </OutputClaims>
      <SubjectNamingInfo ClaimType="sub" />
    </TechnicalProfile>
  </RelyingParty>
</TrustFrameworkPolicy>

当我单击“B2C_1A_signin_signup_oidc”并选择 运行 用户流程时,我会看到我的 IDP 的登录屏幕,一旦我成功登录,我就会从我的 IDP 那里收到授权代码响应,我的 IDP已经配置了“/authresp”重定向 uri as per Microsoft documentation(底部的“Redirect Uri”部分)但似乎“/authresp”没有将代码交换为 id_token 因为当它重定向到 jwt.ms 我得到“令牌不包含有效的发行者”。

Fiddler 代码响应

通过使用 fiddler 的检查器,我可以看到 IDP 的端点正在使用看起来像这样的代码(不是实际代码)进行响应:

<HTML>

<HEAD>
    <TITLE>OIDC Form_Post Response</TITLE>
</HEAD>

<BODY Onload="document.forms[0].submit()">
    <FORM METHOD="POST" ACTION="https://itpauthdev.b2clogin.com/itpauthdev.onmicrosoft.com/oauth2/authresp"> <INPUT
            TYPE="HIDDEN" NAME="code"
            VALUE="4cfed1f1-bfcc-42db-b39c-d79480f6d333.056c6e05-eaec-426a-a5e7-bf9f66f962be.15ac212d-38b7-4e9b-80e2-a948be9360e5" />
        <INPUT TYPE="HIDDEN" NAME="state"
            VALUE="StateProperties=eyJTSUQiOiJ4LW1zLWNwaW0tcmM6M2RkYmRhYjktY2VkZS00MDA4LTliNWYtOGRmZjU2ZDZmZDYzIiveWIlEIjoiMmFtkoc5YjUtMzg0Zi00M2JmLThkMDUtMjIzMGYxNzU1M2JjIiwiVE9CRJI6ImFlMjIwMWViLWU0ZTktNDRlNy04YzczLWI1MmUzN2JhMDFmOCJ9" />
        <INPUT TYPE="HIDDEN" NAME="session_state" VALUE="65e01676-90d1-4c5e-a7f4-66dfd7b3211b" /> <NOSCRIPT>
            <P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue .</P>
            <INPUT name="continue" TYPE="SUBMIT" VALUE="CONTINUE" />
        </NOSCRIPT> </FORM>
</BODY>

</HTML>

Fiddler AuthResp 响应

再次使用 Fiddler,我可以看到 AuthResp 没有使用 IDP 的令牌端点将代码交换为 id_token(或者遇到错误,我没有得到任何帮助)。相反,我回来了:

<html>

<head>
    <title>Object moved</title>
</head>

<body>
    <h2>Object moved to <a
            href="https://jwt.ms/#error=invalid_request&amp;error_description=AADB2C90238%3a+The+provided+token+does+not+contain+a+valid+issuer.+Please+provide+another+token+and+try+again.%0d%0aCorrelation+ID%3a+2ad979b5-384f-43bf-8d05-2230f17553bc%0d%0aTimestamp%3a+2021-02-26+04%3a29%3a08Z%0d%0a">here</a>.
    </h2>
</body>

</html>

问题

  1. 我在某处的文档中读到“OpenIDConnect”技术配置文件会自动将代码交换为 ID 令牌,但我似乎找不到该文档,是我的配置缺少一个步骤还是我必须这样做手动添加额外的 userjourney?
  2. 如果“/authresp”和令牌端点之间存在错误通信,我是否可以在某个地方寻找更具描述性的错误消息? jwt.ms 和审计日志都只是说“令牌不包含有效的颁发者”。

我认为登录的技术配置文件配置不正确。您可以在 starter pack samples.

中找到使用 OpenIdConnect 的工作示例

请在示例中参考,例如到

该错误意味着来自 OIDC 提供者的 ID 令牌有一个发行者 (iss) 声明与众所周知的 OIDC 配置端点中的发行者不匹配。您可以将发行者元素添加到 TUO-OpenIdConnect 技术配置文件的元数据中,以使用令牌中出现的值覆盖它。

https://docs.microsoft.com/en-us/azure/active-directory-b2c/openid-connect-technical-profile#metadata

发行者:OpenID Connect 身份提供者的唯一标识符。颁发者元数据的值优先于 OpenID 知名配置端点中指定的颁发者。如果指定,Azure AD B2C 会检查身份提供者返回的令牌中的 iss 声明是否等于颁发者元数据中指定的声明。

我使用的是 ADB2C 并添加了 AAD 作为家庭领域发现的身份提供者。 HRD 按预期工作,它基于域将用户重定向到 AAD(https://login.microsoftonline.com) 进行身份验证,在成功身份验证后,它重定向到 jwt.ms 并显示“AADB2C90238:提供的令牌不包含有效的颁发者. 请提供另一个令牌,然后重试。”错误代码。 我能够通过从元数据标记中删除以下项目来解决此问题。

<Item Key="ProviderName">https://sts.windows.net/ffc9d30c-a7e7-486d-bbcd-66d88af6f4c9/</Item>

Click here了解更多信息