401 Error, Mule while Username/Password are Correct - api

I am trying to use postman to call an API that I have deployed with Mule. I have downloaded this API from a trusted source (Collibra) and thus expect it to be in working condition.
The API Request:
http://localhost:8081/connect/dgc/export/asset?filter=name%20STARTS_WITH%20E
Here is the Basic Auth setup in one of the xml files.
<mule-ss:security-manager name ="authenticationManager" doc:name="Spring Security Provider">
<mule-ss:delegate-security-provider
name="memory-provider" delegate-ref="authenticationManager-common" />
</mule-ss:security-manager>
<spring:beans>
<ss:authentication-manager alias="authenticationManager-common">
<ss:authentication-provider>
<ss:user-service id="userService">
<ss:user name="${service.user}" password="${service.password}"
authorities="ROLE_ADMIN" />
</ss:user-service>
</ss:authentication-provider>
</ss:authentication-manager>
</spring:beans>
And here is the setting of the username/password in a properties file.
service.user=user
service.password=password
The following error appears when I make a postman GET request with the correct credentials.
Failed to connect/reconnect: Work Descriptor. Root Exception was: Unexpected response with status code: 401 was returned. Message was: {"statusCode":401,"titleMessage":"Not authorized","userMessage":"The user name or password is wrong. Try again."}
And here is the error that appears if I use the incorrect credentials.
Root Exception stack trace:
org.springframework.security.authentication.BadCredentialsException: Bad credentials
What could be going wrong to have the error appear when I am passing the correct credentials through the Basic Auth? I have double-checked the string with an online header generator and it is indeed correct.

It is difficult to troubleshoot without understanding the API implementation, but given the error with incorrect credentials seems to come from the Spring Security Manager and with the correct credentials it looks to be connecting to something else, it is possible that the API is calling some backend system or API and failing to authenticate to it.

Related

How to customise an error message generated by the Anypoint API manager standard policy?

There is an API running on the CloudHub (Mule 4.4) and protected with the standard SLA Rate Limit policy.
We have a requirement to provide a custom error message body instead of the default one generated by the policy when authentication fails.
The default error body returned by the policy looks like this:
{
"error": "Invalid client id or secret"
}
When I run the application in debugger in Studio, it is intercepting the exception and I can see that the error type produced by the policy is CLIENT-ID-ENFORCEMENT:INVALID_CREDENTIALS.
This as well indicates that the exception is reaching the Mule application itself. So, it must be a way to override the default handler with the custom one.
First, I've tried adding the handler for error type to HTTP request processing flow beside the other API Kit errors. It did not intercept the error.
Then, I've defined a separate error handler for the error type and set it as a "Default Error Handler" in the global configuration.
<configuration doc:name="Configuration" doc:id="7a7e22cd-2ee7-42ee-af15-eaf2693d72d9" defaultErrorHandler-ref="apiErrorHandler" />
<error-handler name="apiErrorHandler">
<on-error-propagate enableNotifications="true" logException="true" type="CLIENT-ID-ENFORCEMENT:*">
<ee:transform xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{message: "Unauthorised"}]]></ee:set-payload>
</ee:message>
</on-error-propagate>
</error-handler>
This didn't work as well.
Can you pls advise the right way to customise the error messages returned the standard SLA policy?
To be clear, I'm well aware that it is possible to code your own custom policy. But the intention is to keep the standard one and just customise the response for some error types.
This is not currently possible. Policies have to handle their own errors, they can not be intercepted in the flow.

Mule 4 HTTP Request Client to access OAuth 2 end point

