GET request using Azure app services and Intel Edison - rest

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

Related

How to add policy to Keycloak - UI crashes

I'm trying to enable flow when some admin user by some admin client is able to create users and obtain their access tokens to be used for another clients.
I have KeyCloak setup with token exchange and fine grained authz enabled and configured clients. I'm able to login my admin user by REST api, then exchange token. But when I specify audience I got error.
This one returns token but I need token for another client/audience.
http -f POST https://my-keycloak-server.com/auth/admin/realms/my-realm/protocol/openid-connect/token grant_type=urn:ietf:params:oauth:grant-type:token-exchange requested_subject=1a147915-53fe-454d-906a-186fecfa6974 client_id=api-admin client_secret=23a4ecbe-a9e8-448c-b36a-a45fa1082e6e subject_token=eyJhbGeiOiJSUzI1NiIs......
This one is failing with error.
http -f POST https://my-keycloak-server.com/auth/admin/realms/my-realm/protocol/openid-connect/token grant_type=urn:ietf:params:oauth:grant-type:token-exchange requested_subject=1a147915-53fe-454d-906a-186fecfa6974 client_id=api-admin client_secret=23a4ecbe-a9e8-448c-b36a-a45fa1082e6e subject_token=eyJhbGeiOiJSUzI1NiIs...... audience=my-another-client
{
"error": "access_denied",
"error_description": "Client not allowed to exchange"
}
So I tried to setup fine grained auth for target audience client (enabled it in tab, then tried to add policy for my admin user to be able to exchange token) but when I want to add policy that will allow my admin user to perform token exchange I'm stuck on UI error.
When typing policy name I got 404 when Keycloak is looking for name colisions. Afaik 404 in this case shouldn't block form from posting because it is no name collision. Instead I got instantly redirected with error.
https://my-keycloak-server.com/auth/admin/realms/my-realm/clients/1bafa9a4-f7e2-422c-9188-58ea95db32ef/authz/resource-server/policy/search?name=some-name
In the end of the day I can't add any policy in Keycloak. All the time form validation is ending up with crash caused by 404 policy name not found.
I'm using dockerized keycloak 10.0.0
Any ideas?
I hacked it by live editing Angular JS UI script function that performs verification in line 2403.
this.checkNameAvailability = function (onSuccess) {
if (!$scope.policy.name || $scope.policy.name.trim().length == 0) {
return;
}
ResourceServerPolicy.search({
realm: $route.current.params.realm,
client: client.id,
name: $scope.policy.name
}, function(data) {
if (data && data.id && data.id != $scope.policy.id) {
Notifications.error("Name already in use by another policy or permission, please choose another one.");
} else {
onSuccess();
}
});
}
to
this.checkNameAvailability = function (onSuccess) {
onSuccess();
}
And that end up with successfuly added policy. Still looks like it's UI bug.

Robot Framework api test with OAUTH2 Authorization Request Header

