Error - Failed to add 'SAP-Connectivity-Authentication' header for on-premise connectivity - sap-cloud-platform

I am connecting an On-premise S/4 HANA with SAP Cloud Platform trial account. I am using SAP Cloud SDK to fetch all Business Partners from S/4 HANA.
My Cloud Connector is set
My Destination at Sub-Account level is set and can ping to my on-premise system
My Service instances - XSUAA/Destination/Connectivity is set with the application
But I have the following error
Failed to add 'SAP-Connectivity-Authentication' header for on-premise connectivity: no JWT bearer found in the 'Authorization' header of the request. Continuing without a header. Connecting to on-premise systems may not be possible
The code which I am using is -
final List<BusinessPartner> businessPartners =
new DefaultBusinessPartnerService()
.getAllBusinessPartner()
.select(BusinessPartner.BUSINESS_PARTNER)
.execute(destination);
It seems AppRouter is the recommended for Authorization and Access and hence I tried implementing one- but my approuter shows - Not Found
Approuter App -Name - approuter-demo
Below is the xs-app.json
{
"routes": [
{
"source": "^/s4ext/(.*)",
"target": "/s4ext/$1",
"destination": "******"
}
]
}
The Manifest file is as below:
---
applications:
- name: approuter-demo
routes:
- route: approuter-demo-*****trial.cfapps.eu10.hana.ondemand.com
path: approuter
memory: 128M
env:
TENANT_HOST_PATTERN: 'approuter-demo-(.*).cfapps.eu10.hana.ondemand.com'
destinations: '[{"name":"******", "url" :"https://s4ext-***.cfapps.eu10.hana.ondemand.com", "forwardAuthToken": true }]'
services:
- xsuaa-demo
- connectivity-demo
- destination-demo
Kindly guide me. Thanks.

Your destination type might be wrong. The authorization header is set via the destination.
Try other types in sap cp -> connectivity.

Reading your question again I can identify two issues:
This error message in your log:
Failed to add 'SAP-Connectivity-Authentication' header for on-premise connectivity: no JWT bearer found in the 'Authorization' header of the request. Continuing without a header. Connecting to on-premise systems may not be possible
It may be that this error message is actually superfluous and hence indicating a problem which is actually none. In your case this header is possibly not necessary and the SAP Cloud SDK should not try to add it. But in any case, this will not influence the actual connection, so this error message is at most confusing, but not harmful in the sense of altering functionality.
Still, I am asking you to add the stack trace of this exception to your question to be very sure here.
Your app router shows "Not Found":
Here I am missing more information. When does what exactly show "Not Found"? Is it that your browser cannot find your app router, or can your app router not find the target URL of the application?

Related

Using Keycloak for defining subjects in policies in Eclispe Ditto