There is an external service (lets say "https://external-service.com/service") which is secured by OAuth2. I have client ID (Lets say "123_my_client_id"), Secret ID ("324_mysecret") and the access token URL ( lets say "https://access-token.com/access-token") which returns me the token.
I want to access this service with my Mule 4 Http Request. I followed this https://docs.mulesoft.com/connectors/http/http-authentication#oauth2-client-credentials, but couldn't find any workable solution.
This can be done in Mule 3.9. but still struggling to set up this http request configuration for Mule 4. Can anyone please help to setup this request config .
In order to migrate the request authentication to Mule 4,the config now belongs in the http:request-connection component and the HTTP authentication configuration must be placed within an http:authentication component. This applies to all authentication types supported: basic, digest, NTLM and OAuth2.
From the example in the link provided:
<http:request-config name="HTTP_Request_Configuration"
host="some.api.com" port="80" basePath="/api/1.0">
<oauth:client-credentials-grant-type
clientId="your_client_id" clientSecret="your_client_secret"
tokenUrl="http://some.api.com/api/1.0/oauth/token"
scopes="access_user_details, read_user_files">
</oauth:client-credentials-grant-type>
</http:request-config>
Changes to something like:
<http:request-config name="HTTP_Request_Configuration">
<http:request-connection host="some.api.com" port="80">
<http:authentication>
<oauth:client-credentials-grant-type
clientId="your_client_id" clientSecret="your_client_secret"
tokenUrl="http://some.api.com/api/1.0/oauth/token" scopes="access_user_details, read_user_files" />
</http:authentication>
</http:request-connection>
</http:request-config>
Studio may complain about the oauth element, but it should start up fine. Just ignore it.
To anyone wondering how to do that through the user interface, it is pretty easy but the mulesoft documentation could be more clear.
I ended up finding out how to do it, here's the step-by-step process :
create your HTTP Request processor
choose the display name you want in "Display Name:"
choose the desired method in the "Method:" dropdown menu (ex. : GET)
set the path to the endpoint you wish to reach in "Path:"
then create a HTTP_Request_Configuration, by clicking the "+" on the right of "Configuration:" in the "Basic Settings" box
In the configuration window, set up the protocol (HTTP or HTTPS)
In the configuration window, set up the port (80 for HTTP and 443 for HTTPS)
In the configuration window, set up the host (ex. : www.url-to-request.com)
Scroll down to find the "Authentication:" dropdown menu
Choose "Client credentials grant type"
Set up you client-id and client-secret
Set up scopes if required by the application provider
And finally set up the "Token url" (url given by the application provider to retrieve the oauth identification token)
Click OK
After doing this, your oauth2 request should be working. As said in the mulesoft documentation, each time you run the project, a token will be automatically generated. You then can execute as many request as you want without worrying about the authentication anymore.

When using Quickbooks Online API Collections for Postman I'm getting an Authentication Error

