How to pass Authorization Token to my backend service through WSO2 (API Manager) version 4.1.0? - api

I need to pass Authorization Token from API Manager (WSO2) to my Backend using policies like Header policy but it works for me only using cURL but not with UI.
curl -k -X 'GET'
'https://localhost:8243/test/1.0.0/support/get/55'
-H 'accept: /'
-H 'Authorization: Bearer gatewayToken
-H 'Authorization: Bearer BackendToken'
Screenshot of the result after adding Header policy

By default the authorization header is dropped from the API gateway after validating the request. So you can't send the same header here with multiple values. If you want to send a custom header in the UI, you can do this as follows.
In the API publisher click on the API and go to the API configuration section.
Click on the resource tab and select a HTTP method.
Under parameters, you can add a header. Then from the Swagger UI, you can set this header when trying out the request.
Using API policies in API Manager 4.1.0, you can add AddHeader policy and send any static headers to the backend services.

You should be able to achieve this with a custom Operation Policy and adding that to the inflow of the API.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="TokenExchange">
<property name="Custom" expression="get-property('transport', 'Custom')"/>
<property name="Authorization" expression="get-property('Custom')" scope="transport"/>
<property name="Custom" scope="transport" action="remove"/>
</sequence>
Here, you have to send the backend token with a different header value (Custom) and gateway will automatically forward it to the backend under the Authorization header.
You can refer [1] to get an idea about this flow. Since the mediation sequences are replaced with Operation policies in APIM 4.1.0, you will have to refer the doc [1] and create and apply the Operation policy accordingly.
[1] - https://apim.docs.wso2.com/en/4.0.0/deploy-and-publish/deploy-on-gateway/api-gateway/message-mediation/passing-a-custom-authorization-token-to-the-backend/#passing-a-custom-authorization-token-to-the-backend

Related

NPE in Keycloak internal token-exchange

I'm trying to achieve an internal token exchange in Keycloak 17.0.1, however, the server returns an unknown error (NullPointerException).
My scenario is: I have three microservices, A, B, and C. A calls B, which is an intermediate service that needs to call service C. So, I don't want to propagate the original token (A) to call (C). Instead, I want to exchange the token, so B makes a token-exchange request to Keycloak to get a new token and then calls service C.
What I have done:
I have a client "original" who has his own client-id/client-secret
I created another client "target" and configured the policy for token exchange, assuming the "original" client in that policy.
And finally the cURL call:
curl -L -X POST 'http://localhost:8080/realms/myrealm/protocol/openid-connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=target' \
--data-urlencode 'client_secret=<< TARGET SECRET >>' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'subject_token=<< ORIGINAL CLIENT TOKEN >>' \
--data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:refresh_token' \
--data-urlencode 'audience=original'
Response:
2022-04-19 16:05:16,154 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-37) Uncaught server error: java.lang.NullPointerException
at org.keycloak.protocol.oidc.TokenManager.attachAuthenticationSession(TokenManager.java:539)
at org.keycloak.protocol.oidc.DefaultTokenExchangeProvider.exchangeClientToOIDCClient(DefaultTokenExchangeProvider.java:336)
at org.keycloak.protocol.oidc.DefaultTokenExchangeProvider.exchangeClientToClient(DefaultTokenExchangeProvider.java:315)
at org.keycloak.protocol.oidc.DefaultTokenExchangeProvider.tokenExchange(DefaultTokenExchangeProvider.java:233)
at org.keycloak.protocol.oidc.DefaultTokenExchangeProvider.exchange(DefaultTokenExchangeProvider.java:123)
at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.tokenExchange(TokenEndpoint.java:789)
at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.processGrantRequest(TokenEndpoint.java:204)
at jdk.internal.reflect.GeneratedMethodAccessor344.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:152)
Am I missing something?
UPDATE
The only way I've managed it to work was to "force" a session to be created in Keycloak by using a "password" grant type in the request of client A. So, I created a user foo and got a token in this way:
POST http://localhost:{{keycloak_port}}/realms/{{keycloak_realm}}/protocol/openid-connect/token
Authorization: Basic original:12345
Content-Type: application/x-www-form-urlencoded
grant_type=password
&username=foo
&password=bar
This way, a session was created for the client original and the token exchange request for the target client did work.
I'm wondering if it is a correct approach, though.
client configuration
As I'm using client_credentials OAuth2.0 flow, I had to enable the "Use Refresh Tokens For Client Credentials Grant" in Keycloak (clients/settings/OpenID Connect Compatibility Modes) and then toggle the option mentioned earlier.
Although OAuth2.0 states that refresh_tokens should not be used in this flow, I could not find another solution to this.
See attached image for more details.

Centreon web API v2 endpoints return 500 - No route found