I am trying to use the RequestsLibrary on an api thats using the OAUTH2 authentication.
Authentication is via OAUTH2 with credentials being supplied to the /v1/authtoken endpoint.
Subsequent calls to the APÍ need to have the token included as a ‘bearer’ in the ‘Authorization’ header of the http requests.
So below is the test case. The error I am getting is:
401 != 200
The credentials work ok in jmeter and a list of accounts is returned. However, I am not able to get the RF script work. Any help will be appreciated.
In the script,
Log to Console ${accessToken} returns the access token: 8ETFXTZOWQLrgsMj7c_KuCEeypdj-eO1r...
Log to Console ${token} returns: Bearer 8ETFXTZOWQLrgsMj7c_KuCEeypdj-eO1r...
*** Test Cases ***
Get authToken
Create Session hook http://xxxx.azurewebsites.net verify=${True}
${data}= Create Dictionary grant_type=client_credentials client_id=yyy-zzzz client_secret=xxxxxxxxxxxxxxx
${headers}= Create Dictionary Content-Type=application/x-www-form-urlencoded
${resp}= post request hook /v1/authtoken data=${data} headers=${headers}
Should Be Equal As Strings ${resp.status_code} 200
Dictionary Should Contain Value ${resp.json()} bearer
${accessToken}= evaluate $resp.json().get("access_token")
Log to Console ${accessToken}
${Bearer}= Set Variable Bearer
${token}= catenate Bearer ${accessToken}
Log to Console ${token}
${headers}= Create Dictionary Authorization=${token}
${resp1}= get request hook /v1/integration/accounts headers=${headers}
Should Be Equal As Strings ${resp1.status_code} 200
#Log to Console ${resp1.json()}
I am using OAuth 2.0 authentication as well for my salesforce automation.
My first answer would be to skip client based authentication and switch to username/password based authentication
Get authToken by Password Authentication
RequestsLibrary.Create Session hook https://<url>/services/oauth2 verify=${True}
${data}= Create Dictionary grant_type=password client_id=1abc client_secret=2abc username=test#test.com password=keypass
${headers}= Create Dictionary Content-Type=application/x-www-form-urlencoded
${resp}= RequestsLibrary.Post Request hook /token data=${data} headers=${headers}
Should Be Equal As Strings ${resp.status_code} 200
${accessToken}= evaluate $resp.json().get("access_token")
Log to Console ${accessToken}
If you are using client based or web based authentication, there will be a login screen that will be used by the user to enter their username/password to authorise the app to send requests on its behalf. Have a look at these pages for more information as they primarily discuss about using either refresh tokens or skipping the user prompt altogether.
Why does Google OAuth2 re-ask user for permission when i send them to auth url again
https://salesforce.stackexchange.com/questions/785/authenticate-3rd-party-application-with-oauth2
I have added the new answer for this question.
RequestsLibrary.Create Session OA2 <Your Server URL> verify=${True}
${data}= Create Dictionary Token_Name=TestTokenname grant_type=<grant type> client_Id=<your Id> Client_Secret=<Your client secret> scope=<your scpe>
${headers}= Create Dictionary Content-Type=application/x-www-form-urlencoded
${resp}= RequestsLibrary.Post Request OA2 identity/connect/token data=${data} headers=${headers}
BuiltIn.Log To Console ${resp}
BuiltIn.Log To Console ${resp.status_code}
Should Be Equal As Strings ${resp.status_code} 200
Dictionary Should Contain Value ${resp.json()} Testtokenname
${accessToken}= evaluate $resp.json().get("access_token")
BuiltIn.Log to Console ${accessToken}
${token}= catenate Bearer ${accessToken}
BuiltIn.Log to Console ${token}
${headers1}= Create Dictionary Authorization=${token}
RequestsLibrary.Create Session GT <Your Server URL> verify=${True}
${resp}= RequestsLibrary.Get Request GT <Your API URL> headers=${headers1}
Should Be Equal As Strings ${resp.status_code} 200

production build of ember app works, but when using ember serve, cookies not sent to api

I have a rest API running on localhost:8001/my_app/api/, and I have apache setup to reverse proxy it from localhost/my_app/api. That's working fine.
In order to have permissions to do anything with the api, it requires my session cookie, my csrftoken cookie and a X-CSRFToken HTTP header. I've configured adapters/application.js as follows:
adapters/application.js
import Ember from 'ember';
import DRFAdapter from './drf';
export default DRFAdapter.extend({
headers: Ember.computed(function() {
return {
'X-CSRFToken': Ember.get(document.cookie.match(/csrftoken\=([^;]*)/), '1'),
};
}).volatile(),
ajax: function(url, method, hash) {
hash = hash || {}; // hash may be undefined
hash.crossDomain = true;
hash.xhrFields = {withCredentials: true};
return this._super(url, method, hash);
}
});
If I do a ember build -prod and copy the contents of the dist dir to /var/www/myApp/, apache serves my app, and it works just fine.
It's when I try to use ember-cli's builtin development server where I run into problems. I'm getting 403 errors from my api. It turns out that while the X-CSRFToken header is being sent neither of my cookies are. If I look in my chrome developer tools, it shows that I have both cookies - they simply aren't in the request headers. They're both from localhost, so I'm a bit confused.
Also, I currently I have CORS on my rest backend setup. Here are the headers I'm currently receiving:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:4200
I thought that since allow-credentials == true and allow-origin != * that cookies were supposed to be allowed. sigh.
Here's my API_HOST and contentSecurityPolicy:
config/environment.js
if (environment === 'development') {
ENV.APP.LOG_TRANSITIONS = true;
ENV.APP.API_HOST = "http://localhost"
ENV.contentSecurityPolicy = {
'default-src': "'none'",
'script-src': "'self' 'unsafe-eval' localhost",
'font-src': "'self'",
'connect-src': "'self' localhost",
'img-src': "'self'",
'style-src': "'self'",
'media-src': "'self'"
};
}
As you can see above, the api requests are being sent through my reverse proxy. I've played around with ember serve --proxy trying both http://localhost:80/ and http://localhost:8001/ but neither have helped. I've also tried setting my development ENV.API_HOST = 'http://localhost:8001/'; with and without the various proxy values.
This edit, build, deploy, refresh my browser, test, & repeat process is REALLY slow and getting old REALLY fast.
Could someone please explain to me how to get the ember-cli development server to properly access my rest api?

