How to display error returned from custom REST API endpoint in a subsequent orchestration step? - error-handling

Based on this question... the REST API endpoint is validating the external IDP email and is correclty returning an error back in the case the email is not valid.
return Content(HttpStatusCode.Conflict, new CustomResponseContent
{
Version = "1.0.0",
Status = (int)HttpStatusCode.Conflict,
UserMessage = message
});
Now I'd like to detect this error and use it in a subsequent OrchestrationStep like this:
<OrchestrationStep Order="3"
Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="REST-ValidateSignInEmail"
TechnicalProfileReferenceId="REST-ValidateSignInEmail" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Taken from here: https://medium.com/the-new-control-plane/creating-an-error-page-for-an-azure-ad-b2c-custom-policy-flow-fb2692a3b50f -->
<OrchestrationStep Order="4"
Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals"
ExecuteActionsIf="true">
<Value>extension_Flag</Value>
<Value>False</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="SelfAssertedRegError"
TechnicalProfileReferenceId="SelfAsserted-RegError" />
</ClaimsExchanges>
</OrchestrationStep>
If step 3 returns a conflict, I'd like to show the error message in step 4 using the custom error page implemented as described here.
I see that step 4 executes based on extension_Flag.
Is there any way I could retrieve and store the result from REST-ValidateSignInEmail and use it in the flag for step 4?
Note: when the user journey finishes executing I see the following AADB2C error in the URL. It comes from the REST API endpoint error (409 - Conflict)...
https://mywebsite.azurewebsites.net/#error=server_error&error_description=AADB2C%3a+user%40gmail.com+is+not+valid.%0d%0aCorrelation+ID%7a+7777f77-7afd-7777-a777-7c77b7e77b7b%0d%0aTimestamp%7a+2019-11-09+14%3a40%3a57Z%0d%0a&state=7777c77a-77ad-414a-84df-3c131ed81ba7
The error_description message is what I'd like to pass to step 4.

I did this in a different way... instead of returning a Conflict [409] status, I changed the REST endpoint to return an OutputClaim like this:
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="extension_isEnabled"
PartnerClaimType="IsEnabled" DefaultValue="false"/>
<OutputClaim ClaimTypeReferenceId="errorMessage"
PartnerClaimType="ErrorMessage"/>
</OutputClaims>
This way I have a claim to check on step 4. Note that I also return an errorMessage from the endpoint. This error message will be later passed to SelfAsserted-RegError Technical Profile.
Depending on the validation done in the back-end, extension_isEnabled will get True or False.
On step 4 we check extension_isEnabled:
<OrchestrationStep Order="4"
Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals"
ExecuteActionsIf="true">
<Value>extension_isEnabled</Value>
<Value>True</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="SelfAssertedRegError"
TechnicalProfileReferenceId="SelfAsserted-RegError" />
</ClaimsExchanges>
</OrchestrationStep>
Step 4 will only be executed when extension_isEnabled is false. If it is true we SkipThisOrchestrationStep and the SelfAsserted-RegError Technical Profile won't be called at all. The UserJourney flow continues as expected.

Related

Azure B2C You are already registered, please press the back button and sign in instead

I have created a custom B2C_1A_SIGNUP_SIGNIN Policy.
Used Google Authentication.
When I hit the create button mypersonaltenantid gets validated through a Azure Function.
I am presented the error message You already registered, please press back button and sign in instead.
Before executing this policy i made sure this user does not exist-
After the error message is displayed i look inside B2C: The user was created incl. my custom claim with value mypersonaltenantid.
I was assuming that i am transferred to a different page after signup. Is this assumption wrong?
Created a Issue and got the final hint.
Looks like a action was performed twice. In my case I had a Base policy and a extension policy which had a ValidationTechnicalProfiles section.
Base.xml
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
</ValidationTechnicalProfiles>
Extension.xml
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="REST-ValidateTenantId" />
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
</ValidationTechnicalProfiles>
My assumption after both files get merged:
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="REST-ValidateTenantId" />
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
</ValidationTechnicalProfiles>
But it looks like the merge is performed like this:
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="REST-ValidateTenantId" />
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
</ValidationTechnicalProfiles>
Of course that explains why AAD write is performed twice.
From my point of view the error message is quite misleading.

