0
votes

Having a bizarre issue in Mule 4.3 (Anypoint 7.5.1) using the HTTP Connector to POST to a url to and get back an access token that will be subsequently used in another call for bearer authentication.

The returning access_token when using the Mule4 HTTP Request is 1277 characters, whereas every other tool I have tried, Curl, Postman, Advanced Rest Client all return an access_token that is 1266 characters.

The larger token (from Mule) is not valid and fails subsequent requests with a 401. Wheres the smaller token (from Curl/Postman) is valid and can be copied into the Mule flow and pass authentication.

I am at a complete loss as to where the extra 11 characters in the access_token are coming from.

This is the request in Mule

<http:request
    method="POST"
    doc:name="get-authToken"
    doc:id="e7a7fe05-4085-4d43-a2ee-998364ea7518"
    config-ref="Workforce_Auth_Configuration"
    path="/connect/token"
    sendBodyMode="ALWAYS" target="authToken" targetValue="#[message]" requestStreamingMode="NEVER" outputMimeType="application/json" outputEncoding="UTF-8">
    <http:body><![CDATA[#[%dw 2.0
output application/x-www-form-urlencoded
---
{
    client_id: Mule::p("secure::workforce-api.client_id"),
    client_secret: Mule::p("secure::workforce-api.client_secret"),
    grant_type: "password",
    scope: "openid profile api offline_access",
    username: Mule::p("secure::workforce-api.username"),
    password: Mule::p("secure::workforce-api.password")
}]]]></http:body>
    <http:headers ><![CDATA[#[output application/java
---
{
    "Accept-Encoding" : "gzip, deflate, br"
}]]]></http:headers>
</http:request>

<logger level="INFO" doc:name="Logger" doc:id="afafbd11-1081-4525-a32d-ef1a98284d81" message="********* GOT AUTH TOKEN *********"/>
<logger level="INFO" doc:name="authToken" doc:id="9f03d5dc-fe8f-40b1-be11-b0ea60526703" message="#[vars.authToken.payload.access_token]"/>
<logger level="INFO" doc:name="sizeOf" doc:id="df6879cf-ab78-4823-a6bb-072e84eb8c64" message='#["********* SIZE OF AUTH TOKEN " ++ sizeOf(vars.authToken.payload.access_token) as String]'/>

The logs end up with

LoggerMessageProcessor: ********* GOT AUTH TOKEN *********
LoggerMessageProcessor: eyJhbGciOiJSUzI1NiIsImtpZCI6ImNkYTlkODUyYjdmNGIyNWFlYTZlMjg4NmM2MGQzMTRlIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1OTQ4MjI2MTcsImV4cCI6MTU5NDgyNjIxNywiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5leHByZXNzcHJvcy5jb206NDQzIiwiYXVkIjpbImh0dHBzOi8vYWNjb3VudHMuZXhwcmVzc3Byb3MuY29tOjQ0My9yZXNvdXJjZXMiLCJhcGkiXSwiY2xpZW50X2lkIjoiZXhwcmVzc21vYmlsZSIsInN1YiI6ImQ4YjQ3OGJhLWQyMGUtNDljMi0zMTIzLTA4ZDRjOGQ4MjcyZCIsImF1dGhfdGltZSI6MTU5NDgyMjYxNywiaWRwIjoibG9jYWwiLCJuYW1lIjoia2xydXNzZWxsIiwiZGlzcGxheV9uYW1lIjoiS3Jpc3RvcGhlciBSdXNzZWxsIiwidXNlcl90eXBlIjoiV29ya2ZvcmNlIiwiZ2l2ZW5fbmFtZSI6IktyaXN0b3BoZXIiLCJmYW1pbHlfbmFtZSI6IlJ1c3NlbGwiLCJlbWFpbCI6ImtydXNzb2tjQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoiVHJ1ZSIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL21vYmlsZXBob25lIjoiNDA1Mjg2NDQ0NSIsIm1vYmlsZXBob25lX3ZlcmlmaWVkIjoiVHJ1ZSIsImlzX2FjdGl2ZSI6IlRydWUiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwiYXBpIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbInB3ZCJdfQ.QwREQmLZ2s7UjRwW07SkgFvvLu8fLgYmLag-XALBTM60y74oJpRLSq9vnDP8KEF33ATKiKxJP-A_lPqYWTHSAmF9HJDBA_KqIQ8Igo-9Vd5Xl_nU2ldcM5DBcoOrbudROYII70cmF7njU937EOcJ4STJ2cvTJnKZ8_xmT1A1cr5B7_IxsTMQJ2IzfCYh62RMks3_dqqZb5LZ4z4w7KTHZAwYtBFF6EdaLT1cNDvn2mHacMqKwRrrjOTDIJgx-3vNlkkCgbknYtiNbZhCrYKUzZgq-hS6pI-JFXckmHCP4U2Ohhw33TzUbRrEiC_8KXDSoK1lNDHNpIND2bZX_WuLuw
LoggerMessageProcessor: ********* SIZE OF AUTH TOKEN 1277