JENKINS Authentication Fails

I am getting the following error while trying to trigger Jenkins job from any REST Client
Authentication required
<!-- You are authenticated as: anonymous
Groups that you are in:
Permission you need to have (but didn't):
hudson.model.Hudson.Read
... which is implied by: hudson.security.Permission.GenericRead
... which is implied by: hudson.model.Hudson.Administer
-->
</body> </html>
The request is getting triggered while using curl from terminal
I am using the following syntax
http://user:apiToken#jenkins.yourcompany.com/job/your_job/build?token=TOKEN
[ref :https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clients]
ie. curl -X POST http://user:apiToken#jenkins.yourcompany.com/job/your_job/build?token=TOKEN
Check this "This build is parameterized " , select the credentials parameter from drop down.
Use this
curl -X POST http://jenkins.rtcamp.com/job/Snapbox/buildWithParameters --user "username:password"
It solved my authentication problem.
I hope it will help others too.
My development team's configuration settings were matrix-based security so I had to find my group and give my group workspace access.
1.Click on Manage Jenkins .
2.Click on Configure Global Security .
3.in matrix-based security change:
Overall - Read
Job - Build
Job - Read
Job - Workspace
Then
POST jobUrl/buildWithParameters HTTP/1.1
Host: user:token
Authorization: Basic dWdlbmxpazo4elhjdmJuTQ==
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Branch=develop
For me
https://user:password#jenkins.mycompany.org/job/job_name/build?token=my_token
in https://jenkins.mycompany.org/configureSecurity
disable CORS
hope this help
Try using the -u parameter to specify the credentials:
curl -u user:apiToken -X POST http://jenkins.yourcompany.com/job/your_job/build?token=TOKEN
I provided header Authorization parameter with value :
BASIC base_64encoded(username:password) and it worked fine.
Authorization Basic bmltbWljdjpqZX*********
Simply disable "CSRF Protection" in the global Security Options, because those URLs don't send post data identification.
focal point :
username:password#
curl -u user:apiToken -X POST http://username:password#jenkins.yourcompany.com/job/your_job/build?key1=value1&key2=value2 ...
If you are encountering this problem with jenkins api client in ruby.
I figured Jenkins is blocking all the get request, instead use api_post_request.
Also, you have to generate api token because normal password is not working anymore.
#client = JenkinsApi::Client.new(
server_url: "",
username: '',
password: ""
)
SITE_FILE_PATH = 'artifact/target/site'.freeze
#jenkins_uri=''
#jenkins_job_name=''
def latest_test_file_path
"/job/#{#jenkins_job_name}/job/master/lastSuccessfulBuild/#{SITE_FILE_PATH}/Test-Results/test-results.html"
end
puts #client.api_post_request(latest_test_file_path,{},true).body
you can set the parameter true if you want the raw response.
default parameter or passing false will just return response code.
Also make sure to construct the right prefix.
You can refer to the above snipped.

Update issue journals of redmine through Rest API

I need to create new notes in existent issues of Redmine. It will be better that this can be accomplished through the Rest API, but i'm open to other solutions.
In some parts of the doc it seems to be possible, but in others it's written (soon) as if it does not be implemented jet.
I found this post asking the same, but without response.
I've already try it and in the log appear:
Processing IssuesController#update to json (for 127.0.0.1 at
2012-01-12 16:07:03) [PUT] Parameters: {"format"=>"json",
"action"=>"update", "id"=>"8", "controller"=>"issues"} Completed in
34ms (View: 0, DB: 4) | 200 OK [http://localhost/issues/8.json]
But it's not really updated. I'm using this command to make the request
curl -v -H "Content-Type:text.json" -X PUT --data "#/tmp/8.json" -u admin:admin http://localhost:3000/issues/8.json
and the content of 8.json is:
{
"issue": {
"subject": "subject123",
"notes":"funciona el rest"
}
}
I thing that annoys me is that i'm using port 3000 but it seems to be ignored in the log response.
That JSON should work. You don't want to work with the journals themselves, you want to update the issue and add a new note. That way Redmine will create the journal for you.
Is the subject getting updated? Do you have the REST API enabled? Is the admin account allowed to update that issue?
You can also try putting the notes outside of the issues object:
{
"issue": {
"subject": "subject123"
},
"notes":"funciona el rest"
}