如何从B2C自定义策略返回到带有自定义错误的SPA应用程序?

huangapple go评论48阅读模式
英文:

How to return from B2C custom policy to SPA application with custom error?

问题

我有一个自定义用户属性,用于确定用户是否已完全注册。基于此,我想在策略中继续工作流程,以使用户可以完全注册(明显路径),或将用户重定向到登录流程(问题路径 - 在我的情况下如何实现?)。

我有以下工作流程:

  1. 我们的服务通过 Graph API 创建了一个 B2C 用户,并向用户发送了邀请电子邮件。电子邮件中包含了带有令牌的邀请链接,令牌作为查询参数传递(基于此示例)。令牌包含特定的用户数据,如电子邮件地址和对象标识。

  2. 用户打开链接后,应用程序开始注册流程(我有单独的登录和注册)。

  3. 注册流程包括以下步骤:

    • 从令牌获取用户数据

      <OrchestrationStep Order="1" Type="GetClaims" CpimIssuerTechnicalProfileReferenceId="IdTokenHint_ExtractClaims" />
      
    • 从目录中读取用户数据

      <OrchestrationStep Order="2" Type="ClaimsExchange">
          <ClaimsExchanges>
              <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
          </ClaimsExchanges>
      </OrchestrationStep>
      
    • 现在,我有一个声明,指示用户是否已完全注册。

目标

如果用户已完全注册(第二次点击邀请链接),我希望返回应用程序,并提供启动登录流程的信息。然后,用户可以选择所有的登录选项(作为本地用户,作为AD用户,可以使用忘记密码)。

我尝试过但不起作用的方法

我不想使用 SendClaims 步骤,因为我不想返回该用户的 ID 令牌。

我知道当自定义策略意外失败时,它会在授权响应的位置标头中返回其中一个错误代码。然后,应用程序可以读取此错误代码并做出适当的反应。但是,我认为我不能在我的情况下使用这个选项。

另一个我不能使用的选项是直接从注册流程开始登录子流程。这是因为在注册的初始步骤中,我获得了一个不可移除的对象标识声明。这样,即使另一个用户输入了他的凭据,也会采用初始的对象标识。

作为一种解决方法,我尝试直接从注册流程开始专用的登录流程,该流程只显示密码字段(可选的只读电子邮件字段)。这样,只有已知对象标识的用户才能进行身份验证。但是我看到SelfAsserted-LocalAccountSignin-Email可能需要输入声明<InputClaim ClaimTypeReferenceId="signInName" DefaultValue="{OIDC:LoginHint}" AlwaysUseDefaultValue="true" />。按照这种方式,我可能会注入一个只读的电子邮件(我对这个只读不确定),但我没有设置 login_hint 参数(根据文档),该参数会填充{OIDC:LoginHint}

是否有其他实现我的目标的选项?

英文:

I have a custom user attribute that defines if a user is fully registered. Based on this I would like to continue workflow in the policy so a user may be fully registered (obvious path) or redirect user to sign-in journey (problematic path - how to achieve it in my case?).

I have the following workflow:

  1. Our service creates a B2C user by Graph API and sends an invitation email to the user. An email has the invitation link to our SPA application with the token in query param (based on this sample). The token contains specific user data like email address and objectId.

  2. A user opens the link, the application starts sign-up flow (I have separate sign-in and sign-up).

  3. The sign-up flow does steps:

    • Gets user data from the token

      <OrchestrationStep Order="1" Type="GetClaims" CpimIssuerTechnicalProfileReferenceId="IdTokenHint_ExtractClaims" />
      
    • Reads user data from directory

      <OrchestrationStep Order="2" Type="ClaimsExchange">
          <ClaimsExchanges>
              <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
          </ClaimsExchanges>
      </OrchestrationStep>
      
    • Now, I have a claim which says that a user is fully registered or not.

Goal:

If a user is fully registered (clicked the invitation link a second time) I would like to return to the application with information that a sign-in flow should be started. Then, a user would have all options of sign-in (as local user, as AD user, may use forgot password).

What I tried and it doesn't work for me:

I don't want to use SendClaims step, as I don't want to return ID token of that user.

I know that when custom policy fails unexpectedly, it returns one of error codes in location header of authorize response. Then, the application may read this error code and react appropriately. However, I think I cannot use this on my purpose.

Another option which I cannot use is to start sign-in sub yourney directly from sign-up journey. This is because after initial steps of sign-up I got the objectId claim in a bag which I cannot remove. Such objectId causes that even when another user writes his credentials, the inital objectId is taken.

As a workaround, I tried to start dedicated sign-in journey directly from sign-up which would display just the password field (with optional readonly email field). In such way, only a user with known objectId would be authenticated. But I see that the SelfAsserted-LocalAccountSignin-Email which might handle this requires input claim <InputClaim ClaimTypeReferenceId="signInName" DefaultValue="{OIDC:LoginHint}" AlwaysUseDefaultValue="true" />. Going this way I would maybe inject email which would be readonly (I'm not sure about this readonly), but I don't have login_hint parameter set (based on docs) which would fill {OIDC:LoginHint}.

Is there any other option of how to achieve my goal?

答案1

得分: 1

如果您想将OAuth2错误返回给客户端,您可以使用OAuth2自定义错误技术配置文件

或者,您可以通过显示一个没有“继续”或“取消”按钮的自我断言页面来阻止B2C中的用户。要实现此目标,请将元数据项 setting.showCancelButtonsetting.showContinueButton 设置为 false

英文:

If you want to return an OAuth2 error back to the client then you can use the OAuth2 custom error technical profile.

Alternatively, you can stop the user in B2C by displaying a Self Asserted page with no "Continue" or "Cancel" button. To do this set the metadata items setting.showCancelButton and setting.showContinueButton to false.

huangapple
  • 本文由 发表于 2023年6月27日 17:17:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76563376.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定