The request returns a json object that looks like

{
    "access_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6ImNkYTlkODUyYjdmNGIyNWFlYTZlMjg4NmM2MGQzMTRlIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1OTQ4MjI2MTcsImV4cCI6MTU5NDgyNjIxNywiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5leHByZXNzcHJvcy5jb206NDQzIiwiYXVkIjpbImh0dHBzOi8vYWNjb3VudHMuZXhwcmVzc3Byb3MuY29tOjQ0My9yZXNvdXJjZXMiLCJhcGkiXSwiY2xpZW50X2lkIjoiZXhwcmVzc21vYmlsZSIsInN1YiI6ImQ4YjQ3OGJhLWQyMGUtNDljMi0zMTIzLTA4ZDRjOGQ4MjcyZCIsImF1dGhfdGltZSI6MTU5NDgyMjYxNywiaWRwIjoibG9jYWwiLCJuYW1lIjoia2xydXNzZWxsIiwiZGlzcGxheV9uYW1lIjoiS3Jpc3RvcGhlciBSdXNzZWxsIiwidXNlcl90eXBlIjoiV29ya2ZvcmNlIiwiZ2l2ZW5fbmFtZSI6IktyaXN0b3BoZXIiLCJmYW1pbHlfbmFtZSI6IlJ1c3NlbGwiLCJlbWFpbCI6ImtydXNzb2tjQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoiVHJ1ZSIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL21vYmlsZXBob25lIjoiNDA1Mjg2NDQ0NSIsIm1vYmlsZXBob25lX3ZlcmlmaWVkIjoiVHJ1ZSIsImlzX2FjdGl2ZSI6IlRydWUiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwiYXBpIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbInB3ZCJdfQ.QwREQmLZ2s7UjRwW07SkgFvvLu8fLgYmLag-XALBTM60y74oJpRLSq9vnDP8KEF33ATKiKxJP-A_lPqYWTHSAmF9HJDBA_KqIQ8Igo-9Vd5Xl_nU2ldcM5DBcoOrbudROYII70cmF7njU937EOcJ4STJ2cvTJnKZ8_xmT1A1cr5B7_IxsTMQJ2IzfCYh62RMks3_dqqZb5LZ4z4w7KTHZAwYtBFF6EdaLT1cNDvn2mHacMqKwRrrjOTDIJgx-3vNlkkCgbknYtiNbZhCrYKUzZgq-hS6pI-JFXckmHCP4U2Ohhw33TzUbRrEiC_8KXDSoK1lNDHNpIND2bZX_WuLuw",
    "expires_in" : 3600,
    "token_type" : "Bearer",
    "refresh_token" : "2fcacafc7f850f5812110a921302aab08c1c8124b7d0505691bba34c969210a2",
    "scope" : "api offline_access openid profile"
}

Extracting the access token, you can see that it is 1277 characters, which confirms the log entry.

Running the same request in Curl

curl --location --request POST 'https://***************/connect/token' 
--header 'Content-Type: application/x-www-form-urlencoded' 
--data-urlencode 'client_id=***************' 
--data-urlencode 'client_secret=***************' 
--data-urlencode 'grant_type=password' 
--data-urlencode 'scope=openid profile api offline_access' 
--data-urlencode 'username=***************' 
--data-urlencode 'password=***************'

Returns the following JSON