WSO2 ESB access context property in the response sequence of an HTTP endpoint

I'm calling an HTTP endpoint and getting the response in
a sequence. Response is getting logged in the seq_sla_resp.
<send receive="seq_sla_resp">
<endpoint key="gov:EDI/SLA/endpoints/edi_sla_payment_ep.xml" />
</send>
Inside this response sequence I'm unable to get a property which I set previously during the call (in the main proxy).
<property expression="//m1:sla_row/m1:tran_id/text()"
name="tran_id" scope="default" type="STRING"
xmlns:m1="http://ws.wso2.org/dataservice" />
When I try to log the property in the seq_sla_resp it ends up in the below error message
<log>
<property expression="$tran_id" name="tran_id" xmlns:m0="http://ws.wso2.org/dataservice"/>
</log>
Following is the error.
SynapseXPath Evaluation of the XPath expression $tran_id resulted in an error
org.jaxen.UnresolvableException: Variable tran_id
How can i get the context value in the response sequence.
In the documentaion it says default scope has the largest life span for the property.
Any help is very much appreciated.
I think you would find that your expression would also not work in the inSequence. You should either use expression="$ctx:tran_id" or expression="get-property('tran_id')"
Please note that WSO2 recommends using $ctx instead of the get-property if the scope is default. The get-property methods search in the registry if the value is not available in the message context. Therefore, it affects the performance.
In your case , you can use
<property expression="$ctx:tran_id" name="tran_id" scope="default" xmlns:m0="http://ws.wso2.org/dataservice"/>
Thanks
Kranthi

Struts1 Action Parameters Use and Working

I am new to Struts and I Don't Understand Struts Action Parameters, specifcally: Name,Validate,Input and Redirect="true"
Example:
*#struts.action name="activation" path="/activation" validate="false" parameter="activation"
*#struts.action-forward name="activationStart" path="/activation.html" redirect="true"
Please try to answer me in terms of above example.
So basically you refuse to read the Struts 1 documentation?
name
The name of the ActionForm bean for this action.
validate
Should validation run?
input
The input page for the form, usually used to return to the form on a validation error.
redirect
When this forward is returned should it be a redirect or a forward?
Name
Name is the name of the formbean which is associated with you JSP. In your struts-config you will have something like this
<form-beans>
<form-bean
name="activation">
<form-property name="name" type="java.lang.String"/>
</form-bean>
</form-beans>
validate
You have validator framework which has some validations in place, like checking the name field for null value and so. You tell your struts whether the validator should work or not. If validation=false, then validation is not performed in your current jsp
input
input is the input jsp. If there are any validation errors, the execute method of the action will not get called; instead the control will go back to that ***.jsp. But you have not specified any input in your example
redirect
Whether to redirect or just forward

WSO2 ESB route endpoints based on results from DSS

So pretty much I want to call
/sendAllUsersAnEmail
Which will call the DSS and do something along the lines of SELECT user_id FROM users WHERE status = 'PENDING'
Here is the issue. How can I get the ESB to loop through the results (or can I get the DSS to call an API directly?) and make a call to /sendEmail/{user_id} for each user? or is this not possible and do I need to return the results to an outside language and call the esb again for each results.
If I understand what you need it´s something like that:
You have a table inside your system DB, with the user_id from users pending to do something in your system and you need to consult this table, get the list of user_id and for every entry in this list made a call to a restful service passing the user_id
So my idea is:
Use a data service to obtain the user_id list.
Create a proxy service that in seq1 call this data service and in a seq2 get the result.
In seq2 use the iterator mediator and splits the messages into parts and processes them asynchronously like in this sample: https://docs.wso2.com/display/ESB481/Sample+400%3A+Message+Splitting+and+Aggregating+the+Responses
An example:
<iterate expression="//m0:getQuote/m0:request" preservePayload="true"
attachPath="//m0:getQuote"
xmlns:m0="http://services.samples">
<target>
<sequence>
<send>
<endpoint>
<address
uri="http://localhost:9000/services/SimpleStockQuoteService"/>
</endpoint>
</send>
</sequence>
</target>
</iterate>
I hope this help you.
Regards.