My current use case is: I have a frontend application where a user is logged in via Keycloak. I would like to implement some parts of the Ditto HTTP API in this frontend (https://www.eclipse.org/ditto/http-api-doc.html).
For example I want to create policies (https://www.eclipse.org/ditto/basic-policy.html) for authorization. I've read in the documentation that one can use an OpenID Connect compliant provider and the form is : (https://www.eclipse.org/ditto/basic-policy.html#who-can-be-addressed).
There's basic auth example at the bottom of the page, it seems to use the username in this case.
{
"policyId": "my.namespace:policy-a",
"entries": {
"owner": {
"subjects": {
"nginx:ditto": {
"type": "nginx basic auth user"
}
},
...
}
My question is: What exactly would be the sub-claim if I want to use Keycloak? Is it also the username of the user I want to grant rights to? And how would I get this in my frontend where I want to specify the policy for sending it to Ditto afterwards?
UPDATE 1:
I tried to enable keycloak authentication in Ditto like suggested below and as stated here: https://www.eclipse.org/ditto/installation-operating.html#openid-connect
Because I'm running Ditto with Docker Compose, I added the following line as an environment variable in ditto/deployment/docker/docker-compose.yml in line 136: - Dditto.gateway.authentication.oauth.openid-connect-issuers.keycloak=http://localhost:8090/auth/realms/twin
This URL is the same as in the issuer claim of my token which I'm receiving from keycloak.
Now if I try to make for example a post request with Postman to {{basePath}}/things I get the following error:
<html>
<head>
<title>401 Authorization Required</title>
</head>
<body bgcolor="white">
<center>
<h1>401 Authorization Required</h1>
</center>
<hr>
<center>nginx/1.13.12</center>
</body>
</html>
I chose Bearer Token as Auth in Postman and pasted a fresh token. Basic Auth with the default ditto user is still working.
Do I have to specify the new subject/my user in Ditto before?
UPDATE 2:
I managed to turn basic auth in nginx off by commenting out "auth_basic" and "auth_basic_user_file" in nginx.conf!
It seems to be forwarded to Ditto now, because now I get the following error with Postman:
{
"status": 401,
"error": "gateway:jwt.issuer.notsupported",
"message": "The JWT issuer 'localhost:8090/auth/realms/twin' is not supported.",
"description": "Check if your JWT is correct."
}
UPDATE 3:
My configuration in gateway.conf looks now like this:
oauth {
protocol = "http"
openid-connect-issuers = {
keycloak = "localhost:8090/auth/realms/twin"
}
}
I also tried to add these two lines in the docker-compose.yml:
- Dditto.gateway.authentication.oauth.protocol=http
- Dditto.gateway.authentication.oauth.openid-connect-issuers.keycloak=localhost:8090/auth/realms/twin
Unfortunately I still had no luck, same error as above :/ It seems like an user had a similar problem with keycloak before (https://gitter.im/eclipse/ditto?at=5de3ff186a85195b9edcb1a6), but sadly he mentioned no solution.
EDIT: It turns out that I specified these variables in the wrong way, the correct solution is to add them as part of command: java ... more info here
UPDATE 4:
I tried to build Ditto locally instead of using the latest docker images and I think I might be one step further now, it seems like my oauth config is working. I get now:
{
"status": 503,
"error": "gateway:publickey.provider.unavailable",
"message": "The public key provider is not available.",
"description": "If after retry it is still unavailable, please contact the service team."
}
The error message from the log is:
gateway_1 | 2020-11-05 15:33:18,669 WARN [] o.e.d.s.g.s.a.j.DittoPublicKeyProvider - Got Exception from discovery endpoint <http://localhost:8090/auth/realms/twin/.well-known/openid-configuration>.
gateway_1 | akka.stream.StreamTcpException: Tcp command [Connect(localhost:8090,None,List(),Some(10 seconds),true)] failed because of java.net.ConnectException: Connection refused
gateway_1 | Caused by: java.net.ConnectException: Connection refused
...
gateway_1 | java.util.concurrent.CompletionException: org.eclipse.ditto.services.gateway.security.authentication.jwt.PublicKeyProviderUnavailableException [message='The public key provider is not available.', errorCode=gateway:publickey.provider.unavailable, statusCode=SERVICE_UNAVAILABLE, description='If after retry it is still unavailable, please contact the service team.', href=null, dittoHeaders=ImmutableDittoHeaders [{}]]
...
gateway_1 | Caused by: org.eclipse.ditto.services.gateway.security.authentication.jwt.PublicKeyProviderUnavailableException [message='The public key provider is not available.', errorCode=gateway:publickey.provider.unavailable, statusCode=SERVICE_UNAVAILABLE, description='If after retry it is still unavailable, please contact the service team.', href=null, dittoHeaders=ImmutableDittoHeaders [{}]]
...
gateway_1 | Caused by: akka.stream.StreamTcpException: Tcp command [Connect(localhost:8090,None,List(),Some(10 seconds),true)] failed because of java.net.ConnectException: Connection refused
gateway_1 | Caused by: java.net.ConnectException: Connection refused
My keyloak is definitely running, I'm able to get tokens. If I'm opening http://localhost:8090/auth/realms/twin/.well-known/openid-configuration which is in the first error message, I'm able to see my openid-configuration from keycloak config.
Edit: It seems that my gateway container cannot reach my keycloak container, will try to figure this out.
FINAL UPDATE:
Unreachable keycloak docker container from the gateway docker container was the issue. I'm now using traefik:
Keycloak container has the following alias: keycloak.localhost
Oauth configuration in the gateway looks like this:
oauth {
protocol = "http"
openid-connect-issuers = {
keycloak = "keycloak.localhost/auth/realms/twin"
}
}
Now the gateway can find the keycloak container via the alias and I can still use the keycloak admin ui from my localhoast: http://keycloak.localhost:8090/auth/admin/
Additional info: Traefic Blog
What exactly would be the sub-claim if I want to use Keycloak?
Keycloak provides you a JWT.
A JWT is an encrypted JSON which contains multiple fields called "claims". You can check how your token looks like by visiting https://jwt.io and pasting your token there. One of those fields is called sub. This is the sub claim.
To enable your keycloak authentication in eclipse ditto you need to add the issuer to the ditto configuration.
An example can be founde here.
The address must match the URL in the issuer claim of your JWT token.
ditto.gateway.authentication {
oauth {
protocol = "http"
openid-connect-issuers = {
some-name = "localhost:8090/auth/realms/twin"
}
}
}
Is it also the username of the user I want to grant rights to?
In eclipse ditto there is not really a concept of "user names". Eclipse ditto authentication is based on authorization subjects. For the basic authentication example you provided, the authorization subject which is generated within ditto is nginx:ditto.
For JWT authentication the authorization subject is generated as a combination of the name for the open id connect issuer which you configured (in my case some-name) and the value of the sub claim. An authorization subject could look like this: some-name:8d078113-3ee5-4dbf-8db1-eb1a6cf0fe81.
And how would I get this in my frontend where I want to specify the policy for sending it to Ditto afterwards?
I'm not sure if I understand the question correctly. If you mean how to authenticate your frontend HTTP requests to eclipse ditto, you need to provide the JWT to eclipse ditto by adding it to the authorization header of your HTTP requests in the following form:
authorization: Bearer yourJWT
If you mean how you would know the sub claim of a JWT, you need to parse the JWT to a JSON object and then read the sub claim out of the payload section.

GET request using Azure app services and Intel Edison

I wanted to read data from an azure app service's easy tables using REST API to an Intel Edison. Before I did the same using Azure Mobile Services and my code was this. PS: I'm programming the device by the Arduino IDE.
void send_request()
{
Serial.println("\nconnecting...");
if (client.connect(server, 80)) {
// POST URI
sprintf(buffer, "GET /tables/%s HTTP/1.1", table_name);
client.println(buffer);
// Host header
sprintf(buffer, "Host: %s", server);
client.println(buffer);
// Azure Mobile Services application key
sprintf(buffer, "X-ZUMO-APPLICATION: %s", ams_key);
client.println(buffer);
// JSON content type
client.println("Content-Type: application/json");
client.print("Content-Length: ");
client.println(strlen(buffer));
// End of headers
client.println();
// Request body
client.println(buffer);
}
else {
Serial.println("connection failed");
}
}
where server name was "genesis-iot-control.azure-mobile.net";
but now authentication has changed and mobile service has been replaced by app service. How can I access them using REST API on Intel Edison?
I had followed this lead but with no solutions.
Any kind of help is appreciated.
The Application Key mechanism has been removed from Mobile Apps.
You'll need to implement-your-own-header check.
See this article for more:
https://github.com/Azure/azure-mobile-apps-net-server/wiki/Implementing-Application-Key
In essence, you send a X-YOUR-CUSTOM-HEADER: SeCreT= from your Edison and check its value against an Application Setting (defined in the Portal) in your Node/C# Mobile App backend code.
Yes, they should have kept the old mechanism going, disable it by default but allow us to turn it back on with an application setting.
An alternative to that would be to either get a Bearer token from Azure AD and use that with Authorization: Bearer ToKen= (but that's eventually going to expire anyway unless you also take care of refreshing it), or build another Web App (or API endpoint in your current one) that you send a secret to, goes out to Azure AD and hands you the Bearer token.
OR if you're really in for a very entertaining afternoon, do the OAuth dance from your Edison!
A curl sample here:
https://ahmetalpbalkan.com/blog/azure-rest-api-with-oauth2/
For a tiny 2KB memory device (like Arduino Uno), storing both Bearer token and refresh token in memory is already game over.
I'd be very interested to learn if anyone has a better/more efficient/more secure approach to do authentication from microcontrollers with Mobile Apps.
Example - using X-SECRET as your custom authentication header:
// Todoitem.js
var azureMobileApps = require('azure-mobile-apps');
// Create a new table definition
var table = azureMobileApps.table();
// Execute only if x-secret header matches our secret
table.read(function (context) {
// All header names are in lowercase in context.req.headers
console.info('Got x-secret header with value: ' +
context.req.headers['x-secret']);
if (context.req.headers['x-secret'] == process.env.SECRET) {
console.info('Secret matches value in App Settings.');
return context.execute();
}
});
// Removed CREATE, UPDATE, DELETE definitions for brevity.
// YOU NEED TO PROTECT THOSE METHODS AS WELL!
// Finally, export the table to the Azure Mobile Apps SDK - it can be
// read using the azureMobileApps.tables.import(path) method
module.exports = table;
Behavior as seen from curl (needless to say you should use HTTPS if your Edison can do that):
$ curl -s -i http://{mobileapp}.azurewebsites.net/tables/todoitem \
-H "ZUMO-API-VERSION: 2.0.0"
HTTP/1.1 404 Not Found
...
X-Powered-By: Express
{"error":"The item does not exist"}
$ curl -s -i http://{mobileapp}.azurewebsites.net/tables/todoitem \
-H "ZUMO-API-VERSION: 2.0.0" \
-H "X-SECRET: SeCr3T="
HTTP/1.1 200 OK
...
X-Powered-By: Express
[
{
"id": "40b996d6-ec7f-4188-a310-0f02808e7093",
"createdAt": "2016-08-31T11:30:11.955Z",
...
"Yo_node":"Sup"
}
]
Using App Service Editor (Monaco / Visual Studio Online Editor) to code and check output - https://{mobileapp}.scm.azurewebsites.net/dev

Spring security rest plugin: token based authentiction

I am trying to get successfully integrate Spring security rest plugin
But I am constantly failed,I am using the memcahed for token storage. Config.groovy Setup which I used to implement the plugin is :
//login end point url
grails.plugin.springsecurity.rest.login.active=true
grails.plugin.springsecurity.rest.login.endpointUrl='/api/login'
grails.plugin.springsecurity.rest.login.failureStatusCode='401'
//for memcached
grails.plugin.springsecurity.rest.token.storage.useMemcached=false
grails.plugin.springsecurity.rest.token.storage.memcached.hosts='localhost:11211'
grails.plugin.springsecurity.rest.token.storage.memcached.username=''
grails.plugin.springsecurity.rest.token.storage.memcached.password=''
grails.plugin.springsecurity.rest.token.storage.memcached.expiration=3600
//token generation
grails.plugin.springsecurity.rest.token.generation.useSecureRandom=true
grails.plugin.springsecurity.rest.token.generation.useUUID=false
I making a request on /api/login via Post man rest client with
{
"username": "john.doe",
"password": "dontTellAnybody"
}
json data but it gives me spring security auth page's html in response, Am I doing some wrong configuration?Is there any futher configuration is required.I mentioned that I am using memcache for token storage.Any Idea will be helpfull for me.
Edit: please see the logs file
Edit2 : please check this log file

Mule Facebook Samples Invalid redirect error

I have seen a lot of these errors all over the net with different developer framework
{
"error": {
"message": "Invalid redirect_uri: Given URL is not allowed by the Application configuration.",
"type": "OAuthException",
"code": 191
}
}
I am using Mule ESB to post a comment on a wall but get this error. I have used localhost and the IP address of my PC but nothing seems to work. I am behind a proxy server so not sure if that is the problem. It also seems that Facebook has chaned the UI of the apps page as a lot of sample refer to pages that do not exist anymore.
How do I get my Facebook page to accept my auth and then post using Mule.
Regards.
Jaco.
Have you configured Facebook properly? They tend to change their app system every few months, so any example is usually outdated. The following works with my test app (just tests auth, does not save token):
FB App:
Settings
-> Basic
-> Add Platform
-> App on Facebook
-> Canvas URL: http://localhost:3000/
Mule:
<facebook:config-with-oauth name="Facebook" appId="${id}" appSecret="${secret}" doc:name="Facebook">
<facebook:oauth-callback-config domain="localhost" localPort="3000" remotePort="3000"></facebook:oauth-callback-config>
</facebook:config-with-oauth>
<flow name="authorize">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="3000" path="authorize"></http:inbound-endpoint>
<facebook:authorize config-ref="Facebook"></facebook:authorize>
</flow>
If you have a proxy / port forwarding in your environment, you should add the remotePort option explicitly. I run my Mule inside a virtual machine, and it produces the invalid url error without it.

Loading store data with rest proxy from server in Sencha Touch 2

I have searched around on the forums and read some other posts. However, I'm not sure how exactly to go about this. I have a store with a proxy that I'm trying to load with data from a server. I have tried both jsonp and rest for the type of proxy without luck. In both cases I get a 403 forbidden error. followed by an XMLHTTPRequest cannot load error.
Here's the error that I see in the Chrome console:
Here's my code:
Ext.define('EventsTest.store.Venues', {
extend: 'Ext.data.Store',
requires: [
'Ext.data.proxy.Rest',
],
config: {
storeId: 'venuesStore',
model: 'EventsTest.model.Venue',
proxy: {
type: 'rest',
url: 'http://leo.web/pages/api/',
headers: {
'x-api-key': 'senchaleotestkey'
},
limitParam: false,
pageParam: false,
enablePagingParams: false
/*
extraParams: {
latitude: 45.250157,
longitude: -75.800257,
radius: 5000
}
*/
}
}
});
Security policy in browser and desktop is different so even if it fails in browser it can work in phone. But now the question is how to manage while you are developing the app, for that have a look at this similar question :
How to use json proxy to access remote services during development
Regarding that OPTION request which is getting 403 response, try setting withCredentials : false and useDefaultHeader : false. Details here
http://docs.sencha.com/touch/2-1/#!/api/Ext.data.Operation-cfg-withCredentials
http://docs.sencha.com/touch/2-1/#!/api/Ext.data.Connection-cfg-useDefaultHeader
I would suggest you to read more about CORS if you want to use remote services, you may choose to enable CORS on your server.
You're running your app on a local domain "sencha.test", but you're trying to access data on "leo.web" - the error is that you're trying to load data across domains, which isn't allowed via AJAX.
You say that JSONP doesn't work... why not? Does your server return valid JSONP?