{"access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6ImNkYTlkODUyYjdmNGIyNWFlYTZlMjg4NmM2MGQzMTRlIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1OTQ4MjQ4NzcsImV4cCI6MTU5NDgyODQ3NywiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5leHByZXNzcHJvcy5jb20iLCJhdWQiOlsiaHR0cHM6Ly9hY2NvdW50cy5leHByZXNzcHJvcy5jb20vcmVzb3VyY2VzIiwiYXBpIl0sImNsaWVudF9pZCI6ImV4cHJlc3Ntb2JpbGUiLCJzdWIiOiJkOGI0NzhiYS1kMjBlLTQ5YzItMzEyMy0wOGQ0YzhkODI3MmQiLCJhdXRoX3RpbWUiOjE1OTQ4MjQ4NzcsImlkcCI6ImxvY2FsIiwibmFtZSI6ImtscnVzc2VsbCIsImRpc3BsYXlfbmFtZSI6IktyaXN0b3BoZXIgUnVzc2VsbCIsInVzZXJfdHlwZSI6Ildvcmtmb3JjZSIsImdpdmVuX25hbWUiOiJLcmlzdG9waGVyIiwiZmFtaWx5X25hbWUiOiJSdXNzZWxsIiwiZW1haWwiOiJrcnVzc29rY0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6IlRydWUiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9tb2JpbGVwaG9uZSI6IjQwNTI4NjQ0NDUiLCJtb2JpbGVwaG9uZV92ZXJpZmllZCI6IlRydWUiLCJpc19hY3RpdmUiOiJUcnVlIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsImFwaSIsIm9mZmxpbmVfYWNjZXNzIl0sImFtciI6WyJwd2QiXX0.H9TEAtoKdXkHlcCMDSn_yVKLigF0m-OhUJpnQE202QSEUkmwPJqU28-Dy8neJen6gHpqChZ-nuQmffTONrelQRG6ASh9lO9jiA8_9AzWeJ54eHBF52sSsf36E149MAyDd9yK-K2Umzfk9U9Ob9bW0OX04ih4wvTo7X-lAifk9P4SZrjRgYsVL9IGumSMI6G3EFrshHORuYqL2QjhRVtaCr_A9cAieCzarztEjyvEIYCPHmkxY-P0xAQvhnrplEBbqvoGTajEuDeuCPQ4cSeM1LSYjJpKnST46zfkUoBc-7aztusWnvCF7zbzLleDN7CcvIn8-3JnXqNt-GO_Al5plA","expires_in":3600,"token_type":"Bearer","refresh_token":"311de44f613b547efc9172d3d3d6e7f587706d77804468a426954ef19d9e3f62","scope":"api offline_access openid profile"}

Extracting the access_token here shows it is 1266 characters. If I copy this token and use in it in the subsequent Mule Requests, the requests are authorized and proceed as expected.

I thought that this could be an encoding issue, so I set the outputMimeType to application/json and the outputEncoding to "UTF-8", but it does not seem to make a difference.

Any thoughts on what could be causing this?

EDIT

After the recommendation to enable Wire Logging, I noticed that the content-lengths are different.

The Mule4 content-length is 171, whereas Curl and Postman are 177. It looks like Mule is converting the scope from this script

%dw 2.0
output application/x-www-form-urlencoded
---
{
    client_id: Mule::p("secure::workforce-api.client_id"),
    client_secret: Mule::p("secure::workforce-api.client_secret"),
    grant_type: "password",
    scope: "openid profile api offline_access",
    username: Mule::p("secure::workforce-api.username"),
    password: Mule::p("secure::workforce-api.password")
}

to scope=openid+profile+api+offline_access

whereas Curl and Postman are using scope=openid%20profile%20api%20offline_access.

Could this be the issue?

If I try to make Mule4 to use the %20 in place of the '+', it turns into scope=openid%2520profile%2520api%2520offline_access which then gives me an invalid scope error.

EDIT

I don't think that is the issue. I stripped the profile down to just api and compared the results.

This time the content-lengths on the request are the same, however the access_tokens are still different by 11 characters.

The Curl/Postman token works whereas the Mule one does not.

1

1 Answers

0
votes

Enable HTTP wire logging in the Mule 4 application and use verbose (-v) in the curl command line to compare both requests and responses raw. There might be some small difference in the requests. Also compare the headers in both.

Be sure to use the latest version of the HTTP connector just in case.

UPDATE:

Based on this new comment

scope=openid+profile+api+offline_access

whereas Curl and Postman are using scope=openid%20profile%20api%20offline_access.

It looks like DataWeave is using this interpretation of URL encoding for forms while Curl is using percent encoding. It is a bit unclear but seems that both are valid.

I don't see any option to change the way it is encoding. It is a hack but you could replace the plus signs as text and see if that helps:

%dw 2.0
output text/plain
---
write({
    password: "xxx",
    scope: "openid profile api offline_access"
}, "application/x-www-form-urlencoded") replace "+" with ("%20")