I have implemented HTTP Basic Authentication for my mule flow application.
It listens on HTTP and the URI is http://localhost:8082/login.
<flow name="wsGetReport">
<http:listener config-ref="HTTP_Listener_Configuration" path="${wsPath}" doc:name="HTTP"/>
<logger level="INFO" message="## received" doc:name="Logger"/>
<http:basic-security-filter realm="mule-realm"/>
<flow-ref name="doSubFlow" doc:name="doSubFlow"/>
<logger level="INFO" message="## passed security" doc:name="Logger"/>
<http:static-resource-handler resourceBase="${app.home}/classes" doc:name="HTTP Static Resource Handler" defaultFile="index.html"/>
</flow>
I would retrieve the username typed in the login by the user, and show it in the http Static resource (an html page).
How can I store the username used in authentication?
Thanks.
You can get the user and password of basic auth using mel as following and store it in a variable:-
<flow name="SpringBasicAuthExample">
<http:listener config-ref="HTTP_Listener_Configuration" path="/security" doc:name="HTTP"/>
<logger level="INFO" message="## received" doc:name="Logger"/>
<http:basic-security-filter realm="mule-realm"/>
<set-payload value="#[message.inboundProperties.'Authorization']" doc:name="Set Payload"/>
<set-payload value="#[message.payloadAs(java.lang.String).substring('Basic'.length()).trim()]" doc:name="Set Payload"/>
<expression-transformer expression="#[String credentials = new String(org.mule.util.Base64.decode(payload),java.nio.charset.Charset.forName('UTF-8')); String[] values = credentials.split(':',2); flowVars.user= values[0]; flowVars.pass=values[1];]" doc:name="Expression"/>
<set-payload value="#[['user':flowVars.user,'password':flowVars.pass]]" doc:name="Set Payload"/>
<parse-template location="index.html" doc:name="Parse Template"/>
<logger level="INFO" message="## passed security" doc:name="Logger"/>
</flow>
</mule>
And at the end you can store the username and password in a variable and pass the variable in an html file to display the username using parse-template dynamically:-
index.html:-
<html>
<body>
<b>UserName: #[flowVars.user]</b>
</body>
</html>
Pls note your index.html should be there in resource folder. Here once you get the username in variable you can store it or pass it anywhere you wish :)
take a look at BasicAuthenticationFilter.extractAndDecodeHeader(). this is how Spring Framework does it.
You can get username and password from basic auth Authentication as below:
<set-session-variable variableName="userInfo" value="#[org.mule.util.StringUtils.split(new String(org.mule.util.Base64.decode(message.inboundProperties.'Authorization'.substring('Basic'.length()).trim()), java.nio.charset.Charset.forName('UTF-8')), ':')]" doc:name="Session Variable"/>
<logger message="user name = #[sessionVars.userInfo[0]] ***** password= #[sessionVars.userInfo[1]]" level="INFO" doc:name="Logger"/>
Related
I have a flow where I am trying to load a HTML page if successfully login or fails. Flow is working but while doing POST job on browser side it's not redirecting to the loginSuccessful.html or login/loginFailure.html.
<flow name="GetLoginPage">
<http:listener config-ref="HTTP_Listener_Configuration" path="/login" allowedMethods="GET" doc:name="HTTP"/>
<parse-template location="login/index.html" doc:name="Parse Template"/>
</flow>
<flow name="Dologin">
<http:listener config-ref="HTTP_Listener_Configuration" path="/login" allowedMethods="POST" doc:name="HTTP"/>
<logger message="trying to login!!!!!!!!!!!" level="INFO" doc:name="Logger"/>
<choice doc:name="Choice">
<when expression="#[payload.username == "mule" and payload.password == "mule"]">
<logger message="login successfully!!!!!!!!!!!" level="INFO" doc:name="Logger"/>
<parse-template location="login/loginSuccessful.html" doc:name="Parse Template"/>
</when>
<otherwise>
<logger message="login failed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" level="INFO" doc:name="Logger"/>
<parse-template location="login/loginFailure.html" doc:name="Parse Template"/>
</otherwise>
</choice>
</flow>
I took the liberty of creating my own payload in JSON and added the payload values from above:
{
"name": "mule",
"password": "mule"
}
Then, added a data transformer from JSON to Java, then I mildly adjusted your conditional test to eliminate the encoded quotes and replaced them with single quotes:
payload.username == 'mule' and payload.password == 'mule'
And the choice router correctly to pick up my test files with the parse template.
I want to check if a URI parameter exists in the URL using Mule 3.8.3 and also need to make sure that inboundProperties is not empty either when using the Choice component in Anypoint Studio 6.2 and Mule 3.8.3.
I have tried:
#[message.inboundProperties.'http.uri.params'.code != empty]
#[org.mule.util.StringUtils.isNotEmpty(message.inboundProperties.'http.uri.params'.code)]
For both I get
org.mule.api.expression.ExpressionRuntimeException: Execution of the
expression
"org.mule.util.StringUtils.isNotEmpty(message.inboundProperties.'http.query.params'.code)"
failed.
Is there any other way to try?
There are two "Expression" in palate.
1.Expression-transformer
Example : <expression-transformer expression="#[message.inboundProperties.'http.uri.params'.param != empty]" doc:name="Expression"/>
2.Expression-component
Example : <expression-component doc:name="Expression"/>
Make sure you use "Expression-transformer" as shown below
Try below flow in Anypoint Studio.It works for me.
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8082" basePath="/testapi" doc:name="HTTP Listener Configuration"/>
<flow name="uri">
<http:listener path="uri/{param}/resource" config-ref="HTTP_Listener_Configuration" doc:name="HTTP"/>
<expression-transformer expression="#[message.inboundProperties.'http.uri.params'.param != empty]" doc:name="Expression"/>
<object-to-string-transformer doc:name="Object to String"/>
<set-payload value="#[payload]" doc:name="Set Payload"/>
</flow>
Test above with below url in your browser
http://localhost:8082/testapi/uri/testUriParam/resource
This could be used with Choice component component as well.
Try below code :
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8082" basePath="/testapi" doc:name="HTTP Listener Configuration"/>
<flow name="uri">
<http:listener path="uri/{param}/resource" config-ref="HTTP_Listener_Configuration" doc:name="HTTP"/>
<choice doc:name="Choice">
<when expression="#[message.inboundProperties.'http.uri.params'.param != empty]">
<logger message="Found URI Param" level="INFO" doc:name="Logger"/>
<set-payload value="Found URI Param" doc:name="Set Payload"/>
</when>
<otherwise>
<logger level="INFO" doc:name="Logger" message="URI Param not found"/>
<set-payload value="URI Param not found" doc:name="Set Payload"/>
</otherwise>
</choice>
</flow>
I have two flow one receive the xml payload and another json. I am routing the xml call to json flow using mule flow reference component after converting the xml to json payload. and second flow returns the json payload that i need to convert back to xml and reply to client.
My mule flow reference is throwing TransformerMsgException while receiving the json response from second flow.
Failed to transform from "json" to "java.lang.String" (org.mule.api.transformer.TransformerException). Message payload is of type: String
Here are the code for your reference -
<flow name="post:/chkdb:application/json:chkd-config">
<logger message="========json payload==>>>>==== #[message.payload]" level="INFO" doc:name="Logger"/>
<set-variable variableName="GGG_Number" value="#[json:ggg]" doc:name="Variable"/>
<!-- db call returns the payload-->
<choice doc:name="Choice">
<when expression="#[message.payload.size()>0]">
<set-payload value="{"indicator":"True"}" mimeType="application/json" doc:name="Set Payload"/>
</when>
<otherwise>
<set-payload value="{"indicator":"False"}" mimeType="application/json" doc:name="Set Payload"/>
</otherwise>
</choice>
<logger message="=========after producing json output=======" level="INFO" doc:name="Logger"/>
</flow>
<flow name="post:/chkdb:application/xml:chkdb-config">
<logger message="========= xml payload======== #[message.payload]" level="INFO" doc:name="Logger"/>
<json:xml-to-json-transformer mimeType="application/json" doc:name="XML to JSON"/>
<flow-ref name="post:/chkdb:application/json:chkdb-config" doc:name="post:/chkdb:application/json:chkdbapi-config"/> <!-- Getting exception here -->
<logger message=" after subflow call ==== #[message.payload]" level="INFO" doc:name="Logger"/>
<json:json-to-xml-transformer mimeType="application/xml" doc:name="JSON to XML"/>
<logger message="after json to xml conversion" level="INFO" doc:name="Logger"/>
</flow>
XML Request -
<ggg>DeJmp03bkqALlRFYmgu4+A==</ggg>
How i should retrieve the json response from other flow to current flow.
There is something missing here
First flow name: post:/chkdb:application/json:chkdbapi-config
Second flow name: post:/chkdb:application/xml:chkdbapi-config
Flow ref in second flow: post:/chkdb:application/json:chkdb-config
You are not referencing First flow.
So from your flow posted I can find few issues as follows :-
1. You are using where is the flow post:/chkdb:application/json:chkdb-config doesn't exits and it should be post:/chkdb:application/json:chkdbapi-config instead
2. Right now in the flow you are using <when expression="#[message.payload.size()>0]"> where as the message payload is in String format right now.
So, you can either use <when expression="#[message.payload.length()>0]">, using length() instead of size() or put a <json:json-to-object-transformer returnClass="java.lang.Object" doc:name="JSON to Object"/>before choice if you use #[message.payload.size()>0]
So the full code will be something as follows :-
<flow name="post:/chkdb:application/json:chkdbapi-config">
<logger message="========json payload==>>>>==== #[message.payload]" level="INFO" doc:name="Logger"/>
<!-- <json:json-to-object-transformer returnClass="java.lang.Object" doc:name="JSON to Object"/> --> <!-- incase you use #[message.payload.size()>0] in your choice -->
<!-- db call returns the payload-->
<set-variable variableName="GGG_Number" value="#[json:ggg]" doc:name="Variable"/>
<choice doc:name="Choice">
<when expression="#[message.payload.length()>0]">
<set-payload value="{"indicator":"True"}" mimeType="application/json" doc:name="Set Payload"/>
</when>
<otherwise>
<set-payload value="{"indicator":"False"}" mimeType="application/json" doc:name="Set Payload"/>
</otherwise>
</choice>
<logger message="=========after producing json output=======" level="INFO" doc:name="Logger"/>
</flow>
<flow name="post:/chkdb:application/xml:chkdbapi-config">
<logger message="========= xml payload======== #[message.payload]" level="INFO" doc:name="Logger"/>
<json:xml-to-json-transformer mimeType="application/json" doc:name="XML to JSON"/>
<flow-ref name="post:/chkdb:application/json:chkdbapi-config" doc:name="post:/chkdb:application/json:chkdbapi-config"/> <!-- Getting exception here -->
<logger message=" after subflow call ==== #[message.payload]" level="INFO" doc:name="Logger"/>
<json:json-to-xml-transformer mimeType="application/xml" doc:name="JSON to XML"/>
<logger message="after json to xml conversion" level="INFO" doc:name="Logger"/>
</flow>
I was trying to remove an attachment so that my outbound email only contains the payload. I used the attachment transformer but the attchments are still being sent even if I used "*" as the filter. I have placed it on the inbound and the outbound endpoint but the attchment is still appering on the email
<remove-attachment attachmentName=""*"" doc:name="Attachment"/>
<flow name="ocr_app_testFlow">
<pop3:inbound-endpoint host="mail.awh.com.au" user="knaufack" password="ocr123" responseTimeout="10000" doc:name="POP3"/>
<logger message="#[message.inboundProperties.subject]" level="INFO" doc:name="Logger"/>
<remove-attachment attachmentName="*" doc:name="Attachment"/>
<choice doc:name="Choice">
<when expression="#[wildcard('*Succeeded*',message.inboundProperties.subject)]">
<set-variable variableName="Subject" value="#[message.inboundProperties.subject]" doc:name="Variable"/>
<set-variable variableName="Warehouse" value="#[message.inboundProperties.subject.substring(40,43)]" doc:name="Variable"/>
<set-variable variableName="Order" value="#[message.inboundProperties.subject.substring(44,51)]" doc:name="Variable"/>
</when>
<otherwise>
<set-variable variableName="Subject" value="#[message.inboundProperties.subject]" doc:name="Variable"/>
<set-variable variableName="Warehouse" value="#[message.inboundProperties.subject.substring(37,40)]" doc:name="Variable"/>
<set-variable variableName="Order" value="#[message.inboundProperties.subject.substring(41,48)]" doc:name="Variable"/>
</otherwise>
</choice>
<logger message="#[flowVars.Order] from #[flowVars.Warehouse]" level="INFO" doc:name="Logger"/>
<set-payload value="Your Order #[flowVars.Order] from #[flowVars.Warehouse] Warehouse is imported succesfully. Please Verify" doc:name="Set Payload"/>
<remove-attachment attachmentName="*" doc:name="Attachment"/>
<choice doc:name="Choice">
<when expression="#[flowVars.Warehouse == 'ROC']">
<smtp:outbound-endpoint host="mail.awh.com.au" user="tupload" password="upload123" to="tupload#awh.com.au" from="AWH_Logistics_Integration" subject="AWH OCR Process Notification" responseTimeout="10000" doc:name="ROC Warehouse"/>
</when>
<otherwise>
<smtp:outbound-endpoint host="mail.awh.com.au" user="tupload" password="upload123" to="pauldominguez#awh.com.au" from="AWH_Logistics_Integration" subject="AWH OCR Process Notification" responseTimeout="10000" doc:name="SMTP"/>
</otherwise>
</choice>
</flow>
Add the attached transformer class to your project.
package org.awh.pfinder;
import org.mule.transport.email.transformers.ObjectToMimeMessage;
public class RemoveAttachmentTransformer extends ObjectToMimeMessage {
public RemoveAttachmentTransformer() {
super();
setUseInboundAttachments(false);
}
}
Add an SMTP connector and set that transformer as the outbound one:
Main flow: or FLOW A
<mule>
<flow name="GetQBClassesFlow1" doc:name="GetQBClassesFlow1" processingStrategy="synchronous">
<http:inbound-endpoint exchange-pattern="request-response" host="${hostname}" port="${port}" path="getClasses" doc:name="HTTP"/>
<flow-ref name="Authenticate-QB" doc:name="Flow Reference"/>
<logger message="=========Acc Token==========#[sessionVars['accessToken']]" level="INFO" doc:name="Logger"/>
<flow-ref name="GetQBClassesFlow2" doc:name="Flow Reference"/>
</flow>
<flow name="GetQBClassesFlow2" doc:name="GetQBClassesFlow2" processingStrategy="synchronous">
<logger message="=========Acc Token 2==========#[sessionVars['accessToken']]" level="INFO" doc:name="Logger"/>
</flow>
</mule>
Authentication: or FLOW B
<mule ...>
<quickbooks:config name="QBAuthenticate" consumerKey="${consumerKey}" consumerSecret="${consumerSecret}" doc:name="Quickbooks Online - Authenticate"/>
<flow name="Authenticate-QB" doc:name="Authenticate-QB" processingStrategy="synchronous">
<http:inbound-endpoint exchange-pattern="request-response" host="${hostname}" port="8989" doc:name="HTTP"/>
<quickbooks:auth-user config-ref="Authenticate"
accessTokenUrl="https://oauth.intuit.com/oauth/v1/get_access_token"
authorizationUrl="https://appcenter.intuit.com/Connect/Begin"
callbackUrl="http://${hostname}:8989/getQBAccessToken"
requestTokenUrl="https://oauth.intuit.com/oauth/v1/get_request_token"
doc:name="Authenticate user" requestTokenId="tenantId"/>
</flow>
<flow name="qbAccessToken" doc:name="getAccessToken" processingStrategy="synchronous">
<http:inbound-endpoint exchange-pattern="one-way" host="${hostname}" port="8989" path="getQBAccessToken" doc:name="Get Token"/>
<logger message="=========GET QB Accounts ============" level="INFO" doc:name="Logger"/>
<quickbooks:get-access-token config-ref="QBAuthenticate" doc:name="get access token"/>
<logger message="=========realmId==============#[message.payload.realmId]" level="INFO" doc:name="Logger"/>
<set-session-variable variableName="accessToken"
value="#[message.payload.accessToken]" doc:name="Set accessToken" />
<set-session-variable variableName="accessTokenSecret"
value="#[message.payload.accessTokenSecret]" doc:name="Set accessTokenSecret" />
<set-session-variable variableName="realmId"
value="#[message.payload.realmId]" doc:name="Set realmId" />
</flow>
</mule>
I have a FLOW called GetQBClassesFlow1(Main flow) which invokes another flow Authenticate-QB( authentication flow above), i.e.GetQBClassesFlow1 invokes Authenticate-QB, where Authenticate-QB waits for the user to enter details on login page, but before completion of Authenticate-QB flow, GetQBClassesFlow1 continues( suppose to wait to complete authenticate details page) which causes the issue. I want GetQBClassesFlow1 should wait for flow Authenticate-QB to complete. How can I handle this?
output:
INFO 2014-08-20 11:18:03,830 [[qbprojects].connector.http.mule.default.receiver.03] org.mule.api.processor.LoggerMessageProcessor: =========Acc Token==========null
INFO 2014-08-20 11:18:03,831 [[qbprojects].connector.http.mule.default.receiver.03] org.mule.api.processor.LoggerMessageProcessor: =========Acc Token 2==========null
INFO 2014-08-20 11:18:12,712 [[qbprojects].connector.http.mule.default.receiver.03] org.mule.api.processor.LoggerMessageProcessor: =========GET QB Accounts ============
INFO 2014-08-20 11:18:12,944 [[qbprojects].connector.http.mule.default.receiver.03] org.mule.api.processor.LoggerMessageProcessor: =========realmId==============1345020
The Authenticate-QB flow is designed to be called over HTTP by an end-user, in order to perform the OAuth2 dance.
Thus you can not invoke it with flow-ref. The authentication part is done out-of-band of whatever else your flows are doing.