CCNetModifyingUsers <user> value change after CCNET 1.6 to 1.8 upgrade

After upgrading one of our build servers to the latest version of CCNET it stopped sending emails to modifiers group. We've using Mercurial for source control and version 2.3.2 is installed on the build server.
buildmasters group still gets emails but not modifiers:
<email mailport="25" includeDetails="true" useSSL="false">
<from>buildslave8#company.com</from>
<mailhost>###.###.##.###</mailhost>
<users>
<user name="Name" group="buildmasters" address="name#company.com"/>
</users>
<groups>
<group name="buildmasters">
<notifications>
<NotificationType>Always</NotificationType>
</notifications>
</group>
</groups>
<converters>
<regexConverter find="$" replace="#company.com" />
</converters>
<modifierNotificationTypes>
<NotificationType>Always</NotificationType>
</modifierNotificationTypes>
<subjectSettings>
<subject buildResult="Success" value="Build Status - SUCCESSFUL - ${CCNetProject} - ${CCNetLabel}" />
<subject buildResult="Fixed" value="Build Status - HAS BEEN FIXED - ${CCNetProject} - ${CCNetLabel}" />
<subject buildResult="StillBroken" value="Build Status - FAILED - ${CCNetProject}" />
<subject buildResult="Broken" value="Build Status - FAILED - ${CCNetProject}" />
<subject buildResult="Exception" value="Build Status - SERVER EXCEPTION - ${CCNetProject} - a serious error has occurred" />
</subjectSettings>
<attachments></attachments>
After digging through the build logs I noticed that <user> value under <CCNetModifyingUsers> has changed as follows:
From (CCNET 1.6):
<integrationProperties>
...
<CCNetModifyingUsers>
<user>flast</user>
<user>flast</user>
</CCNetModifyingUsers>
...
</integrationProperties>
To (CCNET 1.8):
<integrationProperties>
...
<CCNetModifyingUsers>
<user>First Last</user>
<user>First Last</user>
</CCNetModifyingUsers>
...
</integrationProperties>
Not sure how the <user> value under <CCNetModifyingUsers> gets populated or how to fix it.
UPDATE #1: I'm trying to see if changing the <converter> to ldapConverter will resolve my issues.
UPDATE #2: Still trying to mess with the ldapConverter:
<ldapConverter domainName="Name.corp" ldapLogOnUser="name" ldapLogOnPassword="pswd" />
This version throws and exception:
EmailPublisher exception: System.FormatException: The specified string is not in the form required for an e-mail address.
at System.Net.Mime.MailBnfHelper.ReadMailAddress(String data, Int32& offset, String& displayName)
at System.Net.Mail.MailAddressCollection.ParseValue(String addresses)
at ThoughtWorks.CruiseControl.Core.Publishers.EmailPublisher.GetMailMessage(String from, String to, String replyto, String subject, String messageText, String workingFolder, String[] attachments)
at ThoughtWorks.CruiseControl.Core.Publishers.EmailPublisher.SendMessage(String from, String to, String replyto, String subject, String message, String workingFolder)
While this:
<ldapConverter domainName="Name.corp" ldapLogOnUser="name" ldapLogOnPassword="pswd" ldapQueryField="userPrincipalName"/>
Successfully builds, but does not send emails out to the modifiers.
UPDATE #3:
I've put the following temporary fix in place:
<converters>
<regexConverter find="(?!^.?).(?!.{0}$).* " replace="" />
<regexConverter find="$" replace="#company.com" />
</converters>
It however does not cover the following cases:
people's Mercurial username does not match their email address' name
people who have a double (triple?) first or last names
UPDATE #4:
Will have to go through the source code to see if I can track down exactly what's causing the issues... might have to maintain a local build of it going forward.
I dealt with this in November of 2013. I had to install the CCNET source code and modify EmailLDAPConverter.cs. The Convert method creates a search filter using the SSAMAccountName Active Directory attribute. This would fail. I ended up filtering on the Active Directory "displayName" attribute.