I've gone through the steps shown here https://developer.intuit.com/docs/0100_quickbooks_online/0100_essentials/000300_your_first_request/first_request_with_postman#/Configuring_the_Postman_Authorization_header-1500 to use Quickbook's API Collection for Postman.
In Postman, I was successfully able to get a new access token. I also updated the {{baseurl}} to be "sandbox-quickbooks.api.intuit.com", and updated the {{companyid}} (aka the "RealmId") to be the appropriate value as shown in the "Manage Sandboxes" page of the developer site (i.e. https://developer.intuit.com/v2/ui#/sandbox).
BUT when I click "send" on the "Customer-ReadById" query (or any other query in the collection), I get the following Authentication error:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3" time="2017-08-16T11:52:00.611-07:00">
<Fault type="AuthenticationFault">
<Error code="100">
<Message>General Authentication Error</Message>
<Detail>AuthenticationErrorGeneral: SRV-110-Authentication Failure , statusCode: 401</Detail>
</Error>
</Fault>
</IntuitResponse>
My next step was to verify that I can query my sandbox using the OAuth 2.0 Playground tool on the developers site, which I can indeed do.
My questions then are: why am I getting this authentication error in Postman? Am I missing a step? Or has something changed in the Quickbooks Online API that has not yet been documented?
EDIT: I've managed to resolve my own issue after a decent amount of trial and error, and with a hint based on a response in the Quickbooks Online help area.
For those who may find this useful, my solution was to request a new access token (click "Get New Access Token" in Postman) and updated the "Scope" section to include "openid" such that the space delimited list read:
com.intuit.quickbooks.accounting openid profile email phone address
Using this new token with the updated scope allowed me to get the desired results.
I had the same problem but I resolved it differently. My issue was that in the requested token, the default to "Add token to" is URL, but it seems that the API requires the token to be in an Authorization header. Changing this to "Header" does just that.
For the "Customer-ReadById" endpoint, the only scope that should be necessary is com.intuit.quickbooks.accounting. My guess is you changed it to Header in your trial and error.

REST Client step in Pentaho DI (Kettle) says I do not have permission to API

I am using version 5.1 of Pentaho DI (Kettle) and am having an issue with the "Rest Client" step. The step executes properly and successfully, but the result says I do not have permission to use the API. I have confirmed in another tool that I do have permission. I have entered my login information on the Authentication tab and have built my URL to include my token.
What am I missing?
ADDITIONAL INFO: I am having the same issue with the "HTTP Post" step. The status being returned from the API is 403.
403 is "Forbidden". Check that you have the correct credentials to access the webservice. The request went through and the server rejected sending the response because username/password are not correct or otherwise the user does not have permissions for that request. Can you see the response correctly in a browser when you enter EXACTLY the same credentials? To avoid active browser sessions masking the real issue I'd test it on incognito/private browsing mode on the browser.

WSO2 API Manager - "Make this the default version" causes authentication errors?

I have an API that works no problem providing the "Make this the default version" checkbox isnt checked, once checked I get this error back
<ams:fault
xmlns:ams="http://wso2.org/apimanager/security">
<ams:code>900906</ams:code>
<ams:message>No matching resource found in the API for the given request</ams:message>
<ams:description>Access failure for API: xxxx/xxxx, version: v0.1 with key: xxxxxx</ams:description>
</ams:fault>
Is there something I have missed at all?
Thanks,
Ash.
EDIT - Extra Detail and Logs
TID[-1234] [AM] [2014-07-10 13:05:56,238] ERROR
{org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler}
- API authentication failure org.wso2.carbon.apimgt.gateway.handlers.security.oauth.OAuthAuthenticator.authenticate(OAuthAuthenticator.java:157)
org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.handleRequest(APIAuthenticationHandler.java:92)
org.apache.synapse.rest.API.process(API.java:285)
org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:83)
org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:64)
org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:220)
org.apache.synapse.core.axis2.SynapseMessageReceiver.receive(SynapseMessageReceiver.java:83)
org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
org.apache.synapse.transport.passthru.ServerWorker.processNonEntityEnclosingRESTHandler(ServerWorker.java:344)
org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:168)
org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:744)
Please save and publish the API once you made the change to the API. This may be causing the issue.
Once you have published you should see 2 sets of production url (one with the version and one without the version). Please check if the same is available in the API store for your API.
You'll first want to turn on wire logs in that environment by editing your ../repository/conf/log4j.properties file and restarting the service. This will allow you to see the request headers for both the initial request to the gateway and the request from the gateway to itself (or other gateways in your cluster) since that's how requests to a default API version are resolved. This can help you identify whether your Authorization header values are actually making it to the authentication handler.
After you take a look at this, note that when you publish an API with a default version, you're actually creating (or updating) two separate synapse configurations for the API: a versioned configuration and an unversioned configuration. The portion of the latter's definition that you need to check is:
<else>
<header name="WSO2_AM_API_DEFAULT_VERSION" scope="transport" value="true"/>
<property name="uri.var.portnum" expression="get-property('https.nio.port')"/>
<send>
<endpoint>
<http uri-template="https://localhost:{uri.var.portnum}/myApi/v1">
<timeout>
<duration>60000</duration>
<responseAction>fault</responseAction>
</timeout>
</http>
</endpoint>
</send>
</else>
By default, the newly generated definition for the default version attempts to send the request to localhost, which may not be what you want. Check at ../repository/deployment/synapse-configs/default/api and make sure that this definition is correct.
Since it looks like this is actually an authentication error, you should also test a new subscription. Create a new application with some subscriber, subscribe to the API, and generate new access tokens. I wouldn't understand why (since setting a default version doesn't create a new API entry in the AM_API table) but this could possibly be due to the access token credentials being invalid for the default version, and generating new tokens should (in theory) test against this.