I run centreon 21.04 in a VM for some tests.
I imported the Centreon REST API v2 collection into Postman as described here.
Some endpoints work like:
POST /login
GET /logout
GET /configuration/icons
GET /monitoring/acknowledgements
GET /platform/topology
but most other endpoints return an error 500 with "No route found".
Example of response with the /centreon/api/latest/monitoring/hosts endpoint:
$ curl --location --request GET 'http://<VM_IP>:80/centreon/api/latest/monitoring/hosts' --header 'X-AUTH-TOKEN: mytoken'
{"code":500,"message":"No route found for 'GET /monitoring/hosts'"}
The X-AUTH-TOKEN header is set with the token retrieved via the /login endpoint.
I'm using the default admin user for which I enabled Reach API Configuration and Reach API Realtime in the web UI via Configuration > Users > Contacts/Users > admin > Centreon Authentication.
Any idea why this is not working ?
So apparently some endpoints only work in the beta version of the API for now, so make sure you use the /centreon/api/beta/ path in the URL

Download attachment from Circuit Conversation via REST API

I'd like to download an attachment from the conversation via REST API (Circuit Sandbox)
If I query the Conversation Item, I can see the attachments and within that the fileID. Then, if I am logged with a user account who is a member of the conversation, I can run the following to download the attachment or paste it in the browser where I am logged to the sandbox:
'''
start chrome https://circuitsandbox.net/rest/v2/fileapi?fileid=MyFileIdHere
'''
And that works. Is there a way to achieve the same with a Bot via REST?
A regular GET request will work.
curl https://circuitsandbox.net/rest/fileapi?fileid=<fileId> \
-H "Authorization: Bearer <ACCESS_TOKEN>"
and here is the REST notation.
GET rest/fileapi?fileid=<fileId> HTTP/1.1
Host: circuitsandbox.net
Authorization: Bearer <ACCESS_TOKEN>
The access token for a bot (client credentials grant) is obtained via OAuth 2.0:
curl https://circuitsandbox.net/oauth/token \
-d 'grant_type=client_credentials&client_id=<CLIENT_ID>&client_secret=<CLIENT_SECRET>&scope=READ_CONVERSATIONS,WRITE_CONVERSATIONS'
REST notation:
POST /oauth/token HTTP/1.1
Host: circuitsandbox.net
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=<CLIENT_ID>&client_secret=<CLIENT_SECRET>&scope=READ_CONVERSATIONS,WRITE_CONVERSATIONS'

Swagger/OpenAPI Bearer auth with custom header name

I'm defining (small parts of) an existing API (Samanage) using OpenAPI to assist with some integration work.
I need to authenticate using Bearer auth, but by sending the token in a header other than Authorize.
The server expects Bearer authentication in a header named X-Samanage-Authorization like this example:
curl -H "X-Samanage-Authorization: Bearer <TokenGoesHere>" -H 'Accept: application/vnd.samanage.v2.1+json' -H 'Content-Type: application/json' -X GET https://api.samanage.com/incidents.json
I'm aware of https://swagger.io/docs/specification/authentication/bearer-authentication/, but it doesn't seem to help me fully.
This (OpenAPI 3)
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
...
security:
- bearerAuth: []
Results in an authentication header named the default (Authorization)
curl -X GET "https://api.samanage.com/incidents/12341234.json" -H "accept: application/json" -H "Authorization: Bearer <TokenGoesHere>"
Which then fails (401).
I feel like I want this:
components:
securitySchemes:
bearerAuth:
type: http
name: X-Samanage-Authorization
in: header
scheme: bearer
But that fails validation in Swagger Editor as I believe a type of http doesn't allow the name component (like a type of apiKey would). I couldn't quite make full sense of the docs here to be honest.
I did read about Specification Extensions but being completely new to OpenAPI, I couldn't find any examples on how to actually implement what I need.
Any insight much appreciated!
type: http is for HTTP authentication as defined by RFC 7235 and the IANA HTTP Authentication Scheme Registry. HTTP authentication, by definition, uses the Authorization header.
To use a custom header name, you need to define it as an API key (type: apiKey):
components:
securitySchemes:
bearerAuth:
type: apiKey
name: X-Samanage-Authorization
in: header
Note that since it's a non-standard Bearer scheme, the clients will need to manually add the "Bearer " prefix to the token value. For example, when you click "Authorize" in Swagger UI, you'll need to enter "Bearer TOKEN" instead of just "TOKEN".

SET X-AUTH-TOKEN in WSO2 ESB

We need to set the http header property X-Auth-Token in ESB before sending it to endpoint. The endpoint authenticates this token.
When we X-Auth-Token in header property it's not working.
Can you suggest the way to set the X-Auth-Token property in http header in WSO2
You use the following config to do this. Make sure the scope is set to transport.
<property name="X-Auth-Token" scope="transport" value="XXXXX" />