Alex
Alex

Reputation: 894

Error messages from REST API call is not showing in B2C custom policy

I have a self asserted technical profile in my custom policy, it have a validation technical profile which is a REST API (azure function) call. I'm not directly calling the azure function from policy, from policy will call azure APIM and APIM will pass the request to azure function.

The problem I'm facing is when my function returns a custom error message it is not showing as expected in policy.

return new OkObjectResult(new ResponseContentModel
      {
       userMessage = "Sorry, Please provide valid information ",
       status = 409,
       retryCounter = data.RetryCounter
     });

My technical profile is as follows:

<TechnicalProfile Id="Registration">
          <DisplayName>Email signup</DisplayName>
          <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
          <Metadata>
            <Item Key="IpAddressClaimReferenceId">IpAddress</Item>
            <Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item>
            <Item Key="language.button_continue">Activate Account</Item>
            <!-- Sample: Remove sign-up email verification -->
            <Item Key="EnforceEmailVerification">False</Item>
            <Item Key="setting.retryLimit">5</Item>
          </Metadata>
          <InputClaimsTransformations>
            <!--Sample: Copy the email to ReadOnlyEamil claim type-->  
            <InputClaimsTransformation ReferenceId="CreateReadOnlyEmailAddress" />
          </InputClaimsTransformations>
          <InputClaims>
            <InputClaim ClaimTypeReferenceId="email" />
            <InputClaim ClaimTypeReferenceId="givenName" />
            <InputClaim ClaimTypeReferenceId="surname" />
          </InputClaims>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="objectId" DefaultValue="123" />
            <OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />
            <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
            <OutputClaim ClaimTypeReferenceId="tncCheckbox" Required="true" />

            <OutputClaim ClaimTypeReferenceId="retryCounter" DefaultValue="0" />
            <OutputClaim ClaimTypeReferenceId="isFound" DefaultValue="false" />
            <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
            <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication"/>
            <OutputClaim ClaimTypeReferenceId="newUser" DefaultValue="true" />
          </OutputClaims>
          <ValidationTechnicalProfiles>
            <ValidationTechnicalProfile ReferenceId="API-Validate-UserInfo" />
            <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
          </ValidationTechnicalProfiles>
          <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
        </TechnicalProfile>

The REST API validation technical profile is as follows:

<TechnicalProfile Id="API-Validate-UserInfo">
                <DisplayName>User OTP Notifications</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://myapimurl</Item>
                  <Item Key="SendClaimsIn">Body</Item>                        
                  <Item Key="AuthenticationType">ClientCertificate</Item>
                </Metadata>
                <CryptographicKeys>
                    <Key Id="ClientCertificate" StorageReferenceId="B2C_1A_APIMClientCertificate" />
                </CryptographicKeys>
                <InputClaims>
                    <InputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="GivenName" />
                    <InputClaim ClaimTypeReferenceId="surname" PartnerClaimType="SurName"/>
                    <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="Email"/>
                    <InputClaim ClaimTypeReferenceId="retryCounter" PartnerClaimType="RetryCounter"/>
                </InputClaims>
                <OutputClaims>
                  <OutputClaim ClaimTypeReferenceId="retryCounter" />
                  <OutputClaim ClaimTypeReferenceId="isFound" />
                </OutputClaims>
                <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
            </TechnicalProfile>

Error message showing in the UI is:

The claims exchange 'API-Validate-UserInfo' specified in step '5' returned HTTP error response with Code 'BadRequest' and Reason 'Bad Request'.

About the function, i'm using .net core 3.1 and function runtime version is ~3

Upvotes: 2

Views: 2440

Answers (3)

Michael Freidgeim
Michael Freidgeim

Reputation: 28541

In my code I've added properties descriptions from Returning validation error message

 public class B2CPolicyValidationResponse
 {
     /// <summary>
     /// Required. Your REST API version. For example: 1.0.1
     /// </summary>
     public string Version { get; set; } = "1.0.0";
     /// <summary>
     /// Required. An HTTP response status codes-like number, and must be 409
     /// </summary>
     public int Status { get; set; } = 409;//Conflict
     /// <summary>
     /// An error code from the RESTful endpoint provider, which is displayed when DebugMode is enabled.
     /// </summary>
     public string Code { get; set; }
     /// <summary>
     /// Required. An error message that is shown to the user.
     /// </summary>
     public string UserMessage { get; set; }
     /// <summary>
     /// The verbose description of the problem and how to fix it, which is displayed when DebugMode is enabled.
     /// </summary>
     public string DeveloperMessage { get; set; }
     /// <summary>
     /// A request identifier from the RESTful endpoint provider, which is displayed when DebugMode is enabled.
     /// </summary>
     public string RequestId { get; set; }
     /// <summary>
     /// A URI that points to additional information, which is displayed when DebugMode is enabled.
     /// </summary>
     public string MoreInfo { get; set; }
 }

Upvotes: 0

EladTal
EladTal

Reputation: 2876

Following this documentation, this is the required error structure:

Returning validation error message

further more, make sure that the response should has http error code corresponding to the content error code:

return StatusCode(409, new ResponseContent { userMessage = ex.Message });

where ResponseContent has the following structure:

        public class ResponseContent : IResult
    {
        public string version { get; set; }
        public int status { get; set; }
        public string code { get; set; }
        public string userMessage { get; set; }
        public string developerMessage { get; set; }
        public string requestId { get; set; }
        public string moreInfo { get; set; }

        public ResponseContent()
        {
            version = "1.0.0";
            status = 409;
            code = "API12345";
            requestId = "50f0bd91-2ff4-4b8f-828f-00f170519ddb";
            userMessage = "Message for the user";
            developerMessage = "Verbose description of problem and how to fix it.";
            moreInfo = "https://learn.microsoft.com/en-us/azure/active-directory-b2c/restful-technical-profile#returning-validation-error-message";
        }
    }

Upvotes: 1

Alex
Alex

Reputation: 894

Found the issue referred this article. Need to include version into the response message version, status and userMessage are mandatory fields for error response message.

{
  version = "1.0.0",
  userMessage = "Sorry, Something happened unexpectedly. Please try after sometime.",
  status = 409,
 }

Upvotes: 3

